Linux Power Management development
 help / color / mirror / Atom feed
* Re: [PATCH v5 0/3] Fix swapoff race and cleanup in hibernation swap path
From: Andrew Morton @ 2026-03-20  2:50 UTC (permalink / raw)
  To: Youngjun Park
  Cc: rafael, chrisl, kasong, pavel, shikemeng, nphamcs, bhe, baohua,
	usama.arif, linux-mm, linux-pm
In-Reply-To: <20260319142404.3683019-1-youngjun.park@lge.com>

On Thu, 19 Mar 2026 23:24:01 +0900 Youngjun Park <youngjun.park@lge.com> wrote:

> Currently, in the uswsusp path, only the swap type value is retrieved at
> lookup time without holding a reference. If swapoff races after the type
> is acquired, subsequent slot allocations operate on a stale swap device.
> 
> Additionally, grabbing and releasing the swap device reference on every
> slot allocation is inefficient across the entire hibernation swap path.

AI review has questions:
	https://sashiko.dev/#/patchset/20260319142404.3683019-1-youngjun.park%40lge.com

^ permalink raw reply

* [PATCH v3 1/1] writeback: don't block sync for filesystems with no data integrity guarantees
From: Joanne Koong @ 2026-03-20  0:51 UTC (permalink / raw)
  To: brauner
  Cc: linux-fsdevel, jack, miklos, david, therealgraysky, linux-pm,
	stable
In-Reply-To: <20260320005145.2483161-1-joannelkoong@gmail.com>

Add a SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot
guarantee data persistence on sync (eg fuse). For superblocks with this
flag set, sync kicks off writeback of dirty inodes but does not wait
for the flusher threads to complete the writeback.

This replaces the per-inode AS_NO_DATA_INTEGRITY mapping flag added in
commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY mappings
in wait_sb_inodes()"). The flag belongs at the superblock level because
data integrity is a filesystem-wide property, not a per-inode one.
Having this flag at the superblock level also allows us to skip having
to iterate every dirty inode in wait_sb_inodes() only to skip each inode
individually.

Prior to this commit, mappings with no data integrity guarantees skipped
waiting on writeback completion but still waited on the flusher threads
to finish initiating the writeback. Waiting on the flusher threads is
unnecessary. This commit kicks off writeback but does not wait on the
flusher threads. This change properly addresses a recent report [1] for
a suspend-to-RAM hang seen on fuse-overlayfs that was caused by waiting
on the flusher threads to finish:

Workqueue: pm_fs_sync pm_fs_sync_work_fn
Call Trace:
 <TASK>
 __schedule+0x457/0x1720
 schedule+0x27/0xd0
 wb_wait_for_completion+0x97/0xe0
 sync_inodes_sb+0xf8/0x2e0
 __iterate_supers+0xdc/0x160
 ksys_sync+0x43/0xb0
 pm_fs_sync_work_fn+0x17/0xa0
 process_one_work+0x193/0x350
 worker_thread+0x1a1/0x310
 kthread+0xfc/0x240
 ret_from_fork+0x243/0x280
 ret_from_fork_asm+0x1a/0x30
 </TASK>

On fuse this is problematic because there are paths that may cause the
flusher thread to block (eg if systemd freezes the user session cgroups
first, which freezes the fuse daemon, before invoking the kernel
suspend. The kernel suspend triggers ->write_node() which on fuse issues
a synchronous setattr request, which cannot be processed since the
daemon is frozen. Or if the daemon is buggy and cannot properly complete
writeback, initiating writeback on a dirty folio already under writeback
leads to writeback_get_folio() -> folio_prepare_writeback() ->
unconditional wait on writeback to finish, which will cause a hang).
This commit restores fuse to its prior behavior before tmp folios were
removed, where sync was essentially a no-op.

[1] https://lore.kernel.org/linux-fsdevel/CAJnrk1a-asuvfrbKXbEwwDSctvemF+6zfhdnuzO65Pt8HsFSRw@mail.gmail.com/T/#m632c4648e9cafc4239299887109ebd880ac6c5c1

Fixes: 0c58a97f919c ("fuse: remove tmp folio for writebacks and internal rb tree")
Reported-by: John <therealgraysky@proton.me>
Cc: <stable@vger.kernel.org>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 fs/fs-writeback.c              | 18 ++++++++++++------
 fs/fuse/file.c                 |  4 +---
 fs/fuse/inode.c                |  1 +
 include/linux/fs/super_types.h |  1 +
 include/linux/pagemap.h        | 11 -----------
 5 files changed, 15 insertions(+), 20 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 7c75ed7e8979..dd6225736721 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -2775,13 +2775,8 @@ static void wait_sb_inodes(struct super_block *sb)
 		 * The mapping can appear untagged while still on-list since we
 		 * do not have the mapping lock. Skip it here, wb completion
 		 * will remove it.
-		 *
-		 * If the mapping does not have data integrity semantics,
-		 * there's no need to wait for the writeout to complete, as the
-		 * mapping cannot guarantee that data is persistently stored.
 		 */
-		if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK) ||
-		    mapping_no_data_integrity(mapping))
+		if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK))
 			continue;
 
 		spin_unlock_irq(&sb->s_inode_wblist_lock);
@@ -2916,6 +2911,17 @@ void sync_inodes_sb(struct super_block *sb)
 	 */
 	if (bdi == &noop_backing_dev_info)
 		return;
+
+	/*
+	 * If the superblock has SB_I_NO_DATA_INTEGRITY set, there's no need to
+	 * wait for the writeout to complete, as the filesystem cannot guarantee
+	 * data persistence on sync. Just kick off writeback and return.
+	 */
+	if (sb->s_iflags & SB_I_NO_DATA_INTEGRITY) {
+		wakeup_flusher_threads_bdi(bdi, WB_REASON_SYNC);
+		return;
+	}
+
 	WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
 	/* protect against inode wb switch, see inode_switch_wbs_work_fn() */
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a9c836d7f586..f6240f24b814 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3202,10 +3202,8 @@ void fuse_init_file_inode(struct inode *inode, unsigned int flags)
 
 	inode->i_fop = &fuse_file_operations;
 	inode->i_data.a_ops = &fuse_file_aops;
-	if (fc->writeback_cache) {
+	if (fc->writeback_cache)
 		mapping_set_writeback_may_deadlock_on_reclaim(&inode->i_data);
-		mapping_set_no_data_integrity(&inode->i_data);
-	}
 
 	INIT_LIST_HEAD(&fi->write_files);
 	INIT_LIST_HEAD(&fi->queued_writes);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e57b8af06be9..c795abe47a4f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1709,6 +1709,7 @@ static void fuse_sb_defaults(struct super_block *sb)
 	sb->s_export_op = &fuse_export_operations;
 	sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
 	sb->s_iflags |= SB_I_NOIDMAP;
+	sb->s_iflags |= SB_I_NO_DATA_INTEGRITY;
 	if (sb->s_user_ns != &init_user_ns)
 		sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
 	sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
diff --git a/include/linux/fs/super_types.h b/include/linux/fs/super_types.h
index fa7638b81246..383050e7fdf5 100644
--- a/include/linux/fs/super_types.h
+++ b/include/linux/fs/super_types.h
@@ -338,5 +338,6 @@ struct super_block {
 #define SB_I_NOUMASK	0x00001000	/* VFS does not apply umask */
 #define SB_I_NOIDMAP	0x00002000	/* No idmapped mounts on this superblock */
 #define SB_I_ALLOW_HSM	0x00004000	/* Allow HSM events on this superblock */
+#define SB_I_NO_DATA_INTEGRITY	0x00008000 /* fs cannot guarantee data persistence on sync */
 
 #endif /* _LINUX_FS_SUPER_TYPES_H */
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index ec442af3f886..31a848485ad9 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -210,7 +210,6 @@ enum mapping_flags {
 	AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM = 9,
 	AS_KERNEL_FILE = 10,	/* mapping for a fake kernel file that shouldn't
 				   account usage to user cgroups */
-	AS_NO_DATA_INTEGRITY = 11, /* no data integrity guarantees */
 	/* Bits 16-25 are used for FOLIO_ORDER */
 	AS_FOLIO_ORDER_BITS = 5,
 	AS_FOLIO_ORDER_MIN = 16,
@@ -346,16 +345,6 @@ static inline bool mapping_writeback_may_deadlock_on_reclaim(const struct addres
 	return test_bit(AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM, &mapping->flags);
 }
 
-static inline void mapping_set_no_data_integrity(struct address_space *mapping)
-{
-	set_bit(AS_NO_DATA_INTEGRITY, &mapping->flags);
-}
-
-static inline bool mapping_no_data_integrity(const struct address_space *mapping)
-{
-	return test_bit(AS_NO_DATA_INTEGRITY, &mapping->flags);
-}
-
 static inline gfp_t mapping_gfp_mask(const struct address_space *mapping)
 {
 	return mapping->gfp_mask;
-- 
2.52.0


^ permalink raw reply related

* [PATCH v3 0/1] writeback: don't block sync for filesystems with no data integrity guarantees
From: Joanne Koong @ 2026-03-20  0:51 UTC (permalink / raw)
  To: brauner; +Cc: linux-fsdevel, jack, miklos, david, therealgraysky, linux-pm

Changelog
---------
v2: https://lore.kernel.org/linux-fsdevel/20260319194540.3463371-1-joannelkoong@gmail.com/
v2 -> v3:
* Move SB_I_NO_DATA_INTEGRITY check to sync_inodes_sb() instead of
  sync_inodes_one_sb() (David)
* Move comment block (David)

v1: https://lore.kernel.org/linux-fsdevel/20260318225604.71545-1-joannelkoong@gmail.com/
v1 -> v2:
* Still kick off flusher threads for writeback for SB_I_NO_DATA_INTEGRITY,
  instead of skipping that entirely (Jan)
* Improve commit message (me)

Joanne Koong (1):
  writeback: don't block sync for filesystems with no data integrity
    guarantees

 fs/fs-writeback.c              | 18 ++++++++++++------
 fs/fuse/file.c                 |  4 +---
 fs/fuse/inode.c                |  1 +
 include/linux/fs/super_types.h |  1 +
 include/linux/pagemap.h        | 11 -----------
 5 files changed, 15 insertions(+), 20 deletions(-)

-- 
2.52.0


^ permalink raw reply

* Re: [PATCH v2 1/1] writeback: don't block sync(2) for filesystems with no data integrity guarantees
From: Joanne Koong @ 2026-03-19 23:55 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: brauner, linux-fsdevel, jack, miklos, therealgraysky, linux-pm,
	stable
In-Reply-To: <1f1dafa7-54c7-4eae-a19e-5ec1be391079@kernel.org>

On Thu, Mar 19, 2026 at 2:26 PM David Hildenbrand (Arm)
<david@kernel.org> wrote:
>
> On 3/19/26 20:45, Joanne Koong wrote:
> > Add a SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot
> > guarantee data persistence on sync (eg fuse). For superblocks with this
> > flag set, sync(2) kicks off writeback of dirty inodes but does not wait
> > for the flusher threads to complete the writeback.
> >
> > This replaces the per-inode AS_NO_DATA_INTEGRITY mapping flag added in
> > commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY mappings
> > in wait_sb_inodes()"). The flag belongs at the superblock level because
> > data integrity is a filesystem-wide property, not a per-inode one.
> > Having this flag at the superblock level allows us to skip the logic in
> > sync_inodes_sb() entirely, rather than iterating every dirty inode in
> > wait_sb_inodes() only to skip each inode individually.
>
> Makes sense to me.
>
> [...]
>
> >       if (sb->s_user_ns != &init_user_ns)
> >               sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
> >       sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
> > diff --git a/fs/sync.c b/fs/sync.c
> > index 942a60cfedfb..aedbf723830a 100644
> > --- a/fs/sync.c
> > +++ b/fs/sync.c
> > @@ -73,7 +73,12 @@ EXPORT_SYMBOL(sync_filesystem);
> >
> >  static void sync_inodes_one_sb(struct super_block *sb, void *arg)
> >  {
> > -     if (!sb_rdonly(sb))
> > +     if (sb_rdonly(sb))
> > +             return;
> > +
>
> Should we move some of the comment you deleting over here?

That's a good idea - I'll bring back the comment block that was
previously in wait_sb_inodes() and move it here

>
> > +     if (sb->s_iflags & SB_I_NO_DATA_INTEGRITY)
> > +             wakeup_flusher_threads_bdi(sb->s_bdi, WB_REASON_SYNC);
> > +     else
> >               sync_inodes_sb(sb);
> >  }
> I was wondering whether that handling should be moved to
> sync_inodes_sb(), so it would catch any (existing+future) callers.
>
> Alternatively, we could catch abuse by adding a warning to sync_inodes_sb.

Thinking about this some more, I think you're right.

At the vfs layer, the only other relevant callers are
generic_shutdown_super() when handling an unmount and syncfs for
syncing a specific fd. For these, I was thinking it'd be more useful
to return after writeback has actually completed, since the caller has
to directly invoke the operation on a specific fd/mount. But that's
wrong, we shouldn't be picking and choosing which syncs are ok vs not
ok to wait for. And I'm realizing now there's also the
hibernate/suspend call paths that call filesystems_freeze_callback()
which can also call into sync_filesystem() -> sync_inodes_sb()...

I'll make this change for v3.

Thanks,
Joanne

>
> --
> Cheers,
>
> David

^ permalink raw reply

* Re: [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
From: Nhat Pham @ 2026-03-19 23:27 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, pfalcato, rafael, rakie.kim,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
	zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <20260319210319.GK3738786@noisy.programming.kicks-ass.net>

On Thu, Mar 19, 2026 at 2:03 PM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Thu, Mar 19, 2026 at 11:37:19AM -0700, Nhat Pham wrote:
> > On Thu, Mar 19, 2026 at 12:56 AM Peter Zijlstra <peterz@infradead.org> wrote:
> > >
> > > On Wed, Mar 18, 2026 at 03:29:40PM -0700, Nhat Pham wrote:
> > > > diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> > > > index 62cd7b35a29c9..85cb45022e796 100644
> > > > --- a/include/linux/cpuhotplug.h
> > > > +++ b/include/linux/cpuhotplug.h
> > > > @@ -86,6 +86,7 @@ enum cpuhp_state {
> > > >       CPUHP_FS_BUFF_DEAD,
> > > >       CPUHP_PRINTK_DEAD,
> > > >       CPUHP_MM_MEMCQ_DEAD,
> > > > +     CPUHP_MM_VSWAP_DEAD,
> > > >       CPUHP_PERCPU_CNT_DEAD,
> > > >       CPUHP_RADIX_DEAD,
> > > >       CPUHP_PAGE_ALLOC,
> > >
> > > > +static int vswap_cpu_dead(unsigned int cpu)
> > > > +{
> > > > +     struct vswap_cluster *cluster;
> > > > +     int order;
> > > > +
> > > > +     rcu_read_lock();
> > >
> > > nit:
> > >         guard(rcu)();
> > >
> > > > +     for (order = 0; order < SWAP_NR_ORDERS; order++) {
> > > > +             cluster = per_cpu(percpu_vswap_cluster.clusters[order], cpu);
> > > > +             if (cluster) {
> > > > +                     per_cpu(percpu_vswap_cluster.clusters[order], cpu) = NULL;
> > > > +                     spin_lock(&cluster->lock);
> > >
> > > This breaks on PREEMPT_RT as this is ran with IRQs disabled. This must
> > > be a raw_spinlock_t.
> > >
> > > > +                     cluster->cached = false;
> > > > +                     if (refcount_dec_and_test(&cluster->refcnt))
> > > > +                             vswap_cluster_free(cluster);
> > >
> > > And this... below.
> > >
> > > > +                     spin_unlock(&cluster->lock);
> > > > +             }
> > > > +     }
> > > > +     rcu_read_unlock();
> > > > +
> > > > +     return 0;
> > > > +}
> > >
> > > > +static void vswap_cluster_free(struct vswap_cluster *cluster)
> > > > +{
> > > > +     VM_WARN_ON(cluster->count || cluster->cached);
> > > > +     VM_WARN_ON(!spin_is_locked(&cluster->lock));
> > >
> > > This is terrible, please use:
> > >
> > >         lockdep_assert_held(&cluster->lock);
> > >
> > > > +     xa_lock(&vswap_cluster_map);
> > >
> > > This is again broken, this cannot be from a DEAD callback with IRQs
> > > disabled.
> > >
> > > > +     list_del_init(&cluster->list);
> > > > +     __xa_erase(&vswap_cluster_map, cluster->id);
> > >
> > > Strictly speaking this can end up in xas_alloc(), which is again, not
> > > allowed in a DEAD callback.
> >
> > I see. I'll take a look at this. Thanks for pointing this out, Peter!
>
> Oh, I think I might have confused DEAD and DYING here. DYING is the
> tricky one, DEAD should be okay. Sorry about that.

No worries at all. Thanks for help taking a look - the other comment
regarding lock-checking still hold regardless, and will be amended in
the next version :)

I'll stare at it a bit more while the context of this portion of the
code is still in my head.

^ permalink raw reply

* Re: [syzbot ci] Re: Virtual Swap Space
From: Nhat Pham @ 2026-03-19 23:26 UTC (permalink / raw)
  To: syzbot ci
  Cc: akpm, apopple, axelrasmussen, baohua, baolin.wang, bhe, byungchul,
	cgroups, chengming.zhou, chrisl, corbet, david, dev.jain, gourry,
	hannes, hughd, jannh, joshua.hahnjy, kasong, kernel-team,
	lance.yang, lenb, liam.howlett, linux-doc, linux-kernel, linux-mm,
	linux-pm, lorenzo.stoakes, matthew.brost, mhocko, muchun.song,
	npache, pavel, peterx, peterz, pfalcato, rafael, rakie.kim, riel,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, syzbot, syzkaller-bugs
In-Reply-To: <69bc6c4f.050a0220.3bf4de.0001.GAE@google.com>

On Thu, Mar 19, 2026 at 2:36 PM syzbot ci
<syzbot+ci0215525ee2c0ed89@syzkaller.appspotmail.com> wrote:
>
> syzbot ci has tested the following series
>
> [v4] Virtual Swap Space
> https://lore.kernel.org/all/20260318222953.441758-1-nphamcs@gmail.com
> * [PATCH v4 01/21] mm/swap: decouple swap cache from physical swap infrastructure
> * [PATCH v4 02/21] swap: rearrange the swap header file
> * [PATCH v4 03/21] mm: swap: add an abstract API for locking out swapoff
> * [PATCH v4 04/21] zswap: add new helpers for zswap entry operations
> * [PATCH v4 05/21] mm/swap: add a new function to check if a swap entry is in swap cached.
> * [PATCH v4 06/21] mm: swap: add a separate type for physical swap slots
> * [PATCH v4 07/21] mm: create scaffolds for the new virtual swap implementation
> * [PATCH v4 08/21] zswap: prepare zswap for swap virtualization
> * [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
> * [PATCH v4 10/21] swap: move swap cache to virtual swap descriptor
> * [PATCH v4 11/21] zswap: move zswap entry management to the virtual swap descriptor
> * [PATCH v4 12/21] swap: implement the swap_cgroup API using virtual swap
> * [PATCH v4 13/21] swap: manage swap entry lifecycle at the virtual swap layer
> * [PATCH v4 14/21] mm: swap: decouple virtual swap slot from backing store
> * [PATCH v4 15/21] zswap: do not start zswap shrinker if there is no physical swap slots
> * [PATCH v4 16/21] swap: do not unnecesarily pin readahead swap entries
> * [PATCH v4 17/21] swapfile: remove zeromap bitmap
> * [PATCH v4 18/21] memcg: swap: only charge physical swap slots
> * [PATCH v4 19/21] swap: simplify swapoff using virtual swap
> * [PATCH v4 20/21] swapfile: replace the swap map with bitmaps
> * [PATCH v4 21/21] vswap: batch contiguous vswap free calls
>
> and found the following issue:
> possible deadlock in vswap_iter
>
> Full report is available here:
> https://ci.syzbot.org/series/f8238a2a-370e-404d-b3f7-5945b574bd63
>
> ***
>
> possible deadlock in vswap_iter
>
> tree:      bpf-next
> URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git
> base:      05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
> arch:      amd64
> compiler:  Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
> config:    https://ci.syzbot.org/builds/cf1517a6-d391-46d8-bfbe-98e6be6b93ce/config
> syz repro: https://ci.syzbot.org/findings/b4e84ae7-17d4-4bf8-9c3f-4c13b10a1e52/syz_repro
>
> ============================================
> WARNING: possible recursive locking detected
> syzkaller #0 Not tainted
> --------------------------------------------
> syz.1.18/6001 is trying to acquire lock:
> ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: spin_lock include/linux/spinlock.h:351 [inline]
> ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: vswap_iter+0xfa/0x1b0 mm/vswap.c:274
>
> but task is already holding lock:
> ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: spin_lock_irq include/linux/spinlock.h:376 [inline]
> ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: swap_cache_lock_irq+0xe2/0x190 mm/vswap.c:1529
>
> other info that might help us debug this:
>  Possible unsafe locking scenario:
>
>        CPU0
>        ----
>   lock(&cluster->lock);
>   lock(&cluster->lock);
>
>  *** DEADLOCK ***
>
>  May be due to missing lock nesting notation
>
> 3 locks held by syz.1.18/6001:
>  #0: ffff8881bb523440 (&mm->mmap_lock){++++}-{4:4}, at: mmap_read_lock include/linux/mmap_lock.h:391 [inline]
>  #0: ffff8881bb523440 (&mm->mmap_lock){++++}-{4:4}, at: madvise_lock+0x152/0x2e0 mm/madvise.c:1789
>  #1: ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: spin_lock_irq include/linux/spinlock.h:376 [inline]
>  #1: ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: swap_cache_lock_irq+0xe2/0x190 mm/vswap.c:1529
>  #2: ffffffff8e55a360 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:331 [inline]
>  #2: ffffffff8e55a360 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:867 [inline]
>  #2: ffffffff8e55a360 (rcu_read_lock){....}-{1:3}, at: vswap_cgroup_record+0x41/0x440 mm/vswap.c:1909
>
> stack backtrace:
> CPU: 0 UID: 0 PID: 6001 Comm: syz.1.18 Not tainted syzkaller #0 PREEMPT(full)
> Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
> Call Trace:
>  <TASK>
>  dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
>  print_deadlock_bug+0x279/0x290 kernel/locking/lockdep.c:3041
>  check_deadlock kernel/locking/lockdep.c:3093 [inline]
>  validate_chain kernel/locking/lockdep.c:3895 [inline]
>  __lock_acquire+0x253f/0x2cf0 kernel/locking/lockdep.c:5237
>  lock_acquire+0x106/0x330 kernel/locking/lockdep.c:5868
>  __raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
>  _raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
>  spin_lock include/linux/spinlock.h:351 [inline]
>  vswap_iter+0xfa/0x1b0 mm/vswap.c:274
>  vswap_cgroup_record+0xeb/0x440 mm/vswap.c:1910
>  swap_cgroup_record+0xc5/0x130 mm/vswap.c:1933
>  memcg1_swapout+0x358/0x9e0 mm/memcontrol-v1.c:623

Good (syz)bot! We're already holding the cluster lock here - shouldn't
need to reacquire the lock.

Should be an easy-ish fix.

^ permalink raw reply

* Re: [PATCH v7 3/7] dax/cxl, hmem: Initialize hmem early and defer dax_cxl binding
From: Dan Williams @ 2026-03-19 23:07 UTC (permalink / raw)
  To: Koralahalli Channabasappa, Smita, Alison Schofield,
	Smita Koralahalli, Jonathan Cameron
  Cc: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm,
	Ard Biesheuvel, Vishal Verma, Ira Weiny, Dan Williams,
	Yazen Ghannam, Dave Jiang, Davidlohr Bueso, Matthew Wilcox,
	Jan Kara, Rafael J . Wysocki, Len Brown, Pavel Machek, Li Ming,
	Jeff Johnson, Ying Huang, Yao Xingtao, Peter Zijlstra,
	Greg Kroah-Hartman, Nathan Fontenot, Terry Bowman, Robert Richter,
	Benjamin Cheatham, Zhijian Li, Borislav Petkov, Tomasz Wolski
In-Reply-To: <b56f55b1-4281-4edf-8aa4-27d0500ebd60@amd.com>

Koralahalli Channabasappa, Smita wrote:
[..]
> > I agree with Jonathan's comments in Patch 6, using __WORK_INITIALIZER or 
> > initializing work in dax_hmem_init() and gating flush on pdev will fix 
> > the WARN — I will add both for v8. But I think the WARN is likely 
> > indicating an ordering issue here..

Yes, Jonathan is right, static initialization is also my expecation.

> > On initial boot, the Makefile ordering ensures dax_hmem_init() runs
> > before cxl_dax_region_init(), so both work items land on system_long_wq
> > in the right order and dax_hmem's deferred work is queued before 
> > dax_cxl's driver registration work.

There is nothing that guarantees that 2 work items in system_long_wq run
in submission order. Unlikely that matters given the explicit flushing.

> > On module reload which Alison is trying here I dont think, modules are 
> > loaded by Makefile order. I think dax_cxl's workqueue is calling 
> > dax_hmem_flush_work() before dax_hmem probe has had a chance to queue 
> > its work, so flush_work() flushes nothing and dax_cxl registers its 
> > driver without waiting.

Module load order does not matter after initial probe completion.

...and dax_hmem is guaranteed to always load before dax_cxl due to the
symbol dependency of dax_hmem_flush_work().

> > __WORK_INITIALIZER fixes the WARN, but doesn't fix the race I guess if 
> > we are hitting that here..
> > 
> > [   34.673051] initcall dax_hmem_init+0x0/0xff0 [dax_hmem] returned 0 
> > after 2225 usecs
> > [   34.676011] calling  cxl_dax_region_init+0x0/0xff0 [dax_cxl] @ 1059
> > 
> > These two lines indicate cxl_dax started after dax_hmem_init() returns 
> > but I dont think that guarantees dax_hmem_platform_probe() has actually 
> > run..
> > 
> > I dont know if wait_for_device_probe() in cxl_dax_region_driver_register
> > might help..
> > 
> > Thanks
> > Smita
> 
> Actually, thinking about this more..
> 
> dax_hmem_initial_probe lives in device.c (built-in) so it survives 
> module reload. On reload it's still true from the first boot. This means 
> hmem_register_device() skips the deferral path entirely..

Yes, that is the expectation.

> The problem is this bypasses the cxl_region_contains_resource() check 
> that the deferred work normally does. On first boot, 
> process_defer_work() walks each range and decides per-range: if CXL 
> covers it, skip. If not, register with HMEM. On reload, that check never 
> happens — whoever registers first via alloc_dax_region() wins, 
> regardless of whether CXL actually covers the range.

Yes, I think you have hit on a real issue. There is no point in having
dax_hmem auto-attach on driver reload. If userspace unloads the driver
it gets to keep the pieces. So that means something like this:

diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
index 15e462589b92..7478bc78a698 100644
--- a/drivers/dax/hmem/hmem.c
+++ b/drivers/dax/hmem/hmem.c
@@ -112,10 +112,12 @@ static int hmem_register_device(struct device *host, int target_nid,
 	    region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
 			      IORES_DESC_CXL) != REGION_DISJOINT) {
 		if (!dax_hmem_initial_probe) {
-			dev_dbg(host, "deferring range to CXL: %pr\n", res);
+			dev_dbg(host, "await CXL initial probe: %pr\n", res);
 			queue_work(system_long_wq, &dax_hmem_work.work);
 			return 0;
 		}
+		dev_dbg(host, "deferring range to CXL: %pr\n", res);
+		return 0;
 	}
 
 	rc = region_intersects_soft_reserve(res->start, resource_size(res));

---

...because if userspace wants to reload the dax_hmem driver, then it
needs to pick what happens with the CXL intersection. Userspace can
always unload cxl_acpi to force everything back to dax_hmem.

Now, you might say, "but this means that if the initial probe results in
a partial result of some regions in dax_hmem and others in dax_cxl, that
state can not be recovered outside of a reboot". I think that is ok.
This mechanism is automatic best-effort workaround for bugs / missing
capabilities in the CXL driver. Module reload fidelity is out of scope.

> So if dax_cxl registers first on reload, it could claim a range that CXL 
> doesn't actually cover, and dax_hmem would lose a range it should own..

With the above change, dax_cxl always wins in the "reload" scenario iff
cxl_acpi is loaded. Otherwise dax_hmem owns all the Soft Reserved.

> I dont know if Im thinking through this right..

You definitely identified the need for that fixup above.

^ permalink raw reply related

* [syzbot ci] Re: Virtual Swap Space
From: syzbot ci @ 2026-03-19 21:36 UTC (permalink / raw)
  To: akpm, apopple, axelrasmussen, baohua, baolin.wang, bhe, byungchul,
	cgroups, chengming.zhou, chrisl, corbet, david, dev.jain, gourry,
	hannes, hughd, jannh, joshua.hahnjy, kasong, kernel-team,
	lance.yang, lenb, liam.howlett, linux-doc, linux-kernel, linux-mm,
	linux-pm, lorenzo.stoakes, matthew.brost, mhocko, muchun.song,
	npache, nphamcs, pavel, peterx, peterz, pfalcato, rafael,
	rakie.kim, riel, roman.gushchin, rppt, ryan.roberts, shakeel.butt,
	shikemeng, surenb, tglx, vbabka, weixugc, ying.huang
  Cc: syzbot, syzkaller-bugs
In-Reply-To: <20260318222953.441758-1-nphamcs@gmail.com>

syzbot ci has tested the following series

[v4] Virtual Swap Space
https://lore.kernel.org/all/20260318222953.441758-1-nphamcs@gmail.com
* [PATCH v4 01/21] mm/swap: decouple swap cache from physical swap infrastructure
* [PATCH v4 02/21] swap: rearrange the swap header file
* [PATCH v4 03/21] mm: swap: add an abstract API for locking out swapoff
* [PATCH v4 04/21] zswap: add new helpers for zswap entry operations
* [PATCH v4 05/21] mm/swap: add a new function to check if a swap entry is in swap cached.
* [PATCH v4 06/21] mm: swap: add a separate type for physical swap slots
* [PATCH v4 07/21] mm: create scaffolds for the new virtual swap implementation
* [PATCH v4 08/21] zswap: prepare zswap for swap virtualization
* [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
* [PATCH v4 10/21] swap: move swap cache to virtual swap descriptor
* [PATCH v4 11/21] zswap: move zswap entry management to the virtual swap descriptor
* [PATCH v4 12/21] swap: implement the swap_cgroup API using virtual swap
* [PATCH v4 13/21] swap: manage swap entry lifecycle at the virtual swap layer
* [PATCH v4 14/21] mm: swap: decouple virtual swap slot from backing store
* [PATCH v4 15/21] zswap: do not start zswap shrinker if there is no physical swap slots
* [PATCH v4 16/21] swap: do not unnecesarily pin readahead swap entries
* [PATCH v4 17/21] swapfile: remove zeromap bitmap
* [PATCH v4 18/21] memcg: swap: only charge physical swap slots
* [PATCH v4 19/21] swap: simplify swapoff using virtual swap
* [PATCH v4 20/21] swapfile: replace the swap map with bitmaps
* [PATCH v4 21/21] vswap: batch contiguous vswap free calls

and found the following issue:
possible deadlock in vswap_iter

Full report is available here:
https://ci.syzbot.org/series/f8238a2a-370e-404d-b3f7-5945b574bd63

***

possible deadlock in vswap_iter

tree:      bpf-next
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git
base:      05f7e89ab9731565d8a62e3b5d1ec206485eeb0b
arch:      amd64
compiler:  Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
config:    https://ci.syzbot.org/builds/cf1517a6-d391-46d8-bfbe-98e6be6b93ce/config
syz repro: https://ci.syzbot.org/findings/b4e84ae7-17d4-4bf8-9c3f-4c13b10a1e52/syz_repro

============================================
WARNING: possible recursive locking detected
syzkaller #0 Not tainted
--------------------------------------------
syz.1.18/6001 is trying to acquire lock:
ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: vswap_iter+0xfa/0x1b0 mm/vswap.c:274

but task is already holding lock:
ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: spin_lock_irq include/linux/spinlock.h:376 [inline]
ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: swap_cache_lock_irq+0xe2/0x190 mm/vswap.c:1529

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&cluster->lock);
  lock(&cluster->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

3 locks held by syz.1.18/6001:
 #0: ffff8881bb523440 (&mm->mmap_lock){++++}-{4:4}, at: mmap_read_lock include/linux/mmap_lock.h:391 [inline]
 #0: ffff8881bb523440 (&mm->mmap_lock){++++}-{4:4}, at: madvise_lock+0x152/0x2e0 mm/madvise.c:1789
 #1: ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: spin_lock_irq include/linux/spinlock.h:376 [inline]
 #1: ffff88811fba0018 (&cluster->lock){+.+.}-{3:3}, at: swap_cache_lock_irq+0xe2/0x190 mm/vswap.c:1529
 #2: ffffffff8e55a360 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:331 [inline]
 #2: ffffffff8e55a360 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:867 [inline]
 #2: ffffffff8e55a360 (rcu_read_lock){....}-{1:3}, at: vswap_cgroup_record+0x41/0x440 mm/vswap.c:1909

stack backtrace:
CPU: 0 UID: 0 PID: 6001 Comm: syz.1.18 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
Call Trace:
 <TASK>
 dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
 print_deadlock_bug+0x279/0x290 kernel/locking/lockdep.c:3041
 check_deadlock kernel/locking/lockdep.c:3093 [inline]
 validate_chain kernel/locking/lockdep.c:3895 [inline]
 __lock_acquire+0x253f/0x2cf0 kernel/locking/lockdep.c:5237
 lock_acquire+0x106/0x330 kernel/locking/lockdep.c:5868
 __raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
 _raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
 spin_lock include/linux/spinlock.h:351 [inline]
 vswap_iter+0xfa/0x1b0 mm/vswap.c:274
 vswap_cgroup_record+0xeb/0x440 mm/vswap.c:1910
 swap_cgroup_record+0xc5/0x130 mm/vswap.c:1933
 memcg1_swapout+0x358/0x9e0 mm/memcontrol-v1.c:623
 __remove_mapping+0x7d4/0xa70 mm/vmscan.c:762
 shrink_folio_list+0x287c/0x5160 mm/vmscan.c:1518
 reclaim_folio_list+0x100/0x400 mm/vmscan.c:2198
 reclaim_pages+0x45b/0x530 mm/vmscan.c:2235
 madvise_cold_or_pageout_pte_range+0x1eac/0x2220 mm/madvise.c:444
 walk_pmd_range mm/pagewalk.c:130 [inline]
 walk_pud_range mm/pagewalk.c:224 [inline]
 walk_p4d_range mm/pagewalk.c:262 [inline]
 walk_pgd_range+0x1032/0x1d30 mm/pagewalk.c:303
 __walk_page_range+0x14c/0x710 mm/pagewalk.c:410
 walk_page_range_vma_unsafe+0x309/0x410 mm/pagewalk.c:714
 madvise_pageout_page_range mm/madvise.c:622 [inline]
 madvise_pageout mm/madvise.c:647 [inline]
 madvise_vma_behavior+0x2951/0x43c0 mm/madvise.c:1366
 madvise_walk_vmas+0x57a/0xaf0 mm/madvise.c:1721
 madvise_do_behavior+0x386/0x540 mm/madvise.c:1937
 do_madvise+0x1fa/0x2e0 mm/madvise.c:2030
 __do_sys_madvise mm/madvise.c:2039 [inline]
 __se_sys_madvise mm/madvise.c:2037 [inline]
 __x64_sys_madvise+0xa6/0xc0 mm/madvise.c:2037
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2b3459c799
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f2b35495028 EFLAGS: 00000246 ORIG_RAX: 000000000000001c
RAX: ffffffffffffffda RBX: 00007f2b34815fa0 RCX: 00007f2b3459c799
RDX: 0000000000000015 RSI: 0000000000600000 RDI: 0000200000000000
RBP: 00007f2b34632c99 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f2b34816038 R14: 00007f2b34815fa0 R15: 00007ffcfbbae8f8
 </TASK>


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

^ permalink raw reply

* Re: [PATCH v2 1/1] writeback: don't block sync(2) for filesystems with no data integrity guarantees
From: David Hildenbrand (Arm) @ 2026-03-19 21:26 UTC (permalink / raw)
  To: Joanne Koong, brauner
  Cc: linux-fsdevel, jack, miklos, therealgraysky, linux-pm, stable
In-Reply-To: <20260319194540.3463371-2-joannelkoong@gmail.com>

On 3/19/26 20:45, Joanne Koong wrote:
> Add a SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot
> guarantee data persistence on sync (eg fuse). For superblocks with this
> flag set, sync(2) kicks off writeback of dirty inodes but does not wait
> for the flusher threads to complete the writeback.
> 
> This replaces the per-inode AS_NO_DATA_INTEGRITY mapping flag added in
> commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY mappings
> in wait_sb_inodes()"). The flag belongs at the superblock level because
> data integrity is a filesystem-wide property, not a per-inode one.
> Having this flag at the superblock level allows us to skip the logic in
> sync_inodes_sb() entirely, rather than iterating every dirty inode in
> wait_sb_inodes() only to skip each inode individually.

Makes sense to me.

[...]

>  	if (sb->s_user_ns != &init_user_ns)
>  		sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
>  	sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
> diff --git a/fs/sync.c b/fs/sync.c
> index 942a60cfedfb..aedbf723830a 100644
> --- a/fs/sync.c
> +++ b/fs/sync.c
> @@ -73,7 +73,12 @@ EXPORT_SYMBOL(sync_filesystem);
>  
>  static void sync_inodes_one_sb(struct super_block *sb, void *arg)
>  {
> -	if (!sb_rdonly(sb))
> +	if (sb_rdonly(sb))
> +		return;
> +

Should we move some of the comment you deleting over here?

> +	if (sb->s_iflags & SB_I_NO_DATA_INTEGRITY)
> +		wakeup_flusher_threads_bdi(sb->s_bdi, WB_REASON_SYNC);
> +	else
>  		sync_inodes_sb(sb);
>  }
I was wondering whether that handling should be moved to
sync_inodes_sb(), so it would catch any (existing+future) callers.

Alternatively, we could catch abuse by adding a warning to sync_inodes_sb.

-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
From: Peter Zijlstra @ 2026-03-19 21:03 UTC (permalink / raw)
  To: Nhat Pham
  Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, pfalcato, rafael, rakie.kim,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
	zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAKEwX=MUrLtZAcmwqBau5GLnWQrjL7A_4tYrdZ4TQQaE+hsVkA@mail.gmail.com>

On Thu, Mar 19, 2026 at 11:37:19AM -0700, Nhat Pham wrote:
> On Thu, Mar 19, 2026 at 12:56 AM Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > On Wed, Mar 18, 2026 at 03:29:40PM -0700, Nhat Pham wrote:
> > > diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> > > index 62cd7b35a29c9..85cb45022e796 100644
> > > --- a/include/linux/cpuhotplug.h
> > > +++ b/include/linux/cpuhotplug.h
> > > @@ -86,6 +86,7 @@ enum cpuhp_state {
> > >       CPUHP_FS_BUFF_DEAD,
> > >       CPUHP_PRINTK_DEAD,
> > >       CPUHP_MM_MEMCQ_DEAD,
> > > +     CPUHP_MM_VSWAP_DEAD,
> > >       CPUHP_PERCPU_CNT_DEAD,
> > >       CPUHP_RADIX_DEAD,
> > >       CPUHP_PAGE_ALLOC,
> >
> > > +static int vswap_cpu_dead(unsigned int cpu)
> > > +{
> > > +     struct vswap_cluster *cluster;
> > > +     int order;
> > > +
> > > +     rcu_read_lock();
> >
> > nit:
> >         guard(rcu)();
> >
> > > +     for (order = 0; order < SWAP_NR_ORDERS; order++) {
> > > +             cluster = per_cpu(percpu_vswap_cluster.clusters[order], cpu);
> > > +             if (cluster) {
> > > +                     per_cpu(percpu_vswap_cluster.clusters[order], cpu) = NULL;
> > > +                     spin_lock(&cluster->lock);
> >
> > This breaks on PREEMPT_RT as this is ran with IRQs disabled. This must
> > be a raw_spinlock_t.
> >
> > > +                     cluster->cached = false;
> > > +                     if (refcount_dec_and_test(&cluster->refcnt))
> > > +                             vswap_cluster_free(cluster);
> >
> > And this... below.
> >
> > > +                     spin_unlock(&cluster->lock);
> > > +             }
> > > +     }
> > > +     rcu_read_unlock();
> > > +
> > > +     return 0;
> > > +}
> >
> > > +static void vswap_cluster_free(struct vswap_cluster *cluster)
> > > +{
> > > +     VM_WARN_ON(cluster->count || cluster->cached);
> > > +     VM_WARN_ON(!spin_is_locked(&cluster->lock));
> >
> > This is terrible, please use:
> >
> >         lockdep_assert_held(&cluster->lock);
> >
> > > +     xa_lock(&vswap_cluster_map);
> >
> > This is again broken, this cannot be from a DEAD callback with IRQs
> > disabled.
> >
> > > +     list_del_init(&cluster->list);
> > > +     __xa_erase(&vswap_cluster_map, cluster->id);
> >
> > Strictly speaking this can end up in xas_alloc(), which is again, not
> > allowed in a DEAD callback.
> 
> I see. I'll take a look at this. Thanks for pointing this out, Peter!

Oh, I think I might have confused DEAD and DYING here. DYING is the
tricky one, DEAD should be okay. Sorry about that.

^ permalink raw reply

* Re: [PATCH RESEND 0/5] bitmap: cleanup bitmaps printing
From: Yury Norov @ 2026-03-19 20:18 UTC (permalink / raw)
  To: linux-kernel, Christophe Leroy (CS GROUP), Peter Zijlstra (Intel),
	Rafael J. Wysocki, Alexander Shishkin, Daniel Lezcano,
	Ingo Molnar, James Clark, Kees Cook, Lukasz Luba,
	Madhavan Srinivasan, Michael Ellerman, Mike Leach, Moritz Fischer,
	Nicholas Piggin, Russ Weight, Shrikanth Hegde, Suki K Poulose,
	Tom Rix, Thomas Weißschuh, Xu Yilun, Yury Norov, Zhang Rui,
	coresight, linux-arm-kernel, linux-fpga, linux-pm, linuxppc-dev
  Cc: Jakub Kicinski
In-Reply-To: <20260303200842.124996-1-ynorov@nvidia.com>

Ping?

On Tue, Mar 03, 2026 at 03:08:36PM -0500, Yury Norov wrote:
> Bitmap API has a bitmap_print_to_pagebuf() function that is intended to
> print bitmap into a human readable format, making sure that the output
> string will not get big enough to cross the current page limit.
> 
> Some drivers use this function immediately before passing the result to
> scnprintf() with no modification. This is useless because scnprintf(),
> and helpers based on it like seq_pritf() and sysfs_emit(), take care of
> not overflowing the buffer by itself, and perfectly print bitmaps with
> "%*pb[l]".
> 
> This is a resend of non-networking part of [1]. Patches #3,5 switch from
> plain scnprintf() to sysfs_emit(), as pointed out by Thomas Weißschuh.
> 
> [1] https://lore.kernel.org/all/20260219181407.290201-1-ynorov@nvidia.com/
> 
> The networking part, for reference:
> 
> https://lore.kernel.org/all/20260303185507.111841-1-ynorov@nvidia.com/
> 
> Each patch can be applied individually per corresponding subsystem.
> 
> Yury Norov (5):
>   powerpc/xive: simplify xive_spapr_debug_show()
>   thermal: intel: switch cpumask_get() to using
>     cpumask_print_to_pagebuf()
>   coresight: don't use bitmap_print_to_pagebuf()
>   lib/prime_numbers: drop temporary buffer in dump_primes()
>   fpga: m10bmc-sec: switch show_canceled_csk() to using sysfs_emit()
> 
>  arch/powerpc/sysdev/xive/spapr.c              | 12 ++-----
>  drivers/fpga/intel-m10-bmc-sec-update.c       |  3 +-
>  .../hwtracing/coresight/coresight-cti-sysfs.c | 32 ++++++++-----------
>  drivers/thermal/intel/intel_powerclamp.c      |  3 +-
>  lib/math/tests/prime_numbers_kunit.c          |  6 ++--
>  5 files changed, 21 insertions(+), 35 deletions(-)
> 
> -- 
> 2.43.0

^ permalink raw reply

* Re: [PATCH v7 6/7] dax/hmem, cxl: Defer and resolve Soft Reserved ownership
From: Alison Schofield @ 2026-03-19 20:03 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Smita Koralahalli, linux-cxl, linux-kernel, nvdimm, linux-fsdevel,
	linux-pm, Ard Biesheuvel, Vishal Verma, Ira Weiny, Dan Williams,
	Yazen Ghannam, Dave Jiang, Davidlohr Bueso, Matthew Wilcox,
	Jan Kara, Rafael J . Wysocki, Len Brown, Pavel Machek, Li Ming,
	Jeff Johnson, Ying Huang, Yao Xingtao, Peter Zijlstra,
	Greg Kroah-Hartman, Nathan Fontenot, Terry Bowman, Robert Richter,
	Benjamin Cheatham, Zhijian Li, Borislav Petkov, Tomasz Wolski
In-Reply-To: <20260319142910.0000113d@huawei.com>

On Thu, Mar 19, 2026 at 02:29:10PM +0000, Jonathan Cameron wrote:
> On Thu, 19 Mar 2026 01:14:59 +0000
> Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> wrote:
> 
> > The current probe time ownership check for Soft Reserved memory based
> > solely on CXL window intersection is insufficient. dax_hmem probing is not
> > always guaranteed to run after CXL enumeration and region assembly, which
> > can lead to incorrect ownership decisions before the CXL stack has
> > finished publishing windows and assembling committed regions.
> > 
> > Introduce deferred ownership handling for Soft Reserved ranges that
> > intersect CXL windows. When such a range is encountered during the
> > initial dax_hmem probe, schedule deferred work to wait for the CXL stack
> > to complete enumeration and region assembly before deciding ownership.
> > 
> > Once the deferred work runs, evaluate each Soft Reserved range
> > individually: if a CXL region fully contains the range, skip it and let
> > dax_cxl bind. Otherwise, register it with dax_hmem. This per-range
> > ownership model avoids the need for CXL region teardown and
> > alloc_dax_region() resource exclusion prevents double claiming.
> > 
> > Introduce a boolean flag dax_hmem_initial_probe to live inside device.c
> > so it survives module reload. Ensure dax_cxl defers driver registration
> > until dax_hmem has completed ownership resolution. dax_cxl calls
> > dax_hmem_flush_work() before cxl_driver_register(), which both waits for
> > the deferred work to complete and creates a module symbol dependency that
> > forces dax_hmem.ko to load before dax_cxl.
> > 
> > Co-developed-by: Dan Williams <dan.j.williams@intel.com>
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
> Hi Smita,
> 
> I think this is very likely to be what is causing the bug Alison
> saw in cxl_test.
> 
> It looks to be possible to flush work before the work structure has
> been configured.  Even though it's not on a work queue and there is
> nothing to do, there are early sanity checks that fail giving the warning
> Alison reported.
> 
> A couple of ways to fix that inline.  I'd be tempted to both initialize
> the function statically and gate against flushing if the whole thing isn't
> set up yet.
> 
> Jonathan

snip

> 
> > diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
> > index 1e3424358490..8c574123bd3b 100644
> > --- a/drivers/dax/hmem/hmem.c
> > +++ b/drivers/dax/hmem/hmem.c
> > @@ -3,6 +3,7 @@
> >  #include <linux/memregion.h>
> >  #include <linux/module.h>
> >  #include <linux/dax.h>
> > +#include <cxl/cxl.h>
> >  #include "../bus.h"
> >  
> >  static bool region_idle;
> > @@ -58,6 +59,19 @@ static void release_hmem(void *pdev)
> >  	platform_device_unregister(pdev);
> >  }
> >  
> > +struct dax_defer_work {
> > +	struct platform_device *pdev;
> > +	struct work_struct work;
> > +};
> > +
> > +static struct dax_defer_work dax_hmem_work;
> 
> static struct dax_defer_work dax_hmem_work = {
> 	.work = __WORK_INITIALIZER(&dax_hmem_work.work,
> 				   process_defer_work),
> };
> or something similar.
> 

Just confirming this stopped the WARN:

-static struct dax_defer_work dax_hmem_work;
+static void process_defer_work(struct work_struct *work);
+
+static struct dax_defer_work dax_hmem_work = {
+        .work = __WORK_INITIALIZER(dax_hmem_work.work, process_defer_work),
+};


> 
> > +
> > +void dax_hmem_flush_work(void)
> > +{
> > +	flush_work(&dax_hmem_work.work);
> > +}
> > +EXPORT_SYMBOL_GPL(dax_hmem_flush_work);
> > +
> >  static int hmem_register_device(struct device *host, int target_nid,
> >  				const struct resource *res)
> >  {
> > @@ -69,8 +83,11 @@ static int hmem_register_device(struct device *host, int target_nid,
> >  	if (IS_ENABLED(CONFIG_DEV_DAX_CXL) &&
> >  	    region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
> >  			      IORES_DESC_CXL) != REGION_DISJOINT) {
> > -		dev_dbg(host, "deferring range to CXL: %pr\n", res);
> > -		return 0;
> > +		if (!dax_hmem_initial_probe) {
> > +			dev_dbg(host, "deferring range to CXL: %pr\n", res);
> > +			queue_work(system_long_wq, &dax_hmem_work.work);
> > +			return 0;
> > +		}
> >  	}
> >  
> >  	rc = region_intersects_soft_reserve(res->start, resource_size(res));
> > @@ -123,8 +140,48 @@ static int hmem_register_device(struct device *host, int target_nid,
> >  	return rc;
> >  }
> >  
> > +static int hmem_register_cxl_device(struct device *host, int target_nid,
> > +				    const struct resource *res)
> > +{
> > +	if (region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
> > +			      IORES_DESC_CXL) == REGION_DISJOINT)
> > +		return 0;
> > +
> > +	if (cxl_region_contains_resource((struct resource *)res)) {
> > +		dev_dbg(host, "CXL claims resource, dropping: %pr\n", res);
> > +		return 0;
> > +	}
> > +
> > +	dev_dbg(host, "CXL did not claim resource, registering: %pr\n", res);
> > +	return hmem_register_device(host, target_nid, res);
> > +}
> > +
> > +static void process_defer_work(struct work_struct *w)
> > +{
> > +	struct dax_defer_work *work = container_of(w, typeof(*work), work);
> > +	struct platform_device *pdev = work->pdev;
> If you do the suggested __INITIALIZE_WORK() then I'd add
> a paranoid
> 
> 	if (!work->pdev)
> 		return;
> We don't actually queue the work before pdev is set, but that might
> be obvious once we spilt up assigning the function and the data
> it uses.
> 
> > +
> > +	wait_for_device_probe();
> > +
> > +	guard(device)(&pdev->dev);
> > +	if (!pdev->dev.driver)
> > +		return;
> > +
> > +	dax_hmem_initial_probe = true;
> > +	walk_hmem_resources(&pdev->dev, hmem_register_cxl_device);
> > +}
> > +
> >  static int dax_hmem_platform_probe(struct platform_device *pdev)
> >  {
> > +	if (work_pending(&dax_hmem_work.work))
> > +		return -EBUSY;
> > +
> > +	if (!dax_hmem_work.pdev) {
> > +		get_device(&pdev->dev);
> > +		dax_hmem_work.pdev = pdev;
> 
> Using the pdev rather than dev breaks the pattern of doing a get_device()
> and assigning in one line. This is a bit ugly.
> 
> 		dax_hmem_work.pdev = to_pci_dev(get_device(&pdev->dev));
> 
> but perhaps makes the association tighter than current code.
> 
> > +		INIT_WORK(&dax_hmem_work.work, process_defer_work);
> 
> See above. I think assigning the work function should be static
> which should resolve the issue Alison was seeing as then it should
> be fine to call flush_work() on the item that isn't on a work queue
> yet but is initialized.
> 
> > +	}
> > +
> >  	return walk_hmem_resources(&pdev->dev, hmem_register_device);
> >  }
> >  
> > @@ -162,6 +219,11 @@ static __init int dax_hmem_init(void)
> >  
> >  static __exit void dax_hmem_exit(void)
> >  {
> > +	flush_work(&dax_hmem_work.work);
> 
> I think this needs to be under the if (dax_hmem_work.pdev) 
> Not sure there is any guarantee dax_hmem_platform_probe() has run
> before we get here otherwise.  Alternative is to assign
> the work function statically.
> 
> 
> 
> > +
> > +	if (dax_hmem_work.pdev)
> > +		put_device(&dax_hmem_work.pdev->dev);
> > +
> >  	platform_driver_unregister(&dax_hmem_driver);
> >  	platform_driver_unregister(&dax_hmem_platform_driver);
> >  }
> 

^ permalink raw reply

* Re: [PATCH v5 3/3] PM: hibernate: fix spurious GFP mask WARNING in uswsusp path
From: Rafael J. Wysocki @ 2026-03-19 19:55 UTC (permalink / raw)
  To: Youngjun Park
  Cc: rafael, akpm, chrisl, kasong, pavel, shikemeng, nphamcs, bhe,
	baohua, usama.arif, linux-mm, linux-pm
In-Reply-To: <20260319142404.3683019-4-youngjun.park@lge.com>

On Thu, Mar 19, 2026 at 3:24 PM Youngjun Park <youngjun.park@lge.com> wrote:
>
> Commit 35e4a69b2003f ("PM: sleep: Allow pm_restrict_gfp_mask()
> stacking") introduced refcount-based GFP mask management that warns
> when pm_restore_gfp_mask() is called with saved_gfp_count == 0:
>
>   WARNING: kernel/power/main.c:44 at pm_restore_gfp_mask+0xd7/0xf0
>   CPU: 0 UID: 0 PID: 373 Comm: s2disk
>   Call Trace:
>    snapshot_ioctl+0x964/0xbd0
>    __x64_sys_ioctl+0x724/0x1320
>   ...
>
> The uswsusp path calls pm_restore_gfp_mask() defensively in
> SNAPSHOT_CREATE_IMAGE and SNAPSHOT_UNFREEZE where the GFP mask may
> or may not be restricted depending on context (first call vs retry,
> hibernate vs resume). Before the stacking patch this was a silent
> no-op; now it triggers a WARNING.
>
> Introduce pm_restore_gfp_mask_safe() that skips the call when
> saved_gfp_count is 0. This is preferred over tracking the restrict
> state in snapshot_ioctl, as incorrect tracking risks leaving the
> GFP mask permanently restricted.
>
> Fixes: 35e4a69b2003f ("PM: sleep: Allow pm_restrict_gfp_mask() stacking")
> Signed-off-by: Youngjun Park <youngjun.park@lge.com>
> ---
>  include/linux/suspend.h | 1 +
>  kernel/power/main.c     | 7 +++++++
>  kernel/power/user.c     | 4 ++--
>  3 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/suspend.h b/include/linux/suspend.h
> index b02876f1ae38..7777931d88a5 100644
> --- a/include/linux/suspend.h
> +++ b/include/linux/suspend.h
> @@ -454,6 +454,7 @@ extern void pm_report_hw_sleep_time(u64 t);
>  extern void pm_report_max_hw_sleep(u64 t);
>  void pm_restrict_gfp_mask(void);
>  void pm_restore_gfp_mask(void);
> +void pm_restore_gfp_mask_safe(void);
>
>  #define pm_notifier(fn, pri) {                         \
>         static struct notifier_block fn##_nb =                  \
> diff --git a/kernel/power/main.c b/kernel/power/main.c
> index 5f8c9e12eaec..e610a8c8b7ff 100644
> --- a/kernel/power/main.c
> +++ b/kernel/power/main.c
> @@ -36,6 +36,13 @@
>  static unsigned int saved_gfp_count;
>  static gfp_t saved_gfp_mask;
>
> +void pm_restore_gfp_mask_safe(void)
> +{
> +       if (!saved_gfp_count)
> +               return;
> +       pm_restore_gfp_mask();
> +}
> +
>  void pm_restore_gfp_mask(void)
>  {
>         WARN_ON(!mutex_is_locked(&system_transition_mutex));
> diff --git a/kernel/power/user.c b/kernel/power/user.c
> index 3e41544b99d5..41cff6a89a1c 100644
> --- a/kernel/power/user.c
> +++ b/kernel/power/user.c
> @@ -306,7 +306,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
>         case SNAPSHOT_UNFREEZE:
>                 if (!data->frozen || data->ready)
>                         break;
> -               pm_restore_gfp_mask();
> +               pm_restore_gfp_mask_safe();
>                 free_basic_memory_bitmaps();
>                 data->free_bitmaps = false;
>                 thaw_processes();
> @@ -318,7 +318,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
>                         error = -EPERM;
>                         break;
>                 }
> -               pm_restore_gfp_mask();
> +               pm_restore_gfp_mask_safe();
>                 error = hibernation_snapshot(data->platform_support);
>                 if (!error) {
>                         error = put_user(in_suspend, (int __user *)arg);
> --

AFAICS, this patch doesn't depend on the rest of the series, so I can
apply it separately unless there is a problem with that.

However, for the other 2 patches in the series, I'd need some tags
(preferably Reviewed-by) from mm people.

Thanks!

^ permalink raw reply

* [PATCH v2 1/1] writeback: don't block sync(2) for filesystems with no data integrity guarantees
From: Joanne Koong @ 2026-03-19 19:45 UTC (permalink / raw)
  To: brauner
  Cc: linux-fsdevel, jack, miklos, david, therealgraysky, linux-pm,
	stable
In-Reply-To: <20260319194540.3463371-1-joannelkoong@gmail.com>

Add a SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot
guarantee data persistence on sync (eg fuse). For superblocks with this
flag set, sync(2) kicks off writeback of dirty inodes but does not wait
for the flusher threads to complete the writeback.

This replaces the per-inode AS_NO_DATA_INTEGRITY mapping flag added in
commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY mappings
in wait_sb_inodes()"). The flag belongs at the superblock level because
data integrity is a filesystem-wide property, not a per-inode one.
Having this flag at the superblock level allows us to skip the logic in
sync_inodes_sb() entirely, rather than iterating every dirty inode in
wait_sb_inodes() only to skip each inode individually.

This also addresses a recent report [1] for a suspend-to-RAM hang seen
on fuse-overlayfs:

Workqueue: pm_fs_sync pm_fs_sync_work_fn
Call Trace:
 <TASK>
 __schedule+0x457/0x1720
 schedule+0x27/0xd0
 wb_wait_for_completion+0x97/0xe0
 sync_inodes_sb+0xf8/0x2e0
 __iterate_supers+0xdc/0x160
 ksys_sync+0x43/0xb0
 pm_fs_sync_work_fn+0x17/0xa0
 process_one_work+0x193/0x350
 worker_thread+0x1a1/0x310
 kthread+0xfc/0x240
 ret_from_fork+0x243/0x280
 ret_from_fork_asm+0x1a/0x30
 </TASK>

Prior to this commit, mappings with no data integrity guarantees skipped
waiting on writeback completion but it still waited on the flusher
threads to finish initiating the writeback. On fuse this is problematic
because even though the writeback requests are non-blocking background
requests, there are still paths that may cause the flusher thread to
block (eg if systemd freezes the user session cgroups first, which
freezes the fuse daemon, before invoking the kernel suspend. The kernel
suspend triggers ->write_node() which on fuse issues a synchronous
setattr request, which cannot be processed since daemon is frozen. Or
another example, if the daemon is buggy and does not properly complete
writeback, initiating writeback on a dirty folio already under writeback
leads to writeback_get_folio() -> folio_prepare_writeback() ->
unconditional wait on writeback to finish which will cause a hang). This
commit restores fuse to its prior behavior before tmp folios were
removed, where sync was essentially a no-op.

[1] https://lore.kernel.org/linux-fsdevel/CAJnrk1a-asuvfrbKXbEwwDSctvemF+6zfhdnuzO65Pt8HsFSRw@mail.gmail.com/T/#m632c4648e9cafc4239299887109ebd880ac6c5c1

Fixes: 0c58a97f919c ("fuse: remove tmp folio for writebacks and internal rb tree")
Reported-by: John <therealgraysky@proton.me>
Cc: <stable@vger.kernel.org>
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
 fs/fs-writeback.c              |  7 +------
 fs/fuse/file.c                 |  4 +---
 fs/fuse/inode.c                |  1 +
 fs/sync.c                      |  7 ++++++-
 include/linux/fs/super_types.h |  1 +
 include/linux/pagemap.h        | 11 -----------
 6 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 7c75ed7e8979..154249e4e5ce 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -2775,13 +2775,8 @@ static void wait_sb_inodes(struct super_block *sb)
 		 * The mapping can appear untagged while still on-list since we
 		 * do not have the mapping lock. Skip it here, wb completion
 		 * will remove it.
-		 *
-		 * If the mapping does not have data integrity semantics,
-		 * there's no need to wait for the writeout to complete, as the
-		 * mapping cannot guarantee that data is persistently stored.
 		 */
-		if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK) ||
-		    mapping_no_data_integrity(mapping))
+		if (!mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK))
 			continue;
 
 		spin_unlock_irq(&sb->s_inode_wblist_lock);
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a9c836d7f586..f6240f24b814 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -3202,10 +3202,8 @@ void fuse_init_file_inode(struct inode *inode, unsigned int flags)
 
 	inode->i_fop = &fuse_file_operations;
 	inode->i_data.a_ops = &fuse_file_aops;
-	if (fc->writeback_cache) {
+	if (fc->writeback_cache)
 		mapping_set_writeback_may_deadlock_on_reclaim(&inode->i_data);
-		mapping_set_no_data_integrity(&inode->i_data);
-	}
 
 	INIT_LIST_HEAD(&fi->write_files);
 	INIT_LIST_HEAD(&fi->queued_writes);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index e57b8af06be9..c795abe47a4f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1709,6 +1709,7 @@ static void fuse_sb_defaults(struct super_block *sb)
 	sb->s_export_op = &fuse_export_operations;
 	sb->s_iflags |= SB_I_IMA_UNVERIFIABLE_SIGNATURE;
 	sb->s_iflags |= SB_I_NOIDMAP;
+	sb->s_iflags |= SB_I_NO_DATA_INTEGRITY;
 	if (sb->s_user_ns != &init_user_ns)
 		sb->s_iflags |= SB_I_UNTRUSTED_MOUNTER;
 	sb->s_flags &= ~(SB_NOSEC | SB_I_VERSION);
diff --git a/fs/sync.c b/fs/sync.c
index 942a60cfedfb..aedbf723830a 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -73,7 +73,12 @@ EXPORT_SYMBOL(sync_filesystem);
 
 static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
-	if (!sb_rdonly(sb))
+	if (sb_rdonly(sb))
+		return;
+
+	if (sb->s_iflags & SB_I_NO_DATA_INTEGRITY)
+		wakeup_flusher_threads_bdi(sb->s_bdi, WB_REASON_SYNC);
+	else
 		sync_inodes_sb(sb);
 }
 
diff --git a/include/linux/fs/super_types.h b/include/linux/fs/super_types.h
index fa7638b81246..383050e7fdf5 100644
--- a/include/linux/fs/super_types.h
+++ b/include/linux/fs/super_types.h
@@ -338,5 +338,6 @@ struct super_block {
 #define SB_I_NOUMASK	0x00001000	/* VFS does not apply umask */
 #define SB_I_NOIDMAP	0x00002000	/* No idmapped mounts on this superblock */
 #define SB_I_ALLOW_HSM	0x00004000	/* Allow HSM events on this superblock */
+#define SB_I_NO_DATA_INTEGRITY	0x00008000 /* fs cannot guarantee data persistence on sync */
 
 #endif /* _LINUX_FS_SUPER_TYPES_H */
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index ec442af3f886..31a848485ad9 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -210,7 +210,6 @@ enum mapping_flags {
 	AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM = 9,
 	AS_KERNEL_FILE = 10,	/* mapping for a fake kernel file that shouldn't
 				   account usage to user cgroups */
-	AS_NO_DATA_INTEGRITY = 11, /* no data integrity guarantees */
 	/* Bits 16-25 are used for FOLIO_ORDER */
 	AS_FOLIO_ORDER_BITS = 5,
 	AS_FOLIO_ORDER_MIN = 16,
@@ -346,16 +345,6 @@ static inline bool mapping_writeback_may_deadlock_on_reclaim(const struct addres
 	return test_bit(AS_WRITEBACK_MAY_DEADLOCK_ON_RECLAIM, &mapping->flags);
 }
 
-static inline void mapping_set_no_data_integrity(struct address_space *mapping)
-{
-	set_bit(AS_NO_DATA_INTEGRITY, &mapping->flags);
-}
-
-static inline bool mapping_no_data_integrity(const struct address_space *mapping)
-{
-	return test_bit(AS_NO_DATA_INTEGRITY, &mapping->flags);
-}
-
 static inline gfp_t mapping_gfp_mask(const struct address_space *mapping)
 {
 	return mapping->gfp_mask;
-- 
2.52.0


^ permalink raw reply related

* [PATCH v2 0/1] writeback: don't block sync(2) for filesystems with no data integrity guarantees
From: Joanne Koong @ 2026-03-19 19:45 UTC (permalink / raw)
  To: brauner
  Cc: linux-fsdevel, jack, miklos, david, therealgraysky, linux-pm,
	stable

Changelog
---------
v1: https://lore.kernel.org/linux-fsdevel/20260318225604.71545-1-joannelkoong@gmail.com/
v1 -> v2:
* Still kick off flusher threads for writeback for SB_I_NO_DATA_INTEGRITY,
  instead of skipping that entirely (Jan)
* Improve commit message (me)

Joanne Koong (1):
  writeback: don't block sync(2) for filesystems with no data integrity
    guarantees

 fs/fs-writeback.c              |  7 +------
 fs/fuse/file.c                 |  4 +---
 fs/fuse/inode.c                |  1 +
 fs/sync.c                      |  7 ++++++-
 include/linux/fs/super_types.h |  1 +
 include/linux/pagemap.h        | 11 -----------
 6 files changed, 10 insertions(+), 21 deletions(-)

-- 
2.52.0


^ permalink raw reply

* Re: [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
From: Nhat Pham @ 2026-03-19 19:26 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, pfalcato, rafael, rakie.kim,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
	zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAKEwX=MUrLtZAcmwqBau5GLnWQrjL7A_4tYrdZ4TQQaE+hsVkA@mail.gmail.com>

On Thu, Mar 19, 2026 at 11:37 AM Nhat Pham <nphamcs@gmail.com> wrote:
>
> On Thu, Mar 19, 2026 at 12:56 AM Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > On Wed, Mar 18, 2026 at 03:29:40PM -0700, Nhat Pham wrote:
> > > diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> > > index 62cd7b35a29c9..85cb45022e796 100644
> > > --- a/include/linux/cpuhotplug.h
> > > +++ b/include/linux/cpuhotplug.h
> > > @@ -86,6 +86,7 @@ enum cpuhp_state {
> > >       CPUHP_FS_BUFF_DEAD,
> > >       CPUHP_PRINTK_DEAD,
> > >       CPUHP_MM_MEMCQ_DEAD,
> > > +     CPUHP_MM_VSWAP_DEAD,
> > >       CPUHP_PERCPU_CNT_DEAD,
> > >       CPUHP_RADIX_DEAD,
> > >       CPUHP_PAGE_ALLOC,
> >
> > > +static int vswap_cpu_dead(unsigned int cpu)
> > > +{
> > > +     struct vswap_cluster *cluster;
> > > +     int order;
> > > +
> > > +     rcu_read_lock();
> >
> > nit:
> >         guard(rcu)();
> >
> > > +     for (order = 0; order < SWAP_NR_ORDERS; order++) {
> > > +             cluster = per_cpu(percpu_vswap_cluster.clusters[order], cpu);
> > > +             if (cluster) {
> > > +                     per_cpu(percpu_vswap_cluster.clusters[order], cpu) = NULL;
> > > +                     spin_lock(&cluster->lock);
> >
> > This breaks on PREEMPT_RT as this is ran with IRQs disabled. This must
> > be a raw_spinlock_t.
> >
> > > +                     cluster->cached = false;
> > > +                     if (refcount_dec_and_test(&cluster->refcnt))
> > > +                             vswap_cluster_free(cluster);
> >
> > And this... below.
> >
> > > +                     spin_unlock(&cluster->lock);
> > > +             }
> > > +     }
> > > +     rcu_read_unlock();
> > > +
> > > +     return 0;
> > > +}
> >
> > > +static void vswap_cluster_free(struct vswap_cluster *cluster)
> > > +{
> > > +     VM_WARN_ON(cluster->count || cluster->cached);
> > > +     VM_WARN_ON(!spin_is_locked(&cluster->lock));
> >
> > This is terrible, please use:
> >
> >         lockdep_assert_held(&cluster->lock);
> >
> > > +     xa_lock(&vswap_cluster_map);
> >
> > This is again broken, this cannot be from a DEAD callback with IRQs
> > disabled.
> >
> > > +     list_del_init(&cluster->list);
> > > +     __xa_erase(&vswap_cluster_map, cluster->id);
> >
> > Strictly speaking this can end up in xas_alloc(), which is again, not
> > allowed in a DEAD callback.
>
> I see. I'll take a look at this. Thanks for pointing this out, Peter!

Hmm seems like we can just defer-free on the cpu_dead path, and that
should be safe?

Right now, if a cluster is cached on a CPU, we know that it's not
cached on any other CPU, and it's not on any other partial lists.
Maybe can call_rcu() here to defer-free it. Hopefully cpu dead is rare
enough of an event that we dont have a backlog of free deferrals :)

The other alternative is workqueue (with some careful rcu handling in
the free callback), but that seems unnecessary.

^ permalink raw reply

* Re: [PATCH v4 09/21] mm: swap: allocate a virtual swap slot for each swapped out page
From: Nhat Pham @ 2026-03-19 18:37 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: kasong, Liam.Howlett, akpm, apopple, axelrasmussen, baohua,
	baolin.wang, bhe, byungchul, cgroups, chengming.zhou, chrisl,
	corbet, david, dev.jain, gourry, hannes, hughd, jannh,
	joshua.hahnjy, lance.yang, lenb, linux-doc, linux-kernel,
	linux-mm, linux-pm, lorenzo.stoakes, matthew.brost, mhocko,
	muchun.song, npache, pavel, peterx, pfalcato, rafael, rakie.kim,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
	zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <20260319075621.GR3738010@noisy.programming.kicks-ass.net>

On Thu, Mar 19, 2026 at 12:56 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Wed, Mar 18, 2026 at 03:29:40PM -0700, Nhat Pham wrote:
> > diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
> > index 62cd7b35a29c9..85cb45022e796 100644
> > --- a/include/linux/cpuhotplug.h
> > +++ b/include/linux/cpuhotplug.h
> > @@ -86,6 +86,7 @@ enum cpuhp_state {
> >       CPUHP_FS_BUFF_DEAD,
> >       CPUHP_PRINTK_DEAD,
> >       CPUHP_MM_MEMCQ_DEAD,
> > +     CPUHP_MM_VSWAP_DEAD,
> >       CPUHP_PERCPU_CNT_DEAD,
> >       CPUHP_RADIX_DEAD,
> >       CPUHP_PAGE_ALLOC,
>
> > +static int vswap_cpu_dead(unsigned int cpu)
> > +{
> > +     struct vswap_cluster *cluster;
> > +     int order;
> > +
> > +     rcu_read_lock();
>
> nit:
>         guard(rcu)();
>
> > +     for (order = 0; order < SWAP_NR_ORDERS; order++) {
> > +             cluster = per_cpu(percpu_vswap_cluster.clusters[order], cpu);
> > +             if (cluster) {
> > +                     per_cpu(percpu_vswap_cluster.clusters[order], cpu) = NULL;
> > +                     spin_lock(&cluster->lock);
>
> This breaks on PREEMPT_RT as this is ran with IRQs disabled. This must
> be a raw_spinlock_t.
>
> > +                     cluster->cached = false;
> > +                     if (refcount_dec_and_test(&cluster->refcnt))
> > +                             vswap_cluster_free(cluster);
>
> And this... below.
>
> > +                     spin_unlock(&cluster->lock);
> > +             }
> > +     }
> > +     rcu_read_unlock();
> > +
> > +     return 0;
> > +}
>
> > +static void vswap_cluster_free(struct vswap_cluster *cluster)
> > +{
> > +     VM_WARN_ON(cluster->count || cluster->cached);
> > +     VM_WARN_ON(!spin_is_locked(&cluster->lock));
>
> This is terrible, please use:
>
>         lockdep_assert_held(&cluster->lock);
>
> > +     xa_lock(&vswap_cluster_map);
>
> This is again broken, this cannot be from a DEAD callback with IRQs
> disabled.
>
> > +     list_del_init(&cluster->list);
> > +     __xa_erase(&vswap_cluster_map, cluster->id);
>
> Strictly speaking this can end up in xas_alloc(), which is again, not
> allowed in a DEAD callback.

I see. I'll take a look at this. Thanks for pointing this out, Peter!

^ permalink raw reply

* Re: (subset) [PATCH v4 4/5] dt-bindings: mfd: max77620: document optional RTC address for MAX77663
From: Lee Jones @ 2026-03-19 18:26 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Lee Jones, Liam Girdwood,
	Mark Brown, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
	Lukasz Luba, Chanwoo Choi, Alexandre Belloni, Svyatoslav Ryhel
  Cc: linux-gpio, devicetree, linux-kernel, linux-pm, linux-rtc
In-Reply-To: <20260312085258.11431-5-clamor95@gmail.com>

On Thu, 12 Mar 2026 10:52:57 +0200, Svyatoslav Ryhel wrote:
> Document an optional second I2C address for the MAX77663 PMIC's RTC
> device, to be used if the MAX77663 RTC is located at a non-default I2C
> address.
> 
> 

Applied, thanks!

[4/5] dt-bindings: mfd: max77620: document optional RTC address for MAX77663
      commit: a526075f56fb8f2fd96f791654ff1557e6680bde

--
Lee Jones [李琼斯]


^ permalink raw reply

* Re: (subset) [PATCH v4 3/5] dt-bindings: mfd: max77620: convert to DT schema
From: Lee Jones @ 2026-03-19 18:23 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Lee Jones, Liam Girdwood,
	Mark Brown, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
	Lukasz Luba, Chanwoo Choi, Alexandre Belloni, Svyatoslav Ryhel
  Cc: linux-gpio, devicetree, linux-kernel, linux-pm, linux-rtc
In-Reply-To: <20260312085258.11431-4-clamor95@gmail.com>

On Thu, 12 Mar 2026 10:52:56 +0200, Svyatoslav Ryhel wrote:
> Convert max77620 devicetree bindings from TXT to YAML format. This patch
> does not change any functionality; the bindings remain the same. The
> thermal bindings are incorporated into the binding. GPIO controller
> function in MAX77620 has no dedicated node and is folded into the parent
> node itself.
> 
> 
> [...]

Applied, thanks!

[3/5] dt-bindings: mfd: max77620: convert to DT schema
      commit: 77c8585abf5d7409990b71ba333e839bf4597cb5

--
Lee Jones [李琼斯]


^ permalink raw reply

* Re: [PATCH v1] writeback: skip sync(2) inode writeback for filesystems with no data integrity guarantees
From: Joanne Koong @ 2026-03-19 18:07 UTC (permalink / raw)
  To: Jan Kara
  Cc: brauner, linux-fsdevel, miklos, david, therealgraysky, linux-pm,
	stable
In-Reply-To: <k7ln2mcmll3t4zic3smao6hvvxprmpsax45fh6mwn4en6f6m42@sdpuqd2pqiwy>

On Thu, Mar 19, 2026 at 5:42 AM Jan Kara <jack@suse.cz> wrote:
>
> On Wed 18-03-26 15:56:04, Joanne Koong wrote:
> > Add SB_I_NO_DATA_INTEGRITY superblock flag for filesystems that cannot
> > guarantee data persistence on sync (eg fuse) and skip sync(2) inode
> > writeback for superblocks with this flag set.
> >
> > There was a recent report [1] for a suspend-to-RAM hang on fuse-overlayfs with
> > firefox + youtube in wb_wait_for_completion() from the pm_fs_sync_work_fn()
> > path:
> >
> > Workqueue: pm_fs_sync pm_fs_sync_work_fn
> > Call Trace:
> >  <TASK>
> >  __schedule+0x457/0x1720
> >  schedule+0x27/0xd0
> >  wb_wait_for_completion+0x97/0xe0
> >  sync_inodes_sb+0xf8/0x2e0
> >  __iterate_supers+0xdc/0x160
> >  ksys_sync+0x43/0xb0
> >  pm_fs_sync_work_fn+0x17/0xa0
> >  process_one_work+0x193/0x350
> >  worker_thread+0x1a1/0x310
> >  kthread+0xfc/0x240
> >  ret_from_fork+0x243/0x280
> >  ret_from_fork_asm+0x1a/0x30
> >  </TASK>
> >
> > This can happen in two ways:
> > a) systemd freezes the user session cgroups first (which freezes the fuse daemon)
> > before invoking the kernel suspend. The suspend triggers the wb_workfn() ->
> > write_inode() path, where fuse issues a synchronous setattr request to the
> > frozen daemon, which cannot process the request
> > b) if a dirty folio is already under writeback and needs to have writeback
> > issued again, in writeback_get_folio() -> folio_prepare_writeback(), we
> > unconditionally wait on writeback to finish, but for buggy/faulty fuse
> > servers, the request may never be processed
> >
> > The correct fix is for sync(2) to skip the sync_inodes_sb() path entirely for
> > any filesystems that do not have data integrity guarantees.
> >
> > A prior commit (commit f9a49aa302a0 ("fs/writeback: skip AS_NO_DATA_INTEGRITY
> > mappings in wait_sb_inodes()")) added the AS_NO_DATA_INTEGRITY mapping flag to
> > skip sync(2) waits for mappings without data integrity semantics, but it still
> > allowed wb_workfn() worker threads to be kicked off for the writeback.
> >
> > This patch improves upon that by replacing the per-inode AS_NO_DATA_INTEGRITY
> > mapping flag with a flag at the superblock level, and using that superblock
> > flag to skip the sync_inodes_sb() path entirely if there are no data integrity
> > guarantees. The flag belongs at the superblock level because data integrity is
> > a filesystem-wide property, not a per-inode one. Having the flag at the
> > superblock level allows sync_inodes_one_sb() to skip the entire filesystem
> > efficiently, rather than iterating every dirty inode only to skip each one
> > individually.
> >
> > This patch restores fuse to its prior behavior before tmp folios were removed,
> > where sync was essentially a no-op.
> >
> > [1] https://lore.kernel.org/linux-fsdevel/CAJnrk1a-asuvfrbKXbEwwDSctvemF+6zfhdnuzO65Pt8HsFSRw@mail.gmail.com/T/#m632c4648e9cafc4239299887109ebd880ac6c5c1
> >
> > Fixes: 0c58a97f919c ("fuse: remove tmp folio for writebacks and internal rb tree")
> > Reported-by: John <therealgraysky@proton.me>
> > Tested-by: John <therealgraysky@proton.me>
> > Cc: <stable@vger.kernel.org>
> > Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
>
> I'd note that previously, if the FUSE server was not broken, although
> sync(2) would not provide any data integrity guarantee, it would still
> flush the data so practically, there would be no user observable difference
> unless you really did powerfail testing. So some users might be
> unpleasantly surprised by sync(2) suddently not doing anything on FUSE
> filesystems. Maybe for SB_I_NO_DATA_INTEGRITY filesystems we should at
> least kick flush worker to do writeback in the background?
>
>                                                                 Honza
>

That's a great point. I'll make this change for v2.

Thanks,
Joanne

^ permalink raw reply

* Re: [PATCH 0/9] driver core / pmdomain: Add support for fined grained sync_state
From: Saravana Kannan @ 2026-03-19 17:19 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Saravana Kannan, Rafael J . Wysocki, Greg Kroah-Hartman, linux-pm,
	Kevin Hilman, Stephen Boyd, Marek Szyprowski, Bjorn Andersson,
	Abel Vesa, Peng Fan, Tomi Valkeinen, Maulik Shah, Konrad Dybcio,
	Thierry Reding, Jonathan Hunter, Geert Uytterhoeven,
	Dmitry Baryshkov, linux-arm-kernel, linux-kernel
In-Reply-To: <CAPDyKFr25L0Omm_uCjZp03_ptnrKR_P2p3e3qxDeUoFFKJg3bQ@mail.gmail.com>

On Thu, Mar 19, 2026 at 9:59 AM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Tue, 3 Mar 2026 at 14:23, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> >
> > Since the introduction [1] of the common sync_state support for pmdomains
> > (genpd), we have encountered a lot of various interesting problems. In most
> > cases the new behaviour of genpd triggered some weird platform specific bugs.
> >
> > That said, in LPC in Tokyo me and Saravana hosted a session to walk through the
> > remaining limitations that we have found for genpd's sync state support. In
> > particular, we discussed the problems we have for the so-called onecell power
> > domain providers, where a single provider typically provides multiple
> > independent power domains, all with their own set of consumers.
> >
> > In these cases, the generic sync_state mechanism with fw_devlink isn't fine
> > grained enough, as we end up waiting for all consumers for all power domains
> > before the ->sync_callback gets called for the supplier/provider. In other
> > words, we may end up keeping unused power domains powered-on, for no good
> > reasons.
> >
> > The series intends to fix this problem. Please have a look at the commit
> > messages for more details.
> >
> > Please help review and test!
>
> Saravana, Rafael, Greg - any concerns you see with this approach?

Not specifically related to this thread, but a general update so
people know I haven't vanished. I've been reading this and all the
other fw_devlink related patches (Doug's making flags set/clear/check
safe, overlay series, the PCIe patch series, etc) being sent since I
last replied. I somehow missed this one. I'll definitely take a look
at this series.

Email replies to LKML are a pain right now but it's
expected to get much easier in a week or two. I'm holding off on
responding to most emails until then.

Thanks,
Saravana

>
> Especially I need your confirmation for patch 1 and patch2.
>
> Kind regards
> Uffe
>
>
> >
> > Kind regards
> > Ulf Hansson
> >
> > [1]
> > https://lore.kernel.org/all/20250701114733.636510-1-ulf.hansson@linaro.org/
> >
> >
> > Ulf Hansson (9):
> >   driver core: Enable suppliers to implement fine grained sync_state
> >     support
> >   driver core: Add dev_set_drv_queue_sync_state()
> >   pmdomain: core: Move genpd_get_from_provider()
> >   pmdomain: core: Add initial fine grained sync_state support
> >   pmdomain: core: Extend fine grained sync_state to more onecell
> >     providers
> >   pmdomain: core: Export a common function for ->queue_sync_state()
> >   pmdomain: renesas: rcar-gen4-sysc: Drop GENPD_FLAG_NO_STAY_ON
> >   pmdomain: renesas: rcar-sysc: Drop GENPD_FLAG_NO_STAY_ON
> >   pmdomain: renesas: rmobile-sysc: Drop GENPD_FLAG_NO_STAY_ON
> >
> >  drivers/base/core.c                       |   7 +-
> >  drivers/pmdomain/core.c                   | 208 ++++++++++++++++++----
> >  drivers/pmdomain/renesas/rcar-gen4-sysc.c |   1 -
> >  drivers/pmdomain/renesas/rcar-sysc.c      |   1 -
> >  drivers/pmdomain/renesas/rmobile-sysc.c   |   3 +-
> >  include/linux/device.h                    |  12 ++
> >  include/linux/device/driver.h             |   7 +
> >  include/linux/pm_domain.h                 |   3 +
> >  8 files changed, 200 insertions(+), 42 deletions(-)
> >
> > --
> > 2.43.0
> >

^ permalink raw reply

* Re: [PATCH v4 09/11] mfd: bq257xx: Add BQ25792 support
From: Lee Jones @ 2026-03-19 17:01 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chris Morgan,
	Liam Girdwood, Mark Brown, Sebastian Reichel, devicetree,
	linux-kernel, Sebastian Reichel, linux-pm
In-Reply-To: <20260311-bq25792-v4-9-7213415d9eec@flipper.net>

On Wed, 11 Mar 2026, Alexey Charkov wrote:

> Add register definitions and a new 'type' enum to be passed via MFD
> private data to support the BQ25792, which is a newer variant of the
> BQ257xx family.
> 
> BQ25792 shares similar logic of operation with the already supported
> BQ25703A but has a completely different register map and different
> electrical constraints.
> 
> Tested-by: Chris Morgan <macromorgan@hotmail.com>
> Signed-off-by: Alexey Charkov <alchark@flipper.net>
> ---
>  drivers/mfd/bq257xx.c       |  54 +++++-
>  include/linux/mfd/bq257xx.h | 414 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 465 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mfd/bq257xx.c b/drivers/mfd/bq257xx.c
> index e9d49dac0a16..4445ded5b2eb 100644
> --- a/drivers/mfd/bq257xx.c
> +++ b/drivers/mfd/bq257xx.c
> @@ -39,13 +39,47 @@ static const struct regmap_config bq25703_regmap_config = {
>  	.val_format_endian = REGMAP_ENDIAN_LITTLE,
>  };
>  
> -static const struct mfd_cell cells[] = {
> +static const struct regmap_range bq25792_writeable_reg_ranges[] = {
> +	regmap_reg_range(BQ25792_REG00_MIN_SYS_VOLTAGE,
> +			 BQ25792_REG18_NTC_CONTROL_1),
> +	regmap_reg_range(BQ25792_REG28_CHARGER_MASK_0,
> +			 BQ25792_REG30_ADC_FUNCTION_DISABLE_1),
> +};
> +
> +static const struct regmap_access_table bq25792_writeable_regs = {
> +	.yes_ranges = bq25792_writeable_reg_ranges,
> +	.n_yes_ranges = ARRAY_SIZE(bq25792_writeable_reg_ranges),
> +};
> +
> +static const struct regmap_range bq25792_volatile_reg_ranges[] = {
> +	regmap_reg_range(BQ25792_REG19_ICO_CURRENT_LIMIT,
> +			 BQ25792_REG27_FAULT_FLAG_1),
> +	regmap_reg_range(BQ25792_REG31_IBUS_ADC,
> +			 BQ25792_REG47_DPDM_DRIVER),
> +};
> +
> +static const struct regmap_access_table bq25792_volatile_regs = {
> +	.yes_ranges = bq25792_volatile_reg_ranges,
> +	.n_yes_ranges = ARRAY_SIZE(bq25792_volatile_reg_ranges),
> +};
> +
> +static const struct regmap_config bq25792_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = BQ25792_REG48_PART_INFORMATION,
> +	.cache_type = REGCACHE_MAPLE,
> +	.wr_table = &bq25792_writeable_regs,
> +	.volatile_table = &bq25792_volatile_regs,
> +};
> +
> +static struct mfd_cell cells[] = {

This was `static const` before. And I don't see any code in here making
changes to it.  Was the `const` dropped intentionally?

>  	MFD_CELL_NAME("bq257xx-regulator"),
>  	MFD_CELL_NAME("bq257xx-charger"),
>  };
>  
>  static int bq257xx_probe(struct i2c_client *client)
>  {
> +	const struct regmap_config *rcfg;
>  	struct bq257xx_device *ddata;
>  	int ret;
>  
> @@ -53,9 +87,21 @@ static int bq257xx_probe(struct i2c_client *client)
>  	if (!ddata)
>  		return -ENOMEM;
>  
> +	ddata->type = (uintptr_t)device_get_match_data(&client->dev);

This logic seems a bit fragile. For non-DeviceTree platforms,
`device_get_match_data()` will return `NULL` since the `i2c_device_id`
table doesn't provide any match data. Casting `NULL` to `uintptr_t` will
result in `0`, which corresponds to `BQ25703A`. This means the new
`bq25792` will be misidentified as a `bq25703a` when instantiated
without a DeviceTree node.  Even with DeviceTree, if a compatible string
is matched but has no `.data` property, the same misidentification will
occur.

Perhaps it would be safer to explicitly handle the `NULL` case and make the
identification logic more robust?  Or perhaps start your IDs from 1.

>  	ddata->client = client;
>  
> -	ddata->regmap = devm_regmap_init_i2c(client, &bq25703_regmap_config);
> +	switch (ddata->type) {
> +	case BQ25703A:
> +		rcfg = &bq25703_regmap_config;
> +		break;
> +	case BQ25792:
> +		rcfg = &bq25792_regmap_config;
> +		break;
> +	default:
> +		return dev_err_probe(&client->dev, -EINVAL, "Unsupported device type\n");

Given the potential for `device_get_match_data()` to return `NULL` (which
becomes `0`), this `default` case might not be reachable for invalid or
un-matchable devices. A more explicit check on the match data before this
`switch` might be better.

> +	}
> +
> +	ddata->regmap = devm_regmap_init_i2c(client, rcfg);
>  	if (IS_ERR(ddata->regmap)) {
>  		return dev_err_probe(&client->dev, PTR_ERR(ddata->regmap),
>  				     "Failed to allocate register map\n");
> @@ -74,12 +120,14 @@ static int bq257xx_probe(struct i2c_client *client)
>  
>  static const struct i2c_device_id bq257xx_i2c_ids[] = {
>  	{ "bq25703a" },
> +	{ "bq25792" },
>  	{}
>  };
>  MODULE_DEVICE_TABLE(i2c, bq257xx_i2c_ids);
>  
>  static const struct of_device_id bq257xx_of_match[] = {
> -	{ .compatible = "ti,bq25703a" },
> +	{ .compatible = "ti,bq25703a", .data = (void *)BQ25703A },
> +	{ .compatible = "ti,bq25792", .data = (void *)BQ25792 },
>  	{}
>  };
>  MODULE_DEVICE_TABLE(of, bq257xx_of_match);

[...]

-- 
Lee Jones [李琼斯]

^ permalink raw reply

* Re: [PATCH 0/9] driver core / pmdomain: Add support for fined grained sync_state
From: Ulf Hansson @ 2026-03-19 16:59 UTC (permalink / raw)
  To: Saravana Kannan, Rafael J . Wysocki, Greg Kroah-Hartman, linux-pm
  Cc: Kevin Hilman, Stephen Boyd, Marek Szyprowski, Bjorn Andersson,
	Abel Vesa, Peng Fan, Tomi Valkeinen, Maulik Shah, Konrad Dybcio,
	Thierry Reding, Jonathan Hunter, Geert Uytterhoeven,
	Dmitry Baryshkov, linux-arm-kernel, linux-kernel
In-Reply-To: <20260303132305.438657-1-ulf.hansson@linaro.org>

On Tue, 3 Mar 2026 at 14:23, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> Since the introduction [1] of the common sync_state support for pmdomains
> (genpd), we have encountered a lot of various interesting problems. In most
> cases the new behaviour of genpd triggered some weird platform specific bugs.
>
> That said, in LPC in Tokyo me and Saravana hosted a session to walk through the
> remaining limitations that we have found for genpd's sync state support. In
> particular, we discussed the problems we have for the so-called onecell power
> domain providers, where a single provider typically provides multiple
> independent power domains, all with their own set of consumers.
>
> In these cases, the generic sync_state mechanism with fw_devlink isn't fine
> grained enough, as we end up waiting for all consumers for all power domains
> before the ->sync_callback gets called for the supplier/provider. In other
> words, we may end up keeping unused power domains powered-on, for no good
> reasons.
>
> The series intends to fix this problem. Please have a look at the commit
> messages for more details.
>
> Please help review and test!

Saravana, Rafael, Greg - any concerns you see with this approach?

Especially I need your confirmation for patch 1 and patch2.

Kind regards
Uffe


>
> Kind regards
> Ulf Hansson
>
> [1]
> https://lore.kernel.org/all/20250701114733.636510-1-ulf.hansson@linaro.org/
>
>
> Ulf Hansson (9):
>   driver core: Enable suppliers to implement fine grained sync_state
>     support
>   driver core: Add dev_set_drv_queue_sync_state()
>   pmdomain: core: Move genpd_get_from_provider()
>   pmdomain: core: Add initial fine grained sync_state support
>   pmdomain: core: Extend fine grained sync_state to more onecell
>     providers
>   pmdomain: core: Export a common function for ->queue_sync_state()
>   pmdomain: renesas: rcar-gen4-sysc: Drop GENPD_FLAG_NO_STAY_ON
>   pmdomain: renesas: rcar-sysc: Drop GENPD_FLAG_NO_STAY_ON
>   pmdomain: renesas: rmobile-sysc: Drop GENPD_FLAG_NO_STAY_ON
>
>  drivers/base/core.c                       |   7 +-
>  drivers/pmdomain/core.c                   | 208 ++++++++++++++++++----
>  drivers/pmdomain/renesas/rcar-gen4-sysc.c |   1 -
>  drivers/pmdomain/renesas/rcar-sysc.c      |   1 -
>  drivers/pmdomain/renesas/rmobile-sysc.c   |   3 +-
>  include/linux/device.h                    |  12 ++
>  include/linux/device/driver.h             |   7 +
>  include/linux/pm_domain.h                 |   3 +
>  8 files changed, 200 insertions(+), 42 deletions(-)
>
> --
> 2.43.0
>

^ permalink raw reply

* Re: [PATCH v7 3/7] dax/cxl, hmem: Initialize hmem early and defer dax_cxl binding
From: Koralahalli Channabasappa, Smita @ 2026-03-19 16:45 UTC (permalink / raw)
  To: Alison Schofield, Smita Koralahalli, Jonathan Cameron
  Cc: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm,
	Ard Biesheuvel, Vishal Verma, Ira Weiny, Dan Williams,
	Yazen Ghannam, Dave Jiang, Davidlohr Bueso, Matthew Wilcox,
	Jan Kara, Rafael J . Wysocki, Len Brown, Pavel Machek, Li Ming,
	Jeff Johnson, Ying Huang, Yao Xingtao, Peter Zijlstra,
	Greg Kroah-Hartman, Nathan Fontenot, Terry Bowman, Robert Richter,
	Benjamin Cheatham, Zhijian Li, Borislav Petkov, Tomasz Wolski
In-Reply-To: <3590e2d5-e768-4180-82a0-c972101f3440@amd.com>

On 3/19/2026 8:46 AM, Koralahalli Channabasappa, Smita wrote:
> Hi Jonathan and Alison,
> 
> Thanks for the report and suggestions. I took a look at Jonathan's 
> comments in Patch 6 and tying it together here.
> 
> On 3/18/2026 10:48 PM, Alison Schofield wrote:
>> On Thu, Mar 19, 2026 at 01:14:56AM +0000, Smita Koralahalli wrote:
>>> From: Dan Williams <dan.j.williams@intel.com>
>>>
>>> Move hmem/ earlier in the dax Makefile so that hmem_init() runs before
>>> dax_cxl.
>>>
>>> In addition, defer registration of the dax_cxl driver to a workqueue
>>> instead of using module_cxl_driver(). This ensures that dax_hmem has
>>> an opportunity to initialize and register its deferred callback and make
>>> ownership decisions before dax_cxl begins probing and claiming Soft
>>> Reserved ranges.
>>>
>>> Mark the dax_cxl driver as PROBE_PREFER_ASYNCHRONOUS so its probe runs
>>> out of line from other synchronous probing avoiding ordering
>>> dependencies while coordinating ownership decisions with dax_hmem.
>>
>> Hi Smita,
>>
>> Replying to this patch, as it's my best guess as to why I may be
>> seeing this WARN when I modprobe cxl-test.
>>
>> We are able to pass all the CXL unit tests because it is only that
>> first load that causes the WARN. All subsequent reloads of cxl-test
>> do not unload dax_cxl and dax_hmem so they chug happily along.
>>
>> I can reproduce by unloading each piece before reloading cxl-test
>> # modprobe -r cxl-test
>> # modprobe -r dax_cxl
>> # modprobe -r dax_hmem
>> # modprobe cxl-test
>> and the WARN repeats.
>>
>> Guessing you may recognize what is going on. Let me know if I can
>> try anything else out.
>>
>>
>> # dmesg (trimmed to just the init calls)
>> [   34.229033] calling  fwctl_init+0x0/0xff0 [fwctl] @ 1057
>> [   34.230616] initcall fwctl_init+0x0/0xff0 [fwctl] returned 0 after 
>> 186 usecs
>> [   34.257096] calling  cxl_core_init+0x0/0x100 [cxl_core] @ 1057
>> [   34.258395] initcall cxl_core_init+0x0/0x100 [cxl_core] returned 0 
>> after 538 usecs
>> [   34.264170] calling  cxl_port_init+0x0/0xff0 [cxl_port] @ 1057
>> [   34.264982] initcall cxl_port_init+0x0/0xff0 [cxl_port] returned 0 
>> after 110 usecs
>> [   34.268058] calling  cxl_mem_driver_init+0x0/0xff0 [cxl_mem] @ 1057
>> [   34.268743] initcall cxl_mem_driver_init+0x0/0xff0 [cxl_mem] 
>> returned 0 after 110 usecs
>> [   34.274670] calling  cxl_pmem_init+0x0/0xff0 [cxl_pmem] @ 1057
>> [   34.277835] initcall cxl_pmem_init+0x0/0xff0 [cxl_pmem] returned 0 
>> after 1671 usecs
>> [   34.285807] calling  cxl_acpi_init+0x0/0xff0 [cxl_acpi] @ 1057
>> [   34.287105] initcall cxl_acpi_init+0x0/0xff0 [cxl_acpi] returned 0 
>> after 262 usecs
>> [   34.292967] calling  cxl_test_init+0x0/0xff0 [cxl_test] @ 1057
>> [   34.339841] initcall cxl_test_init+0x0/0xff0 [cxl_test] returned 0 
>> after 45832 usecs
>> [   34.342259] calling  cxl_mock_mem_driver_init+0x0/0xff0 
>> [cxl_mock_mem] @ 1063
>> [   34.343459] initcall cxl_mock_mem_driver_init+0x0/0xff0 
>> [cxl_mock_mem] returned 0 after 356 usecs
>> [   34.658602] calling  dax_hmem_init+0x0/0xff0 [dax_hmem] @ 1059
>> [   34.670106] calling  cxl_pci_driver_init+0x0/0xff0 [cxl_pci] @ 1100
>> [   34.671023] initcall cxl_pci_driver_init+0x0/0xff0 [cxl_pci] 
>> returned 0 after 197 usecs
>> [   34.673051] initcall dax_hmem_init+0x0/0xff0 [dax_hmem] returned 0 
>> after 2225 usecs
> 
> I agree with Jonathan's comments in Patch 6, using __WORK_INITIALIZER or 
> initializing work in dax_hmem_init() and gating flush on pdev will fix 
> the WARN — I will add both for v8. But I think the WARN is likely 
> indicating an ordering issue here..
> 
> On initial boot, the Makefile ordering ensures dax_hmem_init() runs
> before cxl_dax_region_init(), so both work items land on system_long_wq
> in the right order and dax_hmem's deferred work is queued before 
> dax_cxl's driver registration work.
> 
> On module reload which Alison is trying here I dont think, modules are 
> loaded by Makefile order. I think dax_cxl's workqueue is calling 
> dax_hmem_flush_work() before dax_hmem probe has had a chance to queue 
> its work, so flush_work() flushes nothing and dax_cxl registers its 
> driver without waiting.
> 
> __WORK_INITIALIZER fixes the WARN, but doesn't fix the race I guess if 
> we are hitting that here..
> 
> [   34.673051] initcall dax_hmem_init+0x0/0xff0 [dax_hmem] returned 0 
> after 2225 usecs
> [   34.676011] calling  cxl_dax_region_init+0x0/0xff0 [dax_cxl] @ 1059
> 
> These two lines indicate cxl_dax started after dax_hmem_init() returns 
> but I dont think that guarantees dax_hmem_platform_probe() has actually 
> run..
> 
> I dont know if wait_for_device_probe() in cxl_dax_region_driver_register
> might help..
> 
> Thanks
> Smita

Actually, thinking about this more..

dax_hmem_initial_probe lives in device.c (built-in) so it survives 
module reload. On reload it's still true from the first boot. This means 
hmem_register_device() skips the deferral path entirely..

The problem is this bypasses the cxl_region_contains_resource() check 
that the deferred work normally does. On first boot, 
process_defer_work() walks each range and decides per-range: if CXL 
covers it, skip. If not, register with HMEM. On reload, that check never 
happens — whoever registers first via alloc_dax_region() wins, 
regardless of whether CXL actually covers the range.

So if dax_cxl registers first on reload, it could claim a range that CXL 
doesn't actually cover, and dax_hmem would lose a range it should own..

I dont know if Im thinking through this right..

Thanks
Smita

> 
>> [   34.676011] calling  cxl_dax_region_init+0x0/0xff0 [dax_cxl] @ 1059
>> [   34.676856] ------------[ cut here ]------------
>> [   34.677533] WARNING: kernel/workqueue.c:4289 at 
>> __flush_work+0x4f9/0x550, CPU#3: kworker/3:2/136
>> [   34.678596] Modules linked in: dax_cxl(+) cxl_pci dax_hmem 
>> cxl_mock_mem(O) cxl_test(O) cxl_acpi(O) cxl_pmem(O) cxl_mem(O) 
>> cxl_port(O) cxl_mock(O) cxl_core(O) fwctl nd_pmem nd_btt dax_pmem nfit 
>> nd_e820 libnvdimm
>> [   34.680632] initcall cxl_dax_region_init+0x0/0xff0 [dax_cxl] 
>> returned 0 after 3842 usecs
>> [   34.680918] CPU: 3 UID: 0 PID: 136 Comm: kworker/3:2 Tainted: 
>> G           O        7.0.0-rc4+ #156 PREEMPT(full)
>> [   34.684368] Tainted: [O]=OOT_MODULE
>> [   34.684993] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), 
>> BIOS 0.0.0 02/06/2015
>> [   34.686098] Workqueue: events_long cxl_dax_region_driver_register 
>> [dax_cxl]
>> [   34.687108] RIP: 0010:__flush_work+0x4f9/0x550
>>
>> That addr is this line in flush_work()
>>          if (WARN_ON(!work->func))
>>                  return false;
>>
>>
>> [   34.687811] Code: ff 49 8b 45 00 49 8b 55 08 89 c7 48 c1 e8 04 83 
>> e7 08 83 e0 0f 83 cf 02 49 0f ba 6d 00 03 e9 a1 fc ff ff 0f 0b e9 e6 
>> fe ff ff <0f> 0b e9 df fe ff ff e8 9b 48 15 01 85 c0 0f 84 26 ff ff ff 
>> 80 3d
>> [   34.690107] RSP: 0018:ffffc900020b7cf8 EFLAGS: 00010246
>> [   34.690673] RAX: 0000000000000000 RBX: ffffffffa0ea2088 RCX: 
>> ffff8880088b2b78
>> [   34.691388] RDX: 00000000834fb194 RSI: 0000000000000000 RDI: 
>> ffffffffa0ea2088
>> [   34.692135] RBP: ffffc900020b7de0 R08: 0000000031ab93b0 R09: 
>> 00000000effb42e8
>> [   34.692876] R10: 000000008effb42e R11: 0000000000000000 R12: 
>> ffff88807d9bb340
>> [   34.693588] R13: ffffffffa0ea2088 R14: ffffffffa0ed2020 R15: 
>> 0000000000000001
>> [   34.694358] FS:  0000000000000000(0000) GS:ffff8880fa45f000(0000) 
>> knlGS:0000000000000000
>> [   34.695179] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> [   34.695775] CR2: 00007fe888b4e34c CR3: 00000000090ed004 CR4: 
>> 0000000000370ef0
>> [   34.696494] Call Trace:
>> [   34.696889]  <TASK>
>> [   34.697238]  ? __lock_acquire+0xb08/0x2930
>> [   34.697730]  ? __this_cpu_preempt_check+0x13/0x20
>> [   34.698277]  flush_work+0x17/0x30
>> [   34.698705]  dax_hmem_flush_work+0x10/0x20 [dax_hmem]
>> [   34.699270]  cxl_dax_region_driver_register+0x9/0x30 [dax_cxl]
>> [   34.699943]  process_one_work+0x203/0x6c0
>> [   34.700452]  worker_thread+0x197/0x350
>> [   34.700942]  ? __pfx_worker_thread+0x10/0x10
>> [   34.701455]  kthread+0x108/0x140
>> [   34.701915]  ? __pfx_kthread+0x10/0x10
>> [   34.702396]  ret_from_fork+0x28a/0x310
>> [   34.702880]  ? __pfx_kthread+0x10/0x10
>> [   34.703363]  ret_from_fork_asm+0x1a/0x30
>> [   34.703872]  </TASK>
>> [   34.704227] irq event stamp: 11015
>> [   34.704656] hardirqs last  enabled at (11025): [<ffffffff813486de>] 
>> __up_console_sem+0x5e/0x80
>> [   34.705493] hardirqs last disabled at (11036): [<ffffffff813486c3>] 
>> __up_console_sem+0x43/0x80
>> [   34.706354] softirqs last  enabled at (10500): [<ffffffff812ab9f3>] 
>> __irq_exit_rcu+0xc3/0x120
>> [   34.707197] softirqs last disabled at (10495): [<ffffffff812ab9f3>] 
>> __irq_exit_rcu+0xc3/0x120
>> [   34.708015] ---[ end trace 0000000000000000 ]---
>> [   34.752127] calling  dax_init+0x0/0xff0 [device_dax] @ 1089
>> [   34.754006] initcall dax_init+0x0/0xff0 [device_dax] returned 0 
>> after 422 usecs
>> [   34.759609] calling  dax_kmem_init+0x0/0xff0 [kmem] @ 1089
>> [   37.338377] initcall dax_kmem_init+0x0/0xff0 [kmem] returned 0 
>> after 2577658 usecs
>>
>>
>>>
>>> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>>> Signed-off-by: Smita Koralahalli 
>>> <Smita.KoralahalliChannabasappa@amd.com>
>>> Reviewed-by: Dave Jiang <dave.jiang@intel.com>
>>> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
>>> ---
>>>   drivers/dax/Makefile |  3 +--
>>>   drivers/dax/cxl.c    | 27 ++++++++++++++++++++++++++-
>>>   2 files changed, 27 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/dax/Makefile b/drivers/dax/Makefile
>>> index 5ed5c39857c8..70e996bf1526 100644
>>> --- a/drivers/dax/Makefile
>>> +++ b/drivers/dax/Makefile
>>> @@ -1,4 +1,5 @@
>>>   # SPDX-License-Identifier: GPL-2.0
>>> +obj-y += hmem/
>>>   obj-$(CONFIG_DAX) += dax.o
>>>   obj-$(CONFIG_DEV_DAX) += device_dax.o
>>>   obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
>>> @@ -10,5 +11,3 @@ dax-y += bus.o
>>>   device_dax-y := device.o
>>>   dax_pmem-y := pmem.o
>>>   dax_cxl-y := cxl.o
>>> -
>>> -obj-y += hmem/
>>> diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c
>>> index 13cd94d32ff7..a2136adfa186 100644
>>> --- a/drivers/dax/cxl.c
>>> +++ b/drivers/dax/cxl.c
>>> @@ -38,10 +38,35 @@ static struct cxl_driver cxl_dax_region_driver = {
>>>       .id = CXL_DEVICE_DAX_REGION,
>>>       .drv = {
>>>           .suppress_bind_attrs = true,
>>> +        .probe_type = PROBE_PREFER_ASYNCHRONOUS,
>>>       },
>>>   };
>>> -module_cxl_driver(cxl_dax_region_driver);
>>> +static void cxl_dax_region_driver_register(struct work_struct *work)
>>> +{
>>> +    cxl_driver_register(&cxl_dax_region_driver);
>>> +}
>>> +
>>> +static DECLARE_WORK(cxl_dax_region_driver_work, 
>>> cxl_dax_region_driver_register);
>>> +
>>> +static int __init cxl_dax_region_init(void)
>>> +{
>>> +    /*
>>> +     * Need to resolve a race with dax_hmem wanting to drive regions
>>> +     * instead of CXL
>>> +     */
>>> +    queue_work(system_long_wq, &cxl_dax_region_driver_work);
>>> +    return 0;
>>> +}
>>> +module_init(cxl_dax_region_init);
>>> +
>>> +static void __exit cxl_dax_region_exit(void)
>>> +{
>>> +    flush_work(&cxl_dax_region_driver_work);
>>> +    cxl_driver_unregister(&cxl_dax_region_driver);
>>> +}
>>> +module_exit(cxl_dax_region_exit);
>>> +
>>>   MODULE_ALIAS_CXL(CXL_DEVICE_DAX_REGION);
>>>   MODULE_DESCRIPTION("CXL DAX: direct access to CXL regions");
>>>   MODULE_LICENSE("GPL");
>>> -- 
>>> 2.17.1
>>>
>>>
> 


^ permalink raw reply

* Re: [PATCH v8 05/10] pmdomain: samsung: convert to using regmap
From: Ulf Hansson @ 2026-03-19 16:42 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: André Draszik, Krzysztof Kozlowski, Alim Akhtar, Rob Herring,
	Conor Dooley, Krzysztof Kozlowski, Liam Girdwood, Mark Brown,
	Peter Griffin, Tudor Ambarus, Juan Yescas, Will McVicker,
	kernel-team, linux-arm-kernel, linux-samsung-soc, devicetree,
	linux-kernel, linux-pm
In-Reply-To: <4809918d-fdf1-48c0-bc10-fcf75837cb81@samsung.com>

On Thu, 19 Mar 2026 at 16:57, Marek Szyprowski <m.szyprowski@samsung.com> wrote:
>
> On 19.03.2026 12:58, André Draszik wrote:
> > On Thu, 2026-03-19 at 11:29 +0100, Marek Szyprowski wrote:
> >> On 19.03.2026 11:13, Ulf Hansson wrote:
> >>> As a follow-up patch on top, please consider converting the open-coded
> >>> polling loop above into a readx_poll_timeout_atomic().
> >> This has been tried and it doesn't work in all cases required for power
> >> domain driver:
> >>
> >> https://lore.kernel.org/all/5c19e4ef-c4fd-4bf5-88b3-46c86751b14e@samsung.com/
> >>
> >> Probably a comment about that could be added directly to this code to
> >> avoid such conversion and breakage in the future.
> > I am planning to revisit this in the future and am hoping that we can
> > figure out what goes wrong when using regmap_read_poll_timeout().
> >
> > Hopefully such a comment would only be short-lived, so maybe not really
> > worth it? I can add it, though, if you prefer.
>
> Well, I think I've already pointed what goes wrong with
> regmap_read_poll_timeout() in the above mentioned thread. You would need
> to use regmap_read_poll_timeout_atomic() and modify it the same way as
> commit 7349a69cf312 did for read_poll_timeout_atomic().

Thanks a lot for bringing this to our attention!

To me, it looks like the regmap helpers should really use
readx_poll_timeout_atomic, rather than open-coding the loop from the
regular iopoll helpers.

Kind regards
Uffe

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox