]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 7 Feb 2026 15:02:19 +0000 (16:02 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 7 Feb 2026 15:02:19 +0000 (16:02 +0100)
added patches:
alsa-aloop-fix-racy-access-at-pcm-trigger.patch
arm-9468-1-fix-memset64-on-big-endian.patch
ceph-fix-null-pointer-dereference-in-ceph_mds_auth_match.patch
ceph-fix-oops-due-to-invalid-pointer-for-kfree-in-parse_longname.patch
gve-correct-ethtool-rx_dropped-calculation.patch
gve-fix-stats-report-corruption-on-queue-count-change.patch
mm-shmem-prevent-infinite-loop-on-truncate-race.patch
mm-slab-add-alloc_tagging_slab_free_hook-for-memcg_alloc_abort_single.patch
platform-x86-intel_telemetry-fix-swapped-arrays-in-pss-output.patch
pmdomain-imx-gpcv2-fix-the-imx8mm-gpu-hang-due-to-wrong-adb400-reset.patch
pmdomain-imx8m-blk-ctrl-fix-out-of-range-access-of-bc-domains.patch
pmdomain-imx8mp-blk-ctrl-keep-gpc-power-domain-on-for-system-wakeup.patch
pmdomain-imx8mp-blk-ctrl-keep-usb-phy-power-domain-on-for-system-wakeup.patch
pmdomain-qcom-rpmpd-fix-off-by-one-error-in-clamping-to-the-highest-state.patch
rbd-check-for-eod-after-exclusive-lock-is-ensured-to-be-held.patch
revert-drm-amd-check-if-aspm-is-enabled-from-pcie-subsystem.patch
x86-kfence-fix-booting-on-32bit-non-pae-systems.patch
x86-vmware-fix-hypercall-clobbers.patch

19 files changed:
queue-6.12/alsa-aloop-fix-racy-access-at-pcm-trigger.patch [new file with mode: 0644]
queue-6.12/arm-9468-1-fix-memset64-on-big-endian.patch [new file with mode: 0644]
queue-6.12/ceph-fix-null-pointer-dereference-in-ceph_mds_auth_match.patch [new file with mode: 0644]
queue-6.12/ceph-fix-oops-due-to-invalid-pointer-for-kfree-in-parse_longname.patch [new file with mode: 0644]
queue-6.12/gve-correct-ethtool-rx_dropped-calculation.patch [new file with mode: 0644]
queue-6.12/gve-fix-stats-report-corruption-on-queue-count-change.patch [new file with mode: 0644]
queue-6.12/mm-shmem-prevent-infinite-loop-on-truncate-race.patch [new file with mode: 0644]
queue-6.12/mm-slab-add-alloc_tagging_slab_free_hook-for-memcg_alloc_abort_single.patch [new file with mode: 0644]
queue-6.12/platform-x86-intel_telemetry-fix-swapped-arrays-in-pss-output.patch [new file with mode: 0644]
queue-6.12/pmdomain-imx-gpcv2-fix-the-imx8mm-gpu-hang-due-to-wrong-adb400-reset.patch [new file with mode: 0644]
queue-6.12/pmdomain-imx8m-blk-ctrl-fix-out-of-range-access-of-bc-domains.patch [new file with mode: 0644]
queue-6.12/pmdomain-imx8mp-blk-ctrl-keep-gpc-power-domain-on-for-system-wakeup.patch [new file with mode: 0644]
queue-6.12/pmdomain-imx8mp-blk-ctrl-keep-usb-phy-power-domain-on-for-system-wakeup.patch [new file with mode: 0644]
queue-6.12/pmdomain-qcom-rpmpd-fix-off-by-one-error-in-clamping-to-the-highest-state.patch [new file with mode: 0644]
queue-6.12/rbd-check-for-eod-after-exclusive-lock-is-ensured-to-be-held.patch [new file with mode: 0644]
queue-6.12/revert-drm-amd-check-if-aspm-is-enabled-from-pcie-subsystem.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/x86-kfence-fix-booting-on-32bit-non-pae-systems.patch [new file with mode: 0644]
queue-6.12/x86-vmware-fix-hypercall-clobbers.patch [new file with mode: 0644]

diff --git a/queue-6.12/alsa-aloop-fix-racy-access-at-pcm-trigger.patch b/queue-6.12/alsa-aloop-fix-racy-access-at-pcm-trigger.patch
new file mode 100644 (file)
index 0000000..b89d05d
--- /dev/null
@@ -0,0 +1,117 @@
+From 826af7fa62e347464b1b4e0ba2fe19a92438084f Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 3 Feb 2026 15:09:59 +0100
+Subject: ALSA: aloop: Fix racy access at PCM trigger
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 826af7fa62e347464b1b4e0ba2fe19a92438084f upstream.
+
+The PCM trigger callback of aloop driver tries to check the PCM state
+and stop the stream of the tied substream in the corresponding cable.
+Since both check and stop operations are performed outside the cable
+lock, this may result in UAF when a program attempts to trigger
+frequently while opening/closing the tied stream, as spotted by
+fuzzers.
+
+For addressing the UAF, this patch changes two things:
+- It covers the most of code in loopback_check_format() with
+  cable->lock spinlock, and add the proper NULL checks.  This avoids
+  already some racy accesses.
+- In addition, now we try to check the state of the capture PCM stream
+  that may be stopped in this function, which was the major pain point
+  leading to UAF.
+
+Reported-by: syzbot+5f8f3acdee1ec7a7ef7b@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/69783ba1.050a0220.c9109.0011.GAE@google.com
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20260203141003.116584-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/drivers/aloop.c |   62 +++++++++++++++++++++++++++++---------------------
+ 1 file changed, 36 insertions(+), 26 deletions(-)
+
+--- a/sound/drivers/aloop.c
++++ b/sound/drivers/aloop.c
+@@ -335,37 +335,43 @@ static bool is_access_interleaved(snd_pc
+ static int loopback_check_format(struct loopback_cable *cable, int stream)
+ {
++      struct loopback_pcm *dpcm_play, *dpcm_capt;
+       struct snd_pcm_runtime *runtime, *cruntime;
+       struct loopback_setup *setup;
+       struct snd_card *card;
++      bool stop_capture = false;
+       int check;
+-      if (cable->valid != CABLE_VALID_BOTH) {
+-              if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+-                      goto __notify;
+-              return 0;
+-      }
+-      runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
+-                                                      substream->runtime;
+-      cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
+-                                                      substream->runtime;
+-      check = runtime->format != cruntime->format ||
+-              runtime->rate != cruntime->rate ||
+-              runtime->channels != cruntime->channels ||
+-              is_access_interleaved(runtime->access) !=
+-              is_access_interleaved(cruntime->access);
+-      if (!check)
+-              return 0;
+-      if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+-              return -EIO;
+-      } else {
+-              snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
+-                                      substream, SNDRV_PCM_STATE_DRAINING);
+-            __notify:
+-              runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
+-                                                      substream->runtime;
+-              setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
+-              card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
++      scoped_guard(spinlock_irqsave, &cable->lock) {
++              dpcm_play = cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
++              dpcm_capt = cable->streams[SNDRV_PCM_STREAM_CAPTURE];
++
++              if (cable->valid != CABLE_VALID_BOTH) {
++                      if (stream == SNDRV_PCM_STREAM_CAPTURE || !dpcm_play)
++                              return 0;
++              } else {
++                      if (!dpcm_play || !dpcm_capt)
++                              return -EIO;
++                      runtime = dpcm_play->substream->runtime;
++                      cruntime = dpcm_capt->substream->runtime;
++                      if (!runtime || !cruntime)
++                              return -EIO;
++                      check = runtime->format != cruntime->format ||
++                      runtime->rate != cruntime->rate ||
++                      runtime->channels != cruntime->channels ||
++                      is_access_interleaved(runtime->access) !=
++                      is_access_interleaved(cruntime->access);
++                      if (!check)
++                              return 0;
++                      if (stream == SNDRV_PCM_STREAM_CAPTURE)
++                              return -EIO;
++                      else if (cruntime->state == SNDRV_PCM_STATE_RUNNING)
++                              stop_capture = true;
++              }
++
++              setup = get_setup(dpcm_play);
++              card = dpcm_play->loopback->card;
++              runtime = dpcm_play->substream->runtime;
+               if (setup->format != runtime->format) {
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                                       &setup->format_id);
+@@ -388,6 +394,10 @@ static int loopback_check_format(struct
+                       setup->access = runtime->access;
+               }
+       }
++
++      if (stop_capture)
++              snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING);
++
+       return 0;
+ }
diff --git a/queue-6.12/arm-9468-1-fix-memset64-on-big-endian.patch b/queue-6.12/arm-9468-1-fix-memset64-on-big-endian.patch
new file mode 100644 (file)
index 0000000..665d71a
--- /dev/null
@@ -0,0 +1,40 @@
+From 23ea2a4c72323feb6e3e025e8a6f18336513d5ad Mon Sep 17 00:00:00 2001
+From: Thomas Weissschuh <thomas.weissschuh@linutronix.de>
+Date: Wed, 7 Jan 2026 11:01:49 +0100
+Subject: ARM: 9468/1: fix memset64() on big-endian
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weissschuh <thomas.weissschuh@linutronix.de>
+
+commit 23ea2a4c72323feb6e3e025e8a6f18336513d5ad upstream.
+
+On big-endian systems the 32-bit low and high halves need to be swapped
+for the underlying assembly implementation to work correctly.
+
+Fixes: fd1d362600e2 ("ARM: implement memset32 & memset64")
+Cc: stable@vger.kernel.org
+Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Reviewed-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm/include/asm/string.h |    5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/include/asm/string.h
++++ b/arch/arm/include/asm/string.h
+@@ -42,7 +42,10 @@ static inline void *memset32(uint32_t *p
+ extern void *__memset64(uint64_t *, uint32_t low, __kernel_size_t, uint32_t hi);
+ static inline void *memset64(uint64_t *p, uint64_t v, __kernel_size_t n)
+ {
+-      return __memset64(p, v, n * 8, v >> 32);
++      if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN))
++              return __memset64(p, v, n * 8, v >> 32);
++      else
++              return __memset64(p, v >> 32, n * 8, v);
+ }
+ /*
diff --git a/queue-6.12/ceph-fix-null-pointer-dereference-in-ceph_mds_auth_match.patch b/queue-6.12/ceph-fix-null-pointer-dereference-in-ceph_mds_auth_match.patch
new file mode 100644 (file)
index 0000000..1795a3a
--- /dev/null
@@ -0,0 +1,182 @@
+From 7987cce375ac8ce98e170a77aa2399f2cf6eb99f Mon Sep 17 00:00:00 2001
+From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Date: Tue, 3 Feb 2026 14:54:46 -0800
+Subject: ceph: fix NULL pointer dereference in ceph_mds_auth_match()
+
+From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+
+commit 7987cce375ac8ce98e170a77aa2399f2cf6eb99f upstream.
+
+The CephFS kernel client has regression starting from 6.18-rc1.
+We have issue in ceph_mds_auth_match() if fs_name == NULL:
+
+    const char fs_name = mdsc->fsc->mount_options->mds_namespace;
+    ...
+    if (auth->match.fs_name && strcmp(auth->match.fs_name, fs_name)) {
+            / fsname mismatch, try next one */
+            return 0;
+    }
+
+Patrick Donnelly suggested that: In summary, we should definitely start
+decoding `fs_name` from the MDSMap and do strict authorizations checks
+against it. Note that the `-o mds_namespace=foo` should only be used for
+selecting the file system to mount and nothing else. It's possible
+no mds_namespace is specified but the kernel will mount the only
+file system that exists which may have name "foo".
+
+This patch reworks ceph_mdsmap_decode() and namespace_equals() with
+the goal of supporting the suggested concept. Now struct ceph_mdsmap
+contains m_fs_name field that receives copy of extracted FS name
+by ceph_extract_encoded_string(). For the case of "old" CephFS file
+systems, it is used "cephfs" name.
+
+[ idryomov: replace redundant %*pE with %s in ceph_mdsmap_decode(),
+  get rid of a series of strlen() calls in ceph_namespace_match(),
+  drop changes to namespace_equals() body to avoid treating empty
+  mds_namespace as equal, drop changes to ceph_mdsc_handle_fsmap()
+  as namespace_equals() isn't an equivalent substitution there ]
+
+Cc: stable@vger.kernel.org
+Fixes: 22c73d52a6d0 ("ceph: fix multifs mds auth caps issue")
+Link: https://tracker.ceph.com/issues/73886
+Signed-off-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Reviewed-by: Patrick Donnelly <pdonnell@ibm.com>
+Tested-by: Patrick Donnelly <pdonnell@ibm.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/mds_client.c         |    5 +++--
+ fs/ceph/mdsmap.c             |   26 +++++++++++++++++++-------
+ fs/ceph/mdsmap.h             |    1 +
+ fs/ceph/super.h              |   16 ++++++++++++++--
+ include/linux/ceph/ceph_fs.h |    6 ++++++
+ 5 files changed, 43 insertions(+), 11 deletions(-)
+
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -5652,7 +5652,7 @@ static int ceph_mds_auth_match(struct ce
+       u32 caller_uid = from_kuid(&init_user_ns, cred->fsuid);
+       u32 caller_gid = from_kgid(&init_user_ns, cred->fsgid);
+       struct ceph_client *cl = mdsc->fsc->client;
+-      const char *fs_name = mdsc->fsc->mount_options->mds_namespace;
++      const char *fs_name = mdsc->mdsmap->m_fs_name;
+       const char *spath = mdsc->fsc->mount_options->server_path;
+       bool gid_matched = false;
+       u32 gid, tlen, len;
+@@ -5660,7 +5660,8 @@ static int ceph_mds_auth_match(struct ce
+       doutc(cl, "fsname check fs_name=%s  match.fs_name=%s\n",
+             fs_name, auth->match.fs_name ? auth->match.fs_name : "");
+-      if (auth->match.fs_name && strcmp(auth->match.fs_name, fs_name)) {
++
++      if (!ceph_namespace_match(auth->match.fs_name, fs_name)) {
+               /* fsname mismatch, try next one */
+               return 0;
+       }
+--- a/fs/ceph/mdsmap.c
++++ b/fs/ceph/mdsmap.c
+@@ -353,22 +353,33 @@ struct ceph_mdsmap *ceph_mdsmap_decode(s
+               __decode_and_drop_type(p, end, u8, bad_ext);
+       }
+       if (mdsmap_ev >= 8) {
+-              u32 fsname_len;
++              size_t fsname_len;
++
+               /* enabled */
+               ceph_decode_8_safe(p, end, m->m_enabled, bad_ext);
++
+               /* fs_name */
+-              ceph_decode_32_safe(p, end, fsname_len, bad_ext);
++              m->m_fs_name = ceph_extract_encoded_string(p, end,
++                                                         &fsname_len,
++                                                         GFP_NOFS);
++              if (IS_ERR(m->m_fs_name)) {
++                      m->m_fs_name = NULL;
++                      goto nomem;
++              }
+               /* validate fsname against mds_namespace */
+-              if (!namespace_equals(mdsc->fsc->mount_options, *p,
++              if (!namespace_equals(mdsc->fsc->mount_options, m->m_fs_name,
+                                     fsname_len)) {
+-                      pr_warn_client(cl, "fsname %*pE doesn't match mds_namespace %s\n",
+-                                     (int)fsname_len, (char *)*p,
++                      pr_warn_client(cl, "fsname %s doesn't match mds_namespace %s\n",
++                                     m->m_fs_name,
+                                      mdsc->fsc->mount_options->mds_namespace);
+                       goto bad;
+               }
+-              /* skip fsname after validation */
+-              ceph_decode_skip_n(p, end, fsname_len, bad);
++      } else {
++              m->m_enabled = false;
++              m->m_fs_name = kstrdup(CEPH_OLD_FS_NAME, GFP_NOFS);
++              if (!m->m_fs_name)
++                      goto nomem;
+       }
+       /* damaged */
+       if (mdsmap_ev >= 9) {
+@@ -430,6 +441,7 @@ void ceph_mdsmap_destroy(struct ceph_mds
+               kfree(m->m_info);
+       }
+       kfree(m->m_data_pg_pools);
++      kfree(m->m_fs_name);
+       kfree(m);
+ }
+--- a/fs/ceph/mdsmap.h
++++ b/fs/ceph/mdsmap.h
+@@ -45,6 +45,7 @@ struct ceph_mdsmap {
+       bool m_enabled;
+       bool m_damaged;
+       int m_num_laggy;
++      char *m_fs_name;
+ };
+ static inline struct ceph_entity_addr *
+--- a/fs/ceph/super.h
++++ b/fs/ceph/super.h
+@@ -104,14 +104,26 @@ struct ceph_mount_options {
+       struct fscrypt_dummy_policy dummy_enc_policy;
+ };
++#define CEPH_NAMESPACE_WILDCARD               "*"
++
++static inline bool ceph_namespace_match(const char *pattern,
++                                      const char *target)
++{
++      if (!pattern || !pattern[0] ||
++          !strcmp(pattern, CEPH_NAMESPACE_WILDCARD))
++              return true;
++
++      return !strcmp(pattern, target);
++}
++
+ /*
+  * Check if the mds namespace in ceph_mount_options matches
+  * the passed in namespace string. First time match (when
+  * ->mds_namespace is NULL) is treated specially, since
+  * ->mds_namespace needs to be initialized by the caller.
+  */
+-static inline int namespace_equals(struct ceph_mount_options *fsopt,
+-                                 const char *namespace, size_t len)
++static inline bool namespace_equals(struct ceph_mount_options *fsopt,
++                                  const char *namespace, size_t len)
+ {
+       return !(fsopt->mds_namespace &&
+                (strlen(fsopt->mds_namespace) != len ||
+--- a/include/linux/ceph/ceph_fs.h
++++ b/include/linux/ceph/ceph_fs.h
+@@ -31,6 +31,12 @@
+ #define CEPH_INO_CEPH   2            /* hidden .ceph dir */
+ #define CEPH_INO_GLOBAL_SNAPREALM  3 /* global dummy snaprealm */
++/*
++ * name for "old" CephFS file systems,
++ * see ceph.git e2b151d009640114b2565c901d6f41f6cd5ec652
++ */
++#define CEPH_OLD_FS_NAME      "cephfs"
++
+ /* arbitrary limit on max # of monitors (cluster of 3 is typical) */
+ #define CEPH_MAX_MON   31
diff --git a/queue-6.12/ceph-fix-oops-due-to-invalid-pointer-for-kfree-in-parse_longname.patch b/queue-6.12/ceph-fix-oops-due-to-invalid-pointer-for-kfree-in-parse_longname.patch
new file mode 100644 (file)
index 0000000..87297b1
--- /dev/null
@@ -0,0 +1,67 @@
+From bc8dedae022ce3058659c3addef3ec4b41d15e00 Mon Sep 17 00:00:00 2001
+From: Daniel Vogelbacher <daniel@chaospixel.com>
+Date: Sun, 1 Feb 2026 09:34:01 +0100
+Subject: ceph: fix oops due to invalid pointer for kfree() in parse_longname()
+
+From: Daniel Vogelbacher <daniel@chaospixel.com>
+
+commit bc8dedae022ce3058659c3addef3ec4b41d15e00 upstream.
+
+This fixes a kernel oops when reading ceph snapshot directories (.snap),
+for example by simply running `ls /mnt/my_ceph/.snap`.
+
+The variable str is guarded by __free(kfree), but advanced by one for
+skipping the initial '_' in snapshot names. Thus, kfree() is called
+with an invalid pointer.  This patch removes the need for advancing the
+pointer so kfree() is called with correct memory pointer.
+
+Steps to reproduce:
+
+1. Create snapshots on a cephfs volume (I've 63 snaps in my testcase)
+
+2. Add cephfs mount to fstab
+$ echo "samba-fileserver@.files=/volumes/datapool/stuff/3461082b-ecc9-4e82-8549-3fd2590d3fb6      /mnt/test/stuff   ceph     acl,noatime,_netdev    0       0" >> /etc/fstab
+
+3. Reboot the system
+$ systemctl reboot
+
+4. Check if it's really mounted
+$ mount | grep stuff
+
+5. List snapshots (expected 63 snapshots on my system)
+$ ls /mnt/test/stuff/.snap
+
+Now ls hangs forever and the kernel log shows the oops.
+
+Cc: stable@vger.kernel.org
+Fixes: 101841c38346 ("[ceph] parse_longname(): strrchr() expects NUL-terminated string")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220807
+Suggested-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Daniel Vogelbacher <daniel@chaospixel.com>
+Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ceph/crypto.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/fs/ceph/crypto.c
++++ b/fs/ceph/crypto.c
+@@ -217,12 +217,13 @@ static struct inode *parse_longname(cons
+       struct ceph_vino vino = { .snap = CEPH_NOSNAP };
+       char *name_end, *inode_number;
+       int ret = -EIO;
+-      /* NUL-terminate */
+-      char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL);
++      /* Snapshot name must start with an underscore */
++      if (*name_len <= 0 || name[0] != '_')
++              return ERR_PTR(-EIO);
++      /* Skip initial '_' and NUL-terminate */
++      char *str __free(kfree) = kmemdup_nul(name + 1, *name_len - 1, GFP_KERNEL);
+       if (!str)
+               return ERR_PTR(-ENOMEM);
+-      /* Skip initial '_' */
+-      str++;
+       name_end = strrchr(str, '_');
+       if (!name_end) {
+               doutc(cl, "failed to parse long snapshot name: %s\n", str);
diff --git a/queue-6.12/gve-correct-ethtool-rx_dropped-calculation.patch b/queue-6.12/gve-correct-ethtool-rx_dropped-calculation.patch
new file mode 100644 (file)
index 0000000..efe8610
--- /dev/null
@@ -0,0 +1,111 @@
+From c7db85d579a1dccb624235534508c75fbf2dfe46 Mon Sep 17 00:00:00 2001
+From: Max Yuan <maxyuan@google.com>
+Date: Mon, 2 Feb 2026 19:39:25 +0000
+Subject: gve: Correct ethtool rx_dropped calculation
+
+From: Max Yuan <maxyuan@google.com>
+
+commit c7db85d579a1dccb624235534508c75fbf2dfe46 upstream.
+
+The gve driver's "rx_dropped" statistic, exposed via `ethtool -S`,
+incorrectly includes `rx_buf_alloc_fail` counts. These failures
+represent an inability to allocate receive buffers, not true packet
+drops where a received packet is discarded. This misrepresentation can
+lead to inaccurate diagnostics.
+
+This patch rectifies the ethtool "rx_dropped" calculation. It removes
+`rx_buf_alloc_fail` from the total and adds `xdp_tx_errors` and
+`xdp_redirect_errors`, which represent legitimate packet drops within
+the XDP path.
+
+Cc: stable@vger.kernel.org
+Fixes: 433e274b8f7b ("gve: Add stats for gve.")
+Signed-off-by: Max Yuan <maxyuan@google.com>
+Reviewed-by: Jordan Rhee <jordanrhee@google.com>
+Reviewed-by: Joshua Washington <joshwash@google.com>
+Reviewed-by: Matt Olson <maolson@google.com>
+Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260202193925.3106272-3-hramamurthy@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/google/gve/gve_ethtool.c |   23 +++++++++++++++++------
+ 1 file changed, 17 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
+@@ -152,10 +152,11 @@ gve_get_ethtool_stats(struct net_device
+       u64 tmp_rx_pkts, tmp_rx_hsplit_pkt, tmp_rx_bytes, tmp_rx_hsplit_bytes,
+               tmp_rx_skb_alloc_fail, tmp_rx_buf_alloc_fail,
+               tmp_rx_desc_err_dropped_pkt, tmp_rx_hsplit_unsplit_pkt,
+-              tmp_tx_pkts, tmp_tx_bytes;
++              tmp_tx_pkts, tmp_tx_bytes,
++              tmp_xdp_tx_errors, tmp_xdp_redirect_errors;
+       u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt,
+               rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes,
+-              tx_dropped;
++              tx_dropped, xdp_tx_errors, xdp_redirect_errors;
+       int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx;
+       int stats_idx, stats_region_len, nic_stats_len;
+       struct stats *report_stats;
+@@ -199,6 +200,7 @@ gve_get_ethtool_stats(struct net_device
+       for (rx_pkts = 0, rx_bytes = 0, rx_hsplit_pkt = 0,
+            rx_skb_alloc_fail = 0, rx_buf_alloc_fail = 0,
+            rx_desc_err_dropped_pkt = 0, rx_hsplit_unsplit_pkt = 0,
++           xdp_tx_errors = 0, xdp_redirect_errors = 0,
+            ring = 0;
+            ring < priv->rx_cfg.num_queues; ring++) {
+               if (priv->rx) {
+@@ -216,6 +218,9 @@ gve_get_ethtool_stats(struct net_device
+                                       rx->rx_desc_err_dropped_pkt;
+                               tmp_rx_hsplit_unsplit_pkt =
+                                       rx->rx_hsplit_unsplit_pkt;
++                              tmp_xdp_tx_errors = rx->xdp_tx_errors;
++                              tmp_xdp_redirect_errors =
++                                      rx->xdp_redirect_errors;
+                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                                                      start));
+                       rx_pkts += tmp_rx_pkts;
+@@ -225,6 +230,8 @@ gve_get_ethtool_stats(struct net_device
+                       rx_buf_alloc_fail += tmp_rx_buf_alloc_fail;
+                       rx_desc_err_dropped_pkt += tmp_rx_desc_err_dropped_pkt;
+                       rx_hsplit_unsplit_pkt += tmp_rx_hsplit_unsplit_pkt;
++                      xdp_tx_errors += tmp_xdp_tx_errors;
++                      xdp_redirect_errors += tmp_xdp_redirect_errors;
+               }
+       }
+       for (tx_pkts = 0, tx_bytes = 0, tx_dropped = 0, ring = 0;
+@@ -250,8 +257,8 @@ gve_get_ethtool_stats(struct net_device
+       data[i++] = rx_bytes;
+       data[i++] = tx_bytes;
+       /* total rx dropped packets */
+-      data[i++] = rx_skb_alloc_fail + rx_buf_alloc_fail +
+-                  rx_desc_err_dropped_pkt;
++      data[i++] = rx_skb_alloc_fail + rx_desc_err_dropped_pkt +
++                  xdp_tx_errors + xdp_redirect_errors;
+       data[i++] = tx_dropped;
+       data[i++] = priv->tx_timeo_cnt;
+       data[i++] = rx_skb_alloc_fail;
+@@ -330,6 +337,9 @@ gve_get_ethtool_stats(struct net_device
+                               tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
+                               tmp_rx_desc_err_dropped_pkt =
+                                       rx->rx_desc_err_dropped_pkt;
++                              tmp_xdp_tx_errors = rx->xdp_tx_errors;
++                              tmp_xdp_redirect_errors =
++                                      rx->xdp_redirect_errors;
+                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                                                      start));
+                       data[i++] = tmp_rx_bytes;
+@@ -340,8 +350,9 @@ gve_get_ethtool_stats(struct net_device
+                       data[i++] = rx->rx_frag_alloc_cnt;
+                       /* rx dropped packets */
+                       data[i++] = tmp_rx_skb_alloc_fail +
+-                              tmp_rx_buf_alloc_fail +
+-                              tmp_rx_desc_err_dropped_pkt;
++                                  tmp_rx_desc_err_dropped_pkt +
++                                  tmp_xdp_tx_errors +
++                                  tmp_xdp_redirect_errors;
+                       data[i++] = rx->rx_copybreak_pkt;
+                       data[i++] = rx->rx_copied_pkt;
+                       /* stats from NIC */
diff --git a/queue-6.12/gve-fix-stats-report-corruption-on-queue-count-change.patch b/queue-6.12/gve-fix-stats-report-corruption-on-queue-count-change.patch
new file mode 100644 (file)
index 0000000..41530b7
--- /dev/null
@@ -0,0 +1,131 @@
+From 7b9ebcce0296e104a0d82a6b09d68564806158ff Mon Sep 17 00:00:00 2001
+From: Debarghya Kundu <debarghyak@google.com>
+Date: Mon, 2 Feb 2026 19:39:24 +0000
+Subject: gve: Fix stats report corruption on queue count change
+
+From: Debarghya Kundu <debarghyak@google.com>
+
+commit 7b9ebcce0296e104a0d82a6b09d68564806158ff upstream.
+
+The driver and the NIC share a region in memory for stats reporting.
+The NIC calculates its offset into this region based on the total size
+of the stats region and the size of the NIC's stats.
+
+When the number of queues is changed, the driver's stats region is
+resized. If the queue count is increased, the NIC can write past
+the end of the allocated stats region, causing memory corruption.
+If the queue count is decreased, there is a gap between the driver
+and NIC stats, leading to incorrect stats reporting.
+
+This change fixes the issue by allocating stats region with maximum
+size, and the offset calculation for NIC stats is changed to match
+with the calculation of the NIC.
+
+Cc: stable@vger.kernel.org
+Fixes: 24aeb56f2d38 ("gve: Add Gvnic stats AQ command and ethtool show/set-priv-flags.")
+Signed-off-by: Debarghya Kundu <debarghyak@google.com>
+Reviewed-by: Joshua Washington <joshwash@google.com>
+Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20260202193925.3106272-2-hramamurthy@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/google/gve/gve_ethtool.c |   54 ++++++++++++++++----------
+ drivers/net/ethernet/google/gve/gve_main.c    |    4 -
+ 2 files changed, 36 insertions(+), 22 deletions(-)
+
+--- a/drivers/net/ethernet/google/gve/gve_ethtool.c
++++ b/drivers/net/ethernet/google/gve/gve_ethtool.c
+@@ -156,7 +156,8 @@ gve_get_ethtool_stats(struct net_device
+       u64 rx_buf_alloc_fail, rx_desc_err_dropped_pkt, rx_hsplit_unsplit_pkt,
+               rx_pkts, rx_hsplit_pkt, rx_skb_alloc_fail, rx_bytes, tx_pkts, tx_bytes,
+               tx_dropped;
+-      int stats_idx, base_stats_idx, max_stats_idx;
++      int rx_base_stats_idx, max_rx_stats_idx, max_tx_stats_idx;
++      int stats_idx, stats_region_len, nic_stats_len;
+       struct stats *report_stats;
+       int *rx_qid_to_stats_idx;
+       int *tx_qid_to_stats_idx;
+@@ -265,20 +266,38 @@ gve_get_ethtool_stats(struct net_device
+       data[i++] = priv->stats_report_trigger_cnt;
+       i = GVE_MAIN_STATS_LEN;
+-      /* For rx cross-reporting stats, start from nic rx stats in report */
+-      base_stats_idx = GVE_TX_STATS_REPORT_NUM * num_tx_queues +
+-              GVE_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues;
+-      /* The boundary between driver stats and NIC stats shifts if there are
+-       * stopped queues.
+-       */
+-      base_stats_idx += NIC_RX_STATS_REPORT_NUM * num_stopped_rxqs +
+-              NIC_TX_STATS_REPORT_NUM * num_stopped_txqs;
+-      max_stats_idx = NIC_RX_STATS_REPORT_NUM *
+-              (priv->rx_cfg.num_queues - num_stopped_rxqs) +
+-              base_stats_idx;
++      rx_base_stats_idx = 0;
++      max_rx_stats_idx = 0;
++      max_tx_stats_idx = 0;
++      stats_region_len = priv->stats_report_len -
++                              sizeof(struct gve_stats_report);
++      nic_stats_len = (NIC_RX_STATS_REPORT_NUM * priv->rx_cfg.num_queues +
++              NIC_TX_STATS_REPORT_NUM * num_tx_queues) * sizeof(struct stats);
++      if (unlikely((stats_region_len -
++                              nic_stats_len) % sizeof(struct stats))) {
++              net_err_ratelimited("Starting index of NIC stats should be multiple of stats size");
++      } else {
++              /* For rx cross-reporting stats,
++               * start from nic rx stats in report
++               */
++              rx_base_stats_idx = (stats_region_len - nic_stats_len) /
++                                                      sizeof(struct stats);
++              /* The boundary between driver stats and NIC stats
++               * shifts if there are stopped queues
++               */
++              rx_base_stats_idx += NIC_RX_STATS_REPORT_NUM *
++                      num_stopped_rxqs + NIC_TX_STATS_REPORT_NUM *
++                      num_stopped_txqs;
++              max_rx_stats_idx = NIC_RX_STATS_REPORT_NUM *
++                      (priv->rx_cfg.num_queues - num_stopped_rxqs) +
++                      rx_base_stats_idx;
++              max_tx_stats_idx = NIC_TX_STATS_REPORT_NUM *
++                      (num_tx_queues - num_stopped_txqs) +
++                      max_rx_stats_idx;
++      }
+       /* Preprocess the stats report for rx, map queue id to start index */
+       skip_nic_stats = false;
+-      for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
++      for (stats_idx = rx_base_stats_idx; stats_idx < max_rx_stats_idx;
+               stats_idx += NIC_RX_STATS_REPORT_NUM) {
+               u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
+               u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
+@@ -354,14 +373,9 @@ gve_get_ethtool_stats(struct net_device
+               i += priv->rx_cfg.num_queues * NUM_GVE_RX_CNTS;
+       }
+-      /* For tx cross-reporting stats, start from nic tx stats in report */
+-      base_stats_idx = max_stats_idx;
+-      max_stats_idx = NIC_TX_STATS_REPORT_NUM *
+-              (num_tx_queues - num_stopped_txqs) +
+-              max_stats_idx;
+-      /* Preprocess the stats report for tx, map queue id to start index */
+       skip_nic_stats = false;
+-      for (stats_idx = base_stats_idx; stats_idx < max_stats_idx;
++      /* NIC TX stats start right after NIC RX stats */
++      for (stats_idx = max_rx_stats_idx; stats_idx < max_tx_stats_idx;
+               stats_idx += NIC_TX_STATS_REPORT_NUM) {
+               u32 stat_name = be32_to_cpu(report_stats[stats_idx].stat_name);
+               u32 queue_id = be32_to_cpu(report_stats[stats_idx].queue_id);
+--- a/drivers/net/ethernet/google/gve/gve_main.c
++++ b/drivers/net/ethernet/google/gve/gve_main.c
+@@ -244,9 +244,9 @@ static int gve_alloc_stats_report(struct
+       int tx_stats_num, rx_stats_num;
+       tx_stats_num = (GVE_TX_STATS_REPORT_NUM + NIC_TX_STATS_REPORT_NUM) *
+-                     gve_num_tx_queues(priv);
++                              priv->tx_cfg.max_queues;
+       rx_stats_num = (GVE_RX_STATS_REPORT_NUM + NIC_RX_STATS_REPORT_NUM) *
+-                     priv->rx_cfg.num_queues;
++                              priv->rx_cfg.max_queues;
+       priv->stats_report_len = struct_size(priv->stats_report, stats,
+                                            size_add(tx_stats_num, rx_stats_num));
+       priv->stats_report =
diff --git a/queue-6.12/mm-shmem-prevent-infinite-loop-on-truncate-race.patch b/queue-6.12/mm-shmem-prevent-infinite-loop-on-truncate-race.patch
new file mode 100644 (file)
index 0000000..6606224
--- /dev/null
@@ -0,0 +1,84 @@
+From 2030dddf95451b4e7a389f052091e7c4b7b274c6 Mon Sep 17 00:00:00 2001
+From: Kairui Song <kasong@tencent.com>
+Date: Thu, 29 Jan 2026 00:19:23 +0800
+Subject: mm, shmem: prevent infinite loop on truncate race
+
+From: Kairui Song <kasong@tencent.com>
+
+commit 2030dddf95451b4e7a389f052091e7c4b7b274c6 upstream.
+
+When truncating a large swap entry, shmem_free_swap() returns 0 when the
+entry's index doesn't match the given index due to lookup alignment.  The
+failure fallback path checks if the entry crosses the end border and
+aborts when it happens, so truncate won't erase an unexpected entry or
+range.  But one scenario was ignored.
+
+When `index` points to the middle of a large swap entry, and the large
+swap entry doesn't go across the end border, find_get_entries() will
+return that large swap entry as the first item in the batch with
+`indices[0]` equal to `index`.  The entry's base index will be smaller
+than `indices[0]`, so shmem_free_swap() will fail and return 0 due to the
+"base < index" check.  The code will then call shmem_confirm_swap(), get
+the order, check if it crosses the END boundary (which it doesn't), and
+retry with the same index.
+
+The next iteration will find the same entry again at the same index with
+same indices, leading to an infinite loop.
+
+Fix this by retrying with a round-down index, and abort if the index is
+smaller than the truncate range.
+
+Link: https://lkml.kernel.org/r/aXo6ltB5iqAKJzY8@KASONG-MC4
+Fixes: 809bc86517cc ("mm: shmem: support large folio swap out")
+Fixes: 8a1968bd997f ("mm/shmem, swap: fix race of truncate and swap entry split")
+Signed-off-by: Kairui Song <kasong@tencent.com>
+Reported-by: Chris Mason <clm@meta.com>
+Closes: https://lore.kernel.org/linux-mm/20260128130336.727049-1-clm@meta.com/
+Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Baoquan He <bhe@redhat.com>
+Cc: Barry Song <baohua@kernel.org>
+Cc: Chris Li <chrisl@kernel.org>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Kemeng Shi <shikemeng@huaweicloud.com>
+Cc: Nhat Pham <nphamcs@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/shmem.c |   23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -1109,17 +1109,22 @@ whole_folios:
+                               swaps_freed = shmem_free_swap(mapping, indices[i],
+                                                             end - 1, folio);
+                               if (!swaps_freed) {
+-                                      /*
+-                                       * If found a large swap entry cross the end border,
+-                                       * skip it as the truncate_inode_partial_folio above
+-                                       * should have at least zerod its content once.
+-                                       */
++                                      pgoff_t base = indices[i];
++
+                                       order = shmem_confirm_swap(mapping, indices[i],
+                                                                  radix_to_swp_entry(folio));
+-                                      if (order > 0 && indices[i] + (1 << order) > end)
+-                                              continue;
+-                                      /* Swap was replaced by page: retry */
+-                                      index = indices[i];
++                                      /*
++                                       * If found a large swap entry cross the end or start
++                                       * border, skip it as the truncate_inode_partial_folio
++                                       * above should have at least zerod its content once.
++                                       */
++                                      if (order > 0) {
++                                              base = round_down(base, 1 << order);
++                                              if (base < start || base + (1 << order) > end)
++                                                      continue;
++                                      }
++                                      /* Swap was replaced by page or extended, retry */
++                                      index = base;
+                                       break;
+                               }
+                               nr_swaps_freed += swaps_freed;
diff --git a/queue-6.12/mm-slab-add-alloc_tagging_slab_free_hook-for-memcg_alloc_abort_single.patch b/queue-6.12/mm-slab-add-alloc_tagging_slab_free_hook-for-memcg_alloc_abort_single.patch
new file mode 100644 (file)
index 0000000..066ee69
--- /dev/null
@@ -0,0 +1,99 @@
+From e6c53ead2d8fa73206e0a63e9cd9aea6bc929837 Mon Sep 17 00:00:00 2001
+From: Hao Ge <hao.ge@linux.dev>
+Date: Wed, 4 Feb 2026 18:14:01 +0800
+Subject: mm/slab: Add alloc_tagging_slab_free_hook for memcg_alloc_abort_single
+
+From: Hao Ge <hao.ge@linux.dev>
+
+commit e6c53ead2d8fa73206e0a63e9cd9aea6bc929837 upstream.
+
+When CONFIG_MEM_ALLOC_PROFILING_DEBUG is enabled, the following warning
+may be noticed:
+
+[ 3959.023862] ------------[ cut here ]------------
+[ 3959.023891] alloc_tag was not cleared (got tag for lib/xarray.c:378)
+[ 3959.023947] WARNING: ./include/linux/alloc_tag.h:155 at alloc_tag_add+0x128/0x178, CPU#6: mkfs.ntfs/113998
+[ 3959.023978] Modules linked in: dns_resolver tun brd overlay exfat btrfs blake2b libblake2b xor xor_neon raid6_pq loop sctp ip6_udp_tunnel udp_tunnel ext4 crc16 mbcache jbd2 rfkill sunrpc vfat fat sg fuse nfnetlink sr_mod virtio_gpu cdrom drm_client_lib virtio_dma_buf drm_shmem_helper drm_kms_helper ghash_ce drm sm4 backlight virtio_net net_failover virtio_scsi failover virtio_console virtio_blk virtio_mmio dm_mirror dm_region_hash dm_log dm_multipath dm_mod i2c_dev aes_neon_bs aes_ce_blk [last unloaded: hwpoison_inject]
+[ 3959.024170] CPU: 6 UID: 0 PID: 113998 Comm: mkfs.ntfs Kdump: loaded Tainted: G        W           6.19.0-rc7+ #7 PREEMPT(voluntary)
+[ 3959.024182] Tainted: [W]=WARN
+[ 3959.024186] Hardware name: QEMU KVM Virtual Machine, BIOS unknown 2/2/2022
+[ 3959.024192] pstate: 604000c5 (nZCv daIF +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+[ 3959.024199] pc : alloc_tag_add+0x128/0x178
+[ 3959.024207] lr : alloc_tag_add+0x128/0x178
+[ 3959.024214] sp : ffff80008b696d60
+[ 3959.024219] x29: ffff80008b696d60 x28: 0000000000000000 x27: 0000000000000240
+[ 3959.024232] x26: 0000000000000000 x25: 0000000000000240 x24: ffff800085d17860
+[ 3959.024245] x23: 0000000000402800 x22: ffff0000c0012dc0 x21: 00000000000002d0
+[ 3959.024257] x20: ffff0000e6ef3318 x19: ffff800085ae0410 x18: 0000000000000000
+[ 3959.024269] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
+[ 3959.024281] x14: 0000000000000000 x13: 0000000000000001 x12: ffff600064101293
+[ 3959.024292] x11: 1fffe00064101292 x10: ffff600064101292 x9 : dfff800000000000
+[ 3959.024305] x8 : 00009fff9befed6e x7 : ffff000320809493 x6 : 0000000000000001
+[ 3959.024316] x5 : ffff000320809490 x4 : ffff600064101293 x3 : ffff800080691838
+[ 3959.024328] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0000d5bcd640
+[ 3959.024340] Call trace:
+[ 3959.024346]  alloc_tag_add+0x128/0x178 (P)
+[ 3959.024355]  __alloc_tagging_slab_alloc_hook+0x11c/0x1a8
+[ 3959.024362]  kmem_cache_alloc_lru_noprof+0x1b8/0x5e8
+[ 3959.024369]  xas_alloc+0x304/0x4f0
+[ 3959.024381]  xas_create+0x1e0/0x4a0
+[ 3959.024388]  xas_store+0x68/0xda8
+[ 3959.024395]  __filemap_add_folio+0x5b0/0xbd8
+[ 3959.024409]  filemap_add_folio+0x16c/0x7e0
+[ 3959.024416]  __filemap_get_folio_mpol+0x2dc/0x9e8
+[ 3959.024424]  iomap_get_folio+0xfc/0x180
+[ 3959.024435]  __iomap_get_folio+0x2f8/0x4b8
+[ 3959.024441]  iomap_write_begin+0x198/0xc18
+[ 3959.024448]  iomap_write_iter+0x2ec/0x8f8
+[ 3959.024454]  iomap_file_buffered_write+0x19c/0x290
+[ 3959.024461]  blkdev_write_iter+0x38c/0x978
+[ 3959.024470]  vfs_write+0x4d4/0x928
+[ 3959.024482]  ksys_write+0xfc/0x1f8
+[ 3959.024489]  __arm64_sys_write+0x74/0xb0
+[ 3959.024496]  invoke_syscall+0xd4/0x258
+[ 3959.024507]  el0_svc_common.constprop.0+0xb4/0x240
+[ 3959.024514]  do_el0_svc+0x48/0x68
+[ 3959.024520]  el0_svc+0x40/0xf8
+[ 3959.024526]  el0t_64_sync_handler+0xa0/0xe8
+[ 3959.024533]  el0t_64_sync+0x1ac/0x1b0
+[ 3959.024540] ---[ end trace 0000000000000000 ]---
+
+When __memcg_slab_post_alloc_hook() fails, there are two different
+free paths depending on whether size == 1 or size != 1. In the
+kmem_cache_free_bulk() path, we do call alloc_tagging_slab_free_hook().
+However, in memcg_alloc_abort_single() we don't, the above warning will be
+triggered on the next allocation.
+
+Therefore, add alloc_tagging_slab_free_hook() to the
+memcg_alloc_abort_single() path.
+
+Fixes: 9f9796b413d3 ("mm, slab: move memcg charging to post-alloc hook")
+Cc: stable@vger.kernel.org
+Suggested-by: Hao Li <hao.li@linux.dev>
+Signed-off-by: Hao Ge <hao.ge@linux.dev>
+Reviewed-by: Hao Li <hao.li@linux.dev>
+Reviewed-by: Suren Baghdasaryan <surenb@google.com>
+Reviewed-by: Harry Yoo <harry.yoo@oracle.com>
+Link: https://patch.msgid.link/20260204101401.202762-1-hao.ge@linux.dev
+Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/slub.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -4657,8 +4657,12 @@ void slab_free(struct kmem_cache *s, str
+ static noinline
+ void memcg_alloc_abort_single(struct kmem_cache *s, void *object)
+ {
++      struct slab *slab = virt_to_slab(object);
++
++      alloc_tagging_slab_free_hook(s, slab, &object, 1);
++
+       if (likely(slab_free_hook(s, object, slab_want_init_on_free(s), false)))
+-              do_slab_free(s, virt_to_slab(object), object, object, 1, _RET_IP_);
++              do_slab_free(s, slab, object, object, 1, _RET_IP_);
+ }
+ #endif
diff --git a/queue-6.12/platform-x86-intel_telemetry-fix-swapped-arrays-in-pss-output.patch b/queue-6.12/platform-x86-intel_telemetry-fix-swapped-arrays-in-pss-output.patch
new file mode 100644 (file)
index 0000000..c47d1f9
--- /dev/null
@@ -0,0 +1,54 @@
+From 25e9e322d2ab5c03602eff4fbf4f7c40019d8de2 Mon Sep 17 00:00:00 2001
+From: Kaushlendra Kumar <kaushlendra.kumar@intel.com>
+Date: Wed, 24 Dec 2025 08:50:53 +0530
+Subject: platform/x86: intel_telemetry: Fix swapped arrays in PSS output
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kaushlendra Kumar <kaushlendra.kumar@intel.com>
+
+commit 25e9e322d2ab5c03602eff4fbf4f7c40019d8de2 upstream.
+
+The LTR blocking statistics and wakeup event counters are incorrectly
+cross-referenced during debugfs output rendering. The code populates
+pss_ltr_blkd[] with LTR blocking data and pss_s0ix_wakeup[] with wakeup
+data, but the display loops reference the wrong arrays.
+
+This causes the "LTR Blocking Status" section to print wakeup events
+and the "Wakes Status" section to print LTR blockers, misleading power
+management analysis and S0ix residency debugging.
+
+Fix by aligning array usage with the intended output section labels.
+
+Fixes: 87bee290998d ("platform:x86: Add Intel Telemetry Debugfs interfaces")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kaushlendra Kumar <kaushlendra.kumar@intel.com>
+Link: https://patch.msgid.link/20251224032053.3915900-1-kaushlendra.kumar@intel.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/intel/telemetry/debugfs.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/platform/x86/intel/telemetry/debugfs.c
++++ b/drivers/platform/x86/intel/telemetry/debugfs.c
+@@ -449,7 +449,7 @@ static int telem_pss_states_show(struct
+       for (index = 0; index < debugfs_conf->pss_ltr_evts; index++) {
+               seq_printf(s, "%-32s\t%u\n",
+                          debugfs_conf->pss_ltr_data[index].name,
+-                         pss_s0ix_wakeup[index]);
++                         pss_ltr_blkd[index]);
+       }
+       seq_puts(s, "\n--------------------------------------\n");
+@@ -459,7 +459,7 @@ static int telem_pss_states_show(struct
+       for (index = 0; index < debugfs_conf->pss_wakeup_evts; index++) {
+               seq_printf(s, "%-32s\t%u\n",
+                          debugfs_conf->pss_wakeup[index].name,
+-                         pss_ltr_blkd[index]);
++                         pss_s0ix_wakeup[index]);
+       }
+       return 0;
diff --git a/queue-6.12/pmdomain-imx-gpcv2-fix-the-imx8mm-gpu-hang-due-to-wrong-adb400-reset.patch b/queue-6.12/pmdomain-imx-gpcv2-fix-the-imx8mm-gpu-hang-due-to-wrong-adb400-reset.patch
new file mode 100644 (file)
index 0000000..60b971a
--- /dev/null
@@ -0,0 +1,67 @@
+From ae0a24c5a8dcea20bf8e344eadf6593e6d1959c3 Mon Sep 17 00:00:00 2001
+From: Jacky Bai <ping.bai@nxp.com>
+Date: Fri, 23 Jan 2026 10:51:26 +0800
+Subject: pmdomain: imx: gpcv2: Fix the imx8mm gpu hang due to wrong adb400 reset
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jacky Bai <ping.bai@nxp.com>
+
+commit ae0a24c5a8dcea20bf8e344eadf6593e6d1959c3 upstream.
+
+On i.MX8MM, the GPUMIX, GPU2D, and GPU3D blocks share a common reset
+domain. Due to this hardware limitation, powering off/on GPU2D or GPU3D
+also triggers a reset of the GPUMIX domain, including its ADB400 port.
+However, the ADB400 interface must always be placed into power‑down mode
+before being reset.
+
+Currently the GPUMIX and GPU2D/3D power domains rely on runtime PM to
+handle dependency ordering. In some corner cases, the GPUMIX power off
+sequence is skipped, leaving the ADB400 port active when GPU2D/3D reset.
+This causes the GPUMIX ADB400 port to be reset while still active,
+leading to unpredictable bus behavior and GPU hangs.
+
+To avoid this, refine the power‑domain control logic so that the GPUMIX
+ADB400 port is explicitly powered down and powered up as part of the GPU
+power domain on/off sequence. This ensures proper ordering and prevents
+incorrect ADB400 reset.
+
+Suggested-by: Lucas Stach <l.stach@pengutronix.de>
+Signed-off-by: Jacky Bai <ping.bai@nxp.com>
+Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
+Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/imx/gpcv2.c |    8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/pmdomain/imx/gpcv2.c
++++ b/drivers/pmdomain/imx/gpcv2.c
+@@ -165,13 +165,11 @@
+ #define IMX8M_VPU_HSK_PWRDNREQN                       BIT(5)
+ #define IMX8M_DISP_HSK_PWRDNREQN              BIT(4)
+-#define IMX8MM_GPUMIX_HSK_PWRDNACKN           BIT(29)
+-#define IMX8MM_GPU_HSK_PWRDNACKN              (BIT(27) | BIT(28))
++#define IMX8MM_GPU_HSK_PWRDNACKN              GENMASK(29, 27)
+ #define IMX8MM_VPUMIX_HSK_PWRDNACKN           BIT(26)
+ #define IMX8MM_DISPMIX_HSK_PWRDNACKN          BIT(25)
+ #define IMX8MM_HSIO_HSK_PWRDNACKN             (BIT(23) | BIT(24))
+-#define IMX8MM_GPUMIX_HSK_PWRDNREQN           BIT(11)
+-#define IMX8MM_GPU_HSK_PWRDNREQN              (BIT(9) | BIT(10))
++#define IMX8MM_GPU_HSK_PWRDNREQN              GENMASK(11, 9)
+ #define IMX8MM_VPUMIX_HSK_PWRDNREQN           BIT(8)
+ #define IMX8MM_DISPMIX_HSK_PWRDNREQN          BIT(7)
+ #define IMX8MM_HSIO_HSK_PWRDNREQN             (BIT(5) | BIT(6))
+@@ -794,8 +792,6 @@ static const struct imx_pgc_domain imx8m
+               .bits  = {
+                       .pxx = IMX8MM_GPUMIX_SW_Pxx_REQ,
+                       .map = IMX8MM_GPUMIX_A53_DOMAIN,
+-                      .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
+-                      .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+               },
+               .pgc   = BIT(IMX8MM_PGC_GPUMIX),
+               .keep_clocks = true,
diff --git a/queue-6.12/pmdomain-imx8m-blk-ctrl-fix-out-of-range-access-of-bc-domains.patch b/queue-6.12/pmdomain-imx8m-blk-ctrl-fix-out-of-range-access-of-bc-domains.patch
new file mode 100644 (file)
index 0000000..3ba1429
--- /dev/null
@@ -0,0 +1,32 @@
+From 6bd8b4a92a901fae1a422e6f914801063c345e8d Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Fri, 30 Jan 2026 13:11:07 +0800
+Subject: pmdomain: imx8m-blk-ctrl: fix out-of-range access of bc->domains
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit 6bd8b4a92a901fae1a422e6f914801063c345e8d upstream.
+
+Fix out-of-range access of bc->domains in imx8m_blk_ctrl_remove().
+
+Fixes: 2684ac05a8c4 ("soc: imx: add i.MX8M blk-ctrl driver")
+Cc: stable@kernel.org
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/imx/imx8m-blk-ctrl.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c
++++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
+@@ -340,7 +340,7 @@ static void imx8m_blk_ctrl_remove(struct
+       of_genpd_del_provider(pdev->dev.of_node);
+-      for (i = 0; bc->onecell_data.num_domains; i++) {
++      for (i = 0; i < bc->onecell_data.num_domains; i++) {
+               struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
+               pm_genpd_remove(&domain->genpd);
diff --git a/queue-6.12/pmdomain-imx8mp-blk-ctrl-keep-gpc-power-domain-on-for-system-wakeup.patch b/queue-6.12/pmdomain-imx8mp-blk-ctrl-keep-gpc-power-domain-on-for-system-wakeup.patch
new file mode 100644 (file)
index 0000000..1c0d9a8
--- /dev/null
@@ -0,0 +1,109 @@
+From e9ab2b83893dd03cf04d98faded81190e635233f Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Wed, 4 Feb 2026 19:11:41 +0800
+Subject: pmdomain: imx8mp-blk-ctrl: Keep gpc power domain on for system wakeup
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit e9ab2b83893dd03cf04d98faded81190e635233f upstream.
+
+Current design will power off all dependent GPC power domains in
+imx8mp_blk_ctrl_suspend(), even though the user device has enabled
+wakeup capability. The result is that wakeup function never works
+for such device.
+
+An example will be USB wakeup on i.MX8MP. PHY device '382f0040.usb-phy'
+is attached to power domain 'hsioblk-usb-phy2' which is spawned by hsio
+block control. A virtual power domain device 'genpd:3:32f10000.blk-ctrl'
+is created to build connection with 'hsioblk-usb-phy2' and it depends on
+GPC power domain 'usb-otg2'. If device '382f0040.usb-phy' enable wakeup,
+only power domain 'hsioblk-usb-phy2' keeps on during system suspend,
+power domain 'usb-otg2' is off all the time. So the wakeup event can't
+happen.
+
+In order to further establish a connection between the power domains
+related to GPC and block control during system suspend, register a genpd
+power on/off notifier for the power_dev. This allows us to prevent the GPC
+power domain from being powered off, in case the block control power
+domain is kept on to serve system wakeup.
+
+Suggested-by: Ulf Hansson <ulf.hansson@linaro.org>
+Fixes: 556f5cf9568a ("soc: imx: add i.MX8MP HSIO blk-ctrl")
+Cc: stable@vger.kernel.org
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/imx/imx8mp-blk-ctrl.c |   26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
++++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+@@ -65,6 +65,7 @@ struct imx8mp_blk_ctrl_domain {
+       struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
+       struct device *power_dev;
+       struct imx8mp_blk_ctrl *bc;
++      struct notifier_block power_nb;
+       int num_paths;
+       int id;
+ };
+@@ -594,6 +595,20 @@ static int imx8mp_blk_ctrl_power_off(str
+       return 0;
+ }
++static int imx8mp_blk_ctrl_gpc_notifier(struct notifier_block *nb,
++                                      unsigned long action, void *data)
++{
++      struct imx8mp_blk_ctrl_domain *domain =
++                      container_of(nb, struct imx8mp_blk_ctrl_domain, power_nb);
++
++      if (action == GENPD_NOTIFY_PRE_OFF) {
++              if (domain->genpd.status == GENPD_STATE_ON)
++                      return NOTIFY_BAD;
++      }
++
++      return NOTIFY_OK;
++}
++
+ static struct lock_class_key blk_ctrl_genpd_lock_class;
+ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
+@@ -698,6 +713,14 @@ static int imx8mp_blk_ctrl_probe(struct
+                       goto cleanup_pds;
+               }
++              domain->power_nb.notifier_call = imx8mp_blk_ctrl_gpc_notifier;
++              ret = dev_pm_genpd_add_notifier(domain->power_dev, &domain->power_nb);
++              if (ret) {
++                      dev_err_probe(dev, ret, "failed to add power notifier\n");
++                      dev_pm_domain_detach(domain->power_dev, true);
++                      goto cleanup_pds;
++              }
++
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
+               domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
+@@ -707,6 +730,7 @@ static int imx8mp_blk_ctrl_probe(struct
+               ret = pm_genpd_init(&domain->genpd, NULL, true);
+               if (ret) {
+                       dev_err_probe(dev, ret, "failed to init power domain\n");
++                      dev_pm_genpd_remove_notifier(domain->power_dev);
+                       dev_pm_domain_detach(domain->power_dev, true);
+                       goto cleanup_pds;
+               }
+@@ -755,6 +779,7 @@ cleanup_provider:
+ cleanup_pds:
+       for (i--; i >= 0; i--) {
+               pm_genpd_remove(&bc->domains[i].genpd);
++              dev_pm_genpd_remove_notifier(bc->domains[i].power_dev);
+               dev_pm_domain_detach(bc->domains[i].power_dev, true);
+       }
+@@ -774,6 +799,7 @@ static void imx8mp_blk_ctrl_remove(struc
+               struct imx8mp_blk_ctrl_domain *domain = &bc->domains[i];
+               pm_genpd_remove(&domain->genpd);
++              dev_pm_genpd_remove_notifier(domain->power_dev);
+               dev_pm_domain_detach(domain->power_dev, true);
+       }
diff --git a/queue-6.12/pmdomain-imx8mp-blk-ctrl-keep-usb-phy-power-domain-on-for-system-wakeup.patch b/queue-6.12/pmdomain-imx8mp-blk-ctrl-keep-usb-phy-power-domain-on-for-system-wakeup.patch
new file mode 100644 (file)
index 0000000..d865b86
--- /dev/null
@@ -0,0 +1,52 @@
+From e2c4c5b2bbd4f688a0f9f6da26cdf6d723c53478 Mon Sep 17 00:00:00 2001
+From: Xu Yang <xu.yang_2@nxp.com>
+Date: Wed, 4 Feb 2026 19:11:42 +0800
+Subject: pmdomain: imx8mp-blk-ctrl: Keep usb phy power domain on for system wakeup
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+commit e2c4c5b2bbd4f688a0f9f6da26cdf6d723c53478 upstream.
+
+USB system wakeup need its PHY on, so add the GENPD_FLAG_ACTIVE_WAKEUP
+flags to USB PHY genpd configuration.
+
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Fixes: 556f5cf9568a ("soc: imx: add i.MX8MP HSIO blk-ctrl")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/imx/imx8mp-blk-ctrl.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
++++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+@@ -53,6 +53,7 @@ struct imx8mp_blk_ctrl_domain_data {
+       const char * const *path_names;
+       int num_paths;
+       const char *gpc_name;
++      const unsigned int flags;
+ };
+ #define DOMAIN_MAX_CLKS 3
+@@ -265,10 +266,12 @@ static const struct imx8mp_blk_ctrl_doma
+       [IMX8MP_HSIOBLK_PD_USB_PHY1] = {
+               .name = "hsioblk-usb-phy1",
+               .gpc_name = "usb-phy1",
++              .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+       },
+       [IMX8MP_HSIOBLK_PD_USB_PHY2] = {
+               .name = "hsioblk-usb-phy2",
+               .gpc_name = "usb-phy2",
++              .flags = GENPD_FLAG_ACTIVE_WAKEUP,
+       },
+       [IMX8MP_HSIOBLK_PD_PCIE] = {
+               .name = "hsioblk-pcie",
+@@ -724,6 +727,7 @@ static int imx8mp_blk_ctrl_probe(struct
+               domain->genpd.name = data->name;
+               domain->genpd.power_on = imx8mp_blk_ctrl_power_on;
+               domain->genpd.power_off = imx8mp_blk_ctrl_power_off;
++              domain->genpd.flags = data->flags;
+               domain->bc = bc;
+               domain->id = i;
diff --git a/queue-6.12/pmdomain-qcom-rpmpd-fix-off-by-one-error-in-clamping-to-the-highest-state.patch b/queue-6.12/pmdomain-qcom-rpmpd-fix-off-by-one-error-in-clamping-to-the-highest-state.patch
new file mode 100644 (file)
index 0000000..f72a0e7
--- /dev/null
@@ -0,0 +1,40 @@
+From 8aa6f7697f5981d336cac7af6ddd182a03c6da01 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <j4g8y7@gmail.com>
+Date: Thu, 22 Jan 2026 18:20:12 +0100
+Subject: pmdomain: qcom: rpmpd: fix off-by-one error in clamping to the highest state
+
+From: Gabor Juhos <j4g8y7@gmail.com>
+
+commit 8aa6f7697f5981d336cac7af6ddd182a03c6da01 upstream.
+
+As it is indicated by the comment, the rpmpd_aggregate_corner() function
+tries to clamp the state to the highest corner/level supported by the
+given power domain, however the calculation of the highest state contains
+an off-by-one error.
+
+The 'max_state' member of the 'rpmpd' structure indicates the highest
+corner/level, and as such it does not needs to be decremented.
+
+Change the code to use the 'max_state' value directly to avoid the error.
+
+Fixes: 98c8b3efacae ("soc: qcom: rpmpd: Add sync_state")
+Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pmdomain/qcom/rpmpd.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/pmdomain/qcom/rpmpd.c
++++ b/drivers/pmdomain/qcom/rpmpd.c
+@@ -1001,7 +1001,7 @@ static int rpmpd_aggregate_corner(struct
+       /* Clamp to the highest corner/level if sync_state isn't done yet */
+       if (!pd->state_synced)
+-              this_active_corner = this_sleep_corner = pd->max_state - 1;
++              this_active_corner = this_sleep_corner = pd->max_state;
+       else
+               to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
diff --git a/queue-6.12/rbd-check-for-eod-after-exclusive-lock-is-ensured-to-be-held.patch b/queue-6.12/rbd-check-for-eod-after-exclusive-lock-is-ensured-to-be-held.patch
new file mode 100644 (file)
index 0000000..4ab5532
--- /dev/null
@@ -0,0 +1,94 @@
+From bd3884a204c3b507e6baa9a4091aa927f9af5404 Mon Sep 17 00:00:00 2001
+From: Ilya Dryomov <idryomov@gmail.com>
+Date: Wed, 7 Jan 2026 22:37:55 +0100
+Subject: rbd: check for EOD after exclusive lock is ensured to be held
+
+From: Ilya Dryomov <idryomov@gmail.com>
+
+commit bd3884a204c3b507e6baa9a4091aa927f9af5404 upstream.
+
+Similar to commit 870611e4877e ("rbd: get snapshot context after
+exclusive lock is ensured to be held"), move the "beyond EOD" check
+into the image request state machine so that it's performed after
+exclusive lock is ensured to be held.  This avoids various race
+conditions which can arise when the image is shrunk under I/O (in
+practice, mostly readahead).  In one such scenario
+
+    rbd_assert(objno < rbd_dev->object_map_size);
+
+can be triggered if a close-to-EOD read gets queued right before the
+shrink is initiated and the EOD check is performed against an outdated
+mapping_size.  After the resize is done on the server side and exclusive
+lock is (re)acquired bringing along the new (now shrunk) object map, the
+read starts going through the state machine and rbd_obj_may_exist() gets
+invoked on an object that is out of bounds of rbd_dev->object_map array.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
+Reviewed-by: Dongsheng Yang <dongsheng.yang@linux.dev>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/rbd.c |   33 +++++++++++++++++++++------------
+ 1 file changed, 21 insertions(+), 12 deletions(-)
+
+--- a/drivers/block/rbd.c
++++ b/drivers/block/rbd.c
+@@ -3495,11 +3495,29 @@ static void rbd_img_object_requests(stru
+       rbd_assert(!need_exclusive_lock(img_req) ||
+                  __rbd_is_lock_owner(rbd_dev));
+-      if (rbd_img_is_write(img_req)) {
+-              rbd_assert(!img_req->snapc);
++      if (test_bit(IMG_REQ_CHILD, &img_req->flags)) {
++              rbd_assert(!rbd_img_is_write(img_req));
++      } else {
++              struct request *rq = blk_mq_rq_from_pdu(img_req);
++              u64 off = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
++              u64 len = blk_rq_bytes(rq);
++              u64 mapping_size;
++
+               down_read(&rbd_dev->header_rwsem);
+-              img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc);
++              mapping_size = rbd_dev->mapping.size;
++              if (rbd_img_is_write(img_req)) {
++                      rbd_assert(!img_req->snapc);
++                      img_req->snapc =
++                          ceph_get_snap_context(rbd_dev->header.snapc);
++              }
+               up_read(&rbd_dev->header_rwsem);
++
++              if (unlikely(off + len > mapping_size)) {
++                      rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)",
++                               off, len, mapping_size);
++                      img_req->pending.result = -EIO;
++                      return;
++              }
+       }
+       for_each_obj_request(img_req, obj_req) {
+@@ -4725,7 +4743,6 @@ static void rbd_queue_workfn(struct work
+       struct request *rq = blk_mq_rq_from_pdu(img_request);
+       u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
+       u64 length = blk_rq_bytes(rq);
+-      u64 mapping_size;
+       int result;
+       /* Ignore/skip any zero-length requests */
+@@ -4738,17 +4755,9 @@ static void rbd_queue_workfn(struct work
+       blk_mq_start_request(rq);
+       down_read(&rbd_dev->header_rwsem);
+-      mapping_size = rbd_dev->mapping.size;
+       rbd_img_capture_header(img_request);
+       up_read(&rbd_dev->header_rwsem);
+-      if (offset + length > mapping_size) {
+-              rbd_warn(rbd_dev, "beyond EOD (%llu~%llu > %llu)", offset,
+-                       length, mapping_size);
+-              result = -EIO;
+-              goto err_img_request;
+-      }
+-
+       dout("%s rbd_dev %p img_req %p %s %llu~%llu\n", __func__, rbd_dev,
+            img_request, obj_op_name(op_type), offset, length);
diff --git a/queue-6.12/revert-drm-amd-check-if-aspm-is-enabled-from-pcie-subsystem.patch b/queue-6.12/revert-drm-amd-check-if-aspm-is-enabled-from-pcie-subsystem.patch
new file mode 100644 (file)
index 0000000..23ebb1e
--- /dev/null
@@ -0,0 +1,46 @@
+From 243b467dea1735fed904c2e54d248a46fa417a2d Mon Sep 17 00:00:00 2001
+From: Bert Karwatzki <spasswolf@web.de>
+Date: Sun, 1 Feb 2026 01:24:45 +0100
+Subject: Revert "drm/amd: Check if ASPM is enabled from PCIe subsystem"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bert Karwatzki <spasswolf@web.de>
+
+commit 243b467dea1735fed904c2e54d248a46fa417a2d upstream.
+
+This reverts commit 7294863a6f01248d72b61d38478978d638641bee.
+
+This commit was erroneously applied again after commit 0ab5d711ec74
+("drm/amd: Refactor `amdgpu_aspm` to be evaluated per device")
+removed it, leading to very hard to debug crashes, when used with a system with two
+AMD GPUs of which only one supports ASPM.
+
+Link: https://lore.kernel.org/linux-acpi/20251006120944.7880-1-spasswolf@web.de/
+Link: https://github.com/acpica/acpica/issues/1060
+Fixes: 0ab5d711ec74 ("drm/amd: Refactor `amdgpu_aspm` to be evaluated per device")
+Signed-off-by: Bert Karwatzki <spasswolf@web.de>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 97a9689300eb2b393ba5efc17c8e5db835917080)
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c |    3 ---
+ 1 file changed, 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -2273,9 +2273,6 @@ static int amdgpu_pci_probe(struct pci_d
+                       return -ENODEV;
+       }
+-      if (amdgpu_aspm == -1 && !pcie_aspm_enabled(pdev))
+-              amdgpu_aspm = 0;
+-
+       if (amdgpu_virtual_display ||
+           amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
+               supports_atomic = true;
index 6bd96d575e012295f4f80b8863d2026b37fdd254..b253c8b27c65a09f08e3f89af084c80762499994 100644 (file)
@@ -1 +1,19 @@
 nvmet-tcp-add-bounds-checks-in-nvmet_tcp_build_pdu_iovec.patch
+x86-vmware-fix-hypercall-clobbers.patch
+x86-kfence-fix-booting-on-32bit-non-pae-systems.patch
+platform-x86-intel_telemetry-fix-swapped-arrays-in-pss-output.patch
+alsa-aloop-fix-racy-access-at-pcm-trigger.patch
+pmdomain-qcom-rpmpd-fix-off-by-one-error-in-clamping-to-the-highest-state.patch
+pmdomain-imx8mp-blk-ctrl-keep-gpc-power-domain-on-for-system-wakeup.patch
+pmdomain-imx-gpcv2-fix-the-imx8mm-gpu-hang-due-to-wrong-adb400-reset.patch
+pmdomain-imx8mp-blk-ctrl-keep-usb-phy-power-domain-on-for-system-wakeup.patch
+pmdomain-imx8m-blk-ctrl-fix-out-of-range-access-of-bc-domains.patch
+mm-slab-add-alloc_tagging_slab_free_hook-for-memcg_alloc_abort_single.patch
+ceph-fix-null-pointer-dereference-in-ceph_mds_auth_match.patch
+rbd-check-for-eod-after-exclusive-lock-is-ensured-to-be-held.patch
+arm-9468-1-fix-memset64-on-big-endian.patch
+ceph-fix-oops-due-to-invalid-pointer-for-kfree-in-parse_longname.patch
+gve-fix-stats-report-corruption-on-queue-count-change.patch
+gve-correct-ethtool-rx_dropped-calculation.patch
+mm-shmem-prevent-infinite-loop-on-truncate-race.patch
+revert-drm-amd-check-if-aspm-is-enabled-from-pcie-subsystem.patch
diff --git a/queue-6.12/x86-kfence-fix-booting-on-32bit-non-pae-systems.patch b/queue-6.12/x86-kfence-fix-booting-on-32bit-non-pae-systems.patch
new file mode 100644 (file)
index 0000000..a4cebf6
--- /dev/null
@@ -0,0 +1,68 @@
+From 16459fe7e0ca6520a6e8f603de4ccd52b90fd765 Mon Sep 17 00:00:00 2001
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+Date: Mon, 26 Jan 2026 21:10:46 +0000
+Subject: x86/kfence: fix booting on 32bit non-PAE systems
+
+From: Andrew Cooper <andrew.cooper3@citrix.com>
+
+commit 16459fe7e0ca6520a6e8f603de4ccd52b90fd765 upstream.
+
+The original patch inverted the PTE unconditionally to avoid
+L1TF-vulnerable PTEs, but Linux doesn't make this adjustment in 2-level
+paging.
+
+Adjust the logic to use the flip_protnone_guard() helper, which is a nop
+on 2-level paging but inverts the address bits in all other paging modes.
+
+This doesn't matter for the Xen aspect of the original change.  Linux no
+longer supports running 32bit PV under Xen, and Xen doesn't support
+running any 32bit PV guests without using PAE paging.
+
+Link: https://lkml.kernel.org/r/20260126211046.2096622-1-andrew.cooper3@citrix.com
+Fixes: b505f1944535 ("x86/kfence: avoid writing L1TF-vulnerable PTEs")
+Reported-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Closes: https://lore.kernel.org/lkml/CAKFNMokwjw68ubYQM9WkzOuH51wLznHpEOMSqtMoV1Rn9JV_gw@mail.gmail.com/
+Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
+Tested-by: Borislav Petkov (AMD) <bp@alien8.de>
+Cc: Alexander Potapenko <glider@google.com>
+Cc: Marco Elver <elver@google.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/kfence.h |    7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/include/asm/kfence.h
++++ b/arch/x86/include/asm/kfence.h
+@@ -42,7 +42,7 @@ static inline bool kfence_protect_page(u
+ {
+       unsigned int level;
+       pte_t *pte = lookup_address(addr, &level);
+-      pteval_t val;
++      pteval_t val, new;
+       if (WARN_ON(!pte || level != PG_LEVEL_4K))
+               return false;
+@@ -57,11 +57,12 @@ static inline bool kfence_protect_page(u
+               return true;
+       /*
+-       * Otherwise, invert the entire PTE.  This avoids writing out an
++       * Otherwise, flip the Present bit, taking care to avoid writing an
+        * L1TF-vulnerable PTE (not present, without the high address bits
+        * set).
+        */
+-      set_pte(pte, __pte(~val));
++      new = val ^ _PAGE_PRESENT;
++      set_pte(pte, __pte(flip_protnone_guard(val, new, PTE_PFN_MASK)));
+       /*
+        * If the page was protected (non-present) and we're making it
diff --git a/queue-6.12/x86-vmware-fix-hypercall-clobbers.patch b/queue-6.12/x86-vmware-fix-hypercall-clobbers.patch
new file mode 100644 (file)
index 0000000..66dcbe0
--- /dev/null
@@ -0,0 +1,75 @@
+From 2687c848e57820651b9f69d30c4710f4219f7dbf Mon Sep 17 00:00:00 2001
+From: Josh Poimboeuf <jpoimboe@kernel.org>
+Date: Fri, 6 Feb 2026 14:24:55 -0800
+Subject: x86/vmware: Fix hypercall clobbers
+
+From: Josh Poimboeuf <jpoimboe@kernel.org>
+
+commit 2687c848e57820651b9f69d30c4710f4219f7dbf upstream.
+
+Fedora QA reported the following panic:
+
+  BUG: unable to handle page fault for address: 0000000040003e54
+  #PF: supervisor write access in kernel mode
+  #PF: error_code(0x0002) - not-present page
+  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20251119-3.fc43 11/19/2025
+  RIP: 0010:vmware_hypercall4.constprop.0+0x52/0x90
+  ..
+  Call Trace:
+   vmmouse_report_events+0x13e/0x1b0
+   psmouse_handle_byte+0x15/0x60
+   ps2_interrupt+0x8a/0xd0
+   ...
+
+because the QEMU VMware mouse emulation is buggy, and clears the top 32
+bits of %rdi that the kernel kept a pointer in.
+
+The QEMU vmmouse driver saves and restores the register state in a
+"uint32_t data[6];" and as a result restores the state with the high
+bits all cleared.
+
+RDI originally contained the value of a valid kernel stack address
+(0xff5eeb3240003e54).  After the vmware hypercall it now contains
+0x40003e54, and we get a page fault as a result when it is dereferenced.
+
+The proper fix would be in QEMU, but this works around the issue in the
+kernel to keep old setups working, when old kernels had not happened to
+keep any state in %rdi over the hypercall.
+
+In theory this same issue exists for all the hypercalls in the vmmouse
+driver; in practice it has only been seen with vmware_hypercall3() and
+vmware_hypercall4().  For now, just mark RDI/RSI as clobbered for those
+two calls.  This should have a minimal effect on code generation overall
+as it should be rare for the compiler to want to make RDI/RSI live
+across hypercalls.
+
+Reported-by: Justin Forbes <jforbes@fedoraproject.org>
+Link: https://lore.kernel.org/all/99a9c69a-fc1a-43b7-8d1e-c42d6493b41f@broadcom.com/
+Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Cc: stable@kernel.org
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/vmware.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/include/asm/vmware.h
++++ b/arch/x86/include/asm/vmware.h
+@@ -140,7 +140,7 @@ unsigned long vmware_hypercall3(unsigned
+                 "b" (in1),
+                 "c" (cmd),
+                 "d" (0)
+-              : "cc", "memory");
++              : "di", "si", "cc", "memory");
+       return out0;
+ }
+@@ -165,7 +165,7 @@ unsigned long vmware_hypercall4(unsigned
+                 "b" (in1),
+                 "c" (cmd),
+                 "d" (0)
+-              : "cc", "memory");
++              : "di", "si", "cc", "memory");
+       return out0;
+ }