Linux Power Management development
 help / color / mirror / Atom feed
* 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

* Re: [PATCH v4 1/3] mm/swap, PM: hibernate: fix swapoff race in uswsusp by getting swap reference
From: Kairui Song @ 2026-03-19 16:34 UTC (permalink / raw)
  To: Youngjun Park
  Cc: rafael, akpm, chrisl, kasong, pavel, shikemeng, nphamcs, bhe,
	baohua, usama.arif, linux-pm, linux-mm
In-Reply-To: <20260317181318.2517015-2-youngjun.park@lge.com>

On Wed, Mar 18, 2026 at 03:13:16AM +0800, Youngjun Park wrote:
> Hibernation via uswsusp (/dev/snapshot ioctls) has a race: between
> setting the resume swap area and allocating a swap slot, user-space is
> not yet frozen, so swapoff can run and cause an incorrect slot allocation.
> 
> Fix this by keeping swap_type_of() as a static helper that requires
> swap_lock to be held, and introducing new interfaces that wrap it with
> proper locking and reference management:
> 
> - get_hibernation_swap_type(): Lookup under swap_lock + acquire a swap
>   device reference to block swapoff (used by uswsusp).
> - find_hibernation_swap_type(): Lookup under swap_lock only, no
>   reference. Used by the sysfs path where user-space is already frozen,
>   making swapoff impossible.
> - put_hibernation_swap_type(): Release the reference.
> 
> Because the reference is held via get_swap_device(), swapoff will block
> at wait_for_completion_interruptible() until put_hibernation_swap_type()
> releases it. The wait is interruptible, so swapoff can be cancelled by
> a signal.
> 
> Signed-off-by: Youngjun Park <youngjun.park@lge.com>
> ---
>  include/linux/swap.h |  4 +-
>  kernel/power/swap.c  |  2 +-
>  kernel/power/user.c  | 15 ++++++--
>  mm/swapfile.c        | 92 ++++++++++++++++++++++++++++++++++++--------
>  4 files changed, 92 insertions(+), 21 deletions(-)
> 
> diff --git a/include/linux/swap.h b/include/linux/swap.h
> index 7a09df6977a5..cf8cfdaf34a7 100644
> --- a/include/linux/swap.h
> +++ b/include/linux/swap.h
> @@ -433,7 +433,9 @@ static inline long get_nr_swap_pages(void)
>  }
>  
>  extern void si_swapinfo(struct sysinfo *);
> -int swap_type_of(dev_t device, sector_t offset);
> +int get_hibernation_swap_type(dev_t device, sector_t offset);
> +int find_hibernation_swap_type(dev_t device, sector_t offset);
> +void put_hibernation_swap_type(int type);

Hi Youngjun,

Thanks! This set of API looks better that before.

>  
> -/*
> - * Find the swap type that corresponds to given device (if any).
> - *
> - * @offset - number of the PAGE_SIZE-sized block of the device, starting
> - * from 0, in which the swap header is expected to be located.
> - *
> - * This is needed for the suspend to disk (aka swsusp).
> - */
> -int swap_type_of(dev_t device, sector_t offset)
> +static int swap_type_of(dev_t device, sector_t offset)

Maybe rename it while at it, it's a internal helper now and
no one is using it.

>  {
>  	int type;
>  
> +	lockdep_assert_held(&swap_lock);
> +
>  	if (!device)
>  		return -1;
>  
> -	spin_lock(&swap_lock);
>  	for (type = 0; type < nr_swapfiles; type++) {
>  		struct swap_info_struct *sis = swap_info[type];
>  
> @@ -2164,16 +2157,70 @@ int swap_type_of(dev_t device, sector_t offset)
>  		if (device == sis->bdev->bd_dev) {
>  			struct swap_extent *se = first_se(sis);
>  
> -			if (se->start_block == offset) {
> -				spin_unlock(&swap_lock);
> +			if (se->start_block == offset)
>  				return type;
> -			}
>  		}
>  	}
> -	spin_unlock(&swap_lock);
>  	return -ENODEV;
>  }
>  
> +/*
> + * Finds the swap type and safely acquires a reference to the swap device
> + * to prevent race conditions with swapoff.
> + *
> + * This should be used in environments like uswsusp where a race condition
> + * exists between configuring the resume device and allocating a swap slot.
> + * For sysfs hibernation where user-space is frozen (making swapoff
> + * impossible), use find_hibernation_swap_type() instead.
> + *
> + * The caller must drop the reference using put_hibernation_swap_type().
> + */

You can follow the kernel doc format.

> +int get_hibernation_swap_type(dev_t device, sector_t offset)
> +{
> +	int type;
> +	struct swap_info_struct *sis;
> +
> +	spin_lock(&swap_lock);
> +	type = swap_type_of(device, offset);
> +	sis = swap_type_to_info(type);
> +	if (!sis || !get_swap_device_info(sis))
> +		type = -1;
> +
> +	spin_unlock(&swap_lock);
> +	return type;
> +}
> +
> +/*
> + * Drops the reference to the swap device previously acquired by
> + * get_hibernation_swap_type().
> + */
> +void put_hibernation_swap_type(int type)
> +{
> +	struct swap_info_struct *sis;
> +
> +	sis = swap_type_to_info(type);
> +	if (!sis)
> +		return;

I think it should never see sis == NULL here?

> +
> +	put_swap_device(sis);
> +}
> +
> +/*
> + * Simple lookup without acquiring a reference. Used by the sysfs
> + * hibernation path where user-space is already frozen, making
> + * swapoff impossible.
> + */
> +int find_hibernation_swap_type(dev_t device, sector_t offset)
> +{
> +	int type;
> +
> +	spin_lock(&swap_lock);
> +	type = swap_type_of(device, offset);
> +	spin_unlock(&swap_lock);
> +
> +	return type;
> +}
> +
>  int find_first_swap(dev_t *device)
>  {
>  	int type;
> @@ -2971,10 +3018,23 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
>  	 * spinlock) will be waited too.  This makes it easy to
>  	 * prevent folio_test_swapcache() and the following swap cache
>  	 * operations from racing with swapoff.
> +	 *
> +	 * Note: if a hibernation session is actively holding a swap
> +	 * device reference, swapoff will block here until the reference
> +	 * is released via put_hibernation_swap_type() or the wait is
> +	 * interrupted by a signal.

This looks really bad... It means swapoff will hung unless user send a
signal to stop it? How does that happen?

If hibernate may hold a reference without allocating any slot for a
long time, then maybe we better introduce a new si->flags bit to
indicate a device is used by hibernate, so swapoff can abort early
with a -EBUSY.

If hibernate only holds the swap device reference after it allocated
any slot, then we can avoid use a flag but use a hibernate type in
swap table instead:

diff --git a/mm/swap_table.h b/mm/swap_table.h
index 8415ffbe2b9c..025e004fc2e7 100644
--- a/mm/swap_table.h
+++ b/mm/swap_table.h
@@ -25,6 +25,7 @@ struct swap_table {
  * PFN:      | SWAP_COUNT |------ PFN -------|10| - Cached slot
  * Pointer:  |----------- Pointer ----------|100| - (Unused)
  * Bad:      |------------- 1 -------------|1000| - Bad slot
+ * Exclusive:|---- 0  ----| ------ 1 -----|10000| - Exclusive usage
  *
  * SWAP_COUNT is `SWP_TB_COUNT_BITS` long, each entry is an atomic long.
  *
@@ -46,6 +47,8 @@ struct swap_table {
  *   because only the lower three bits can be used as a marker for 8 bytes
  *   aligned pointers.
  *
+ * - Exclusive usage: e.g. for hibernation.
+ *
  * - Bad: Swap slot is reserved, protects swap header or holes on swap devices.
  */

Both readahead and swapoff (unuse scan) will abort upon seeing such slot,
we solve both readahead and swapoff issue together.

How do you think? We can use the flag idea first.

>  	 */
>  	percpu_ref_kill(&p->users);
>  	synchronize_rcu();
> -	wait_for_completion(&p->comp);
> +	err = wait_for_completion_interruptible(&p->comp);
> +	if (err) {
> +		percpu_ref_resurrect(&p->users);
> +		synchronize_rcu();

Do we need a synchronize_rcu here? It's required above because we are
releasing the resources so all RCU readers must exit from grace
period. But here we are aborting and not releasing anything so
there is no such need?

> +		reinit_completion(&p->comp);
> +		reinsert_swap_info(p);
> +		goto out_dput;
> +	}
> +
>  
>  	flush_work(&p->discard_work);
>  	flush_work(&p->reclaim_work);
> -- 
> 2.34.1

^ permalink raw reply related

* [PATCH] devfreq: event: rockchip-dfi: fix missing clk_disable_unprepare() on error
From: Anas Iqbal @ 2026-03-19 16:30 UTC (permalink / raw)
  To: Chanwoo Choi, MyungJoo Ham, Heiko Stuebner
  Cc: Kyungmin Park, Sascha Hauer, Sebastian Reichel, Jonathan Cameron,
	linux-pm, linux-arm-kernel, linux-rockchip, linux-kernel,
	Anas Iqbal

Smatch reports:
drivers/devfreq/event/rockchip-dfi.c:215 rockchip_dfi_enable() warn:
'dfi->clk' from clk_prepare_enable() not released.

If rockchip_dfi_ddrtype_to_ctrl() fails after clk_prepare_enable(),
the clock is not disabled, leading to a resource leak.

Add clk_disable_unprepare() in the error path to properly release
the clock.

Fixes: d724f4a4581b ("PM / devfreq: rockchip-dfi: Prepare for multiple users")
Signed-off-by: Anas Iqbal <mohd.abd.6602@gmail.com>
---
 drivers/devfreq/event/rockchip-dfi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
index 5e6e7e900bda..8db0bceeded4 100644
--- a/drivers/devfreq/event/rockchip-dfi.c
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -185,8 +185,10 @@ static int rockchip_dfi_enable(struct rockchip_dfi *dfi)
 	}
 
 	ret = rockchip_dfi_ddrtype_to_ctrl(dfi, &ctrl);
-	if (ret)
+	if (ret) {
+		clk_disable_unprepare(dfi->clk);
 		goto out;
+	}
 
 	for (i = 0; i < dfi->max_channels; i++) {
 
-- 
2.43.0


^ permalink raw reply related

* Re: (subset) [PATCH v2 00/10] workqueue / drivers: Add device-managed allocate workqueue
From: Lee Jones @ 2026-03-19 16:21 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
	Jonathan Corbet, Shuah Khan, Tejun Heo, Lai Jiangshan,
	Tobias Schrammm, Sebastian Reichel, Andy Shevchenko,
	Dan Carpenter, Krzysztof Kozlowski, Lee Jones, Dzmitry Sankouski,
	Matthias Brugger, AngeloGioacchino Del Regno, Benson Leung,
	Tzung-Bi Shih, Krzysztof Kozlowski
  Cc: Matti Vaittinen, driver-core, linux-doc, linux-kernel,
	Sebastian Reichel, linux-pm, linux-arm-kernel, linux-mediatek,
	chrome-platform, stable
In-Reply-To: <20260305-workqueue-devm-v2-0-66a38741c652@oss.qualcomm.com>

On Thu, 05 Mar 2026 22:45:39 +0100, Krzysztof Kozlowski wrote:
> Merging / Dependency
> ====================
> All further patches depend on the first one, thus this probably should
> go via one tree, e.g. power supply.  The first patch might be needed for
> other trees as well, e.g. if more drivers are discovered, so the best if
> it is on dedicated branch in case it has to be shared.
> 
> [...]

Applied, thanks!

[07/10] mfd: ezx-pcap: Drop memory allocation error message
        commit: 33e0316783a205625b7c55a78041ddc0d5dce7c7
[08/10] mfd: ezx-pcap: Return directly instead of empty gotos
        commit: 444e11d9d9e56c994da8a253cdf7f33ac2eeb15b
[09/10] mfd: ezx-pcap: Avoid rescheduling after destroying workqueue
        commit: 356ee03f6ae7d04f90d8e2104660193c4f3a071c

--
Lee Jones [李琼斯]


^ permalink raw reply

* Re: [PATCH v8 05/10] pmdomain: samsung: convert to using regmap
From: Marek Szyprowski @ 2026-03-19 15:57 UTC (permalink / raw)
  To: André Draszik, Ulf Hansson
  Cc: 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: <ae31c62c940e99077d44e1935465dce7db0e4c06.camel@linaro.org>

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().

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply

* Re: [GIT PULL] Power management fixes for v7.0-rc5
From: pr-tracker-bot @ 2026-03-19 15:52 UTC (permalink / raw)
  To: Rafael J. Wysocki; +Cc: Linus Torvalds, Linux PM, Linux Kernel Mailing List
In-Reply-To: <CAJZ5v0jQxkAKLgx9e7FqdWq67EO_97=A9kyT_Yd2QQbDZakUjw@mail.gmail.com>

The pull request you sent on Thu, 19 Mar 2026 15:53:41 +0100:

> git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git pm-7.0-rc5

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/e9825d1c79570b4c11259e826b3f7c1511544a85

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html

^ 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 15:46 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,
	Jonathan Cameron, 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: <abuOLq6bMPa0nNAL@aschofie-mobl2.lan>

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

> [   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] x86, hibernate: Remove inclusion of crypto/hash.h
From: Rafael J. Wysocki @ 2026-03-19 15:15 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Rafael J . Wysocki, linux-pm, Pavel Machek, x86, linux-kernel
In-Reply-To: <20260314201225.38822-1-ebiggers@kernel.org>

On Sat, Mar 14, 2026 at 9:15 PM Eric Biggers <ebiggers@kernel.org> wrote:
>
> hibernate_64.c does not do any cryptographic hashing, so the header
> crypto/hash.h is not needed at all.
>
> Signed-off-by: Eric Biggers <ebiggers@kernel.org>
> ---
>  arch/x86/power/hibernate_64.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c
> index a595953f1d6d8..e72d26acae797 100644
> --- a/arch/x86/power/hibernate_64.c
> +++ b/arch/x86/power/hibernate_64.c
> @@ -12,12 +12,10 @@
>  #include <linux/suspend.h>
>  #include <linux/scatterlist.h>
>  #include <linux/kdebug.h>
>  #include <linux/pgtable.h>
>
> -#include <crypto/hash.h>
> -
>  #include <asm/e820/api.h>
>  #include <asm/init.h>
>  #include <asm/proto.h>
>  #include <asm/page.h>
>  #include <asm/mtrr.h>
>
> base-commit: 1c9982b4961334c1edb0745a04cabd34bc2de675
> --

Applied as 7.1 material, thanks!

^ permalink raw reply

* Re: [PATCH v7 0/3] HID: Add support for multiple batteries per device
From: Benjamin Tissoires @ 2026-03-19 15:01 UTC (permalink / raw)
  To: linux-input, Lucas Zampieri
  Cc: linux-kernel, Jiri Kosina, Sebastian Reichel, Bastien Nocera,
	linux-pm
In-Reply-To: <20260314010533.110278-1-lcasmz54@gmail.com>

On Sat, 14 Mar 2026 01:05:27 +0000, Lucas Zampieri wrote:
> This series adds support for HID devices with multiple batteries.
> 
> Currently, the HID battery reporting subsystem only supports one battery per
> device. There are several devices with multiple batteries that would benefit
> from this support:
> - Gaming headsets with batteries in both the headset and charging dock
> - Wireless earbuds with per-earbud batteries plus charging case
> - Split keyboards with per-side batteries
> 
> [...]

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git (for-7.1/core-v2), thanks!

[1/3] HID: input: Convert battery code to devm_*
      https://git.kernel.org/hid/hid/c/5a9df498581a
[2/3] HID: input: Introduce struct hid_battery and refactor battery code
      https://git.kernel.org/hid/hid/c/7a3ac62473f2
[3/3] HID: input: Add support for multiple batteries per device
      https://git.kernel.org/hid/hid/c/4a58ae85c3f9

Cheers,
-- 
Benjamin Tissoires <bentiss@kernel.org>


^ permalink raw reply

* [GIT PULL] Power management fixes for v7.0-rc5
From: Rafael J. Wysocki @ 2026-03-19 14:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Linux PM, Linux Kernel Mailing List

Hi Linus,

Please pull from the tag

 git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git \
 pm-7.0-rc5

with top-most commit 9633370653151a0d5637634d1887d2f32511e69f

 Merge branch 'pm-runtime'

on top of commit f338e77383789c0cae23ca3d48adcc5e9e137e3c

 Linux 7.0-rc4

to receive power management fixes for 7.0-rc5.

These fix an idle loop issue exposed by recent changes and a race
condition related to device removal in the runtime PM core code:

 - Consolidate the handling of two special cases in the idle loop that
   occur when only one CPU idle state is present (Rafael Wysocki)

 - Fix a race condition related to device removal in the runtime PM
   core code that may cause a stale device object pointer to be
   dereferenced (Bart Van Assche)

Thanks!


---------------

Bart Van Assche (1):
      PM: runtime: Fix a race condition related to device removal

Rafael J. Wysocki (1):
      sched: idle: Consolidate the handling of two special cases

---------------

 drivers/base/power/runtime.c |  1 +
 kernel/sched/idle.c          | 30 +++++++++++++++++++++---------
 2 files changed, 22 insertions(+), 9 deletions(-)

^ permalink raw reply

* Re: [PATCH v7 7/7] dax/hmem: Reintroduce Soft Reserved ranges back into the iomem tree
From: Jonathan Cameron @ 2026-03-19 14:35 UTC (permalink / raw)
  To: Smita Koralahalli
  Cc: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm,
	Ard Biesheuvel, Alison Schofield, 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: <20260319011500.241426-8-Smita.KoralahalliChannabasappa@amd.com>

On Thu, 19 Mar 2026 01:15:00 +0000
Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> wrote:

> Reworked from a patch by Alison Schofield <alison.schofield@intel.com>
> 
> Reintroduce Soft Reserved range into the iomem_resource tree for HMEM
> to consume.
> 
> This restores visibility in /proc/iomem for ranges actively in use, while
> avoiding the early-boot conflicts that occurred when Soft Reserved was
> published into iomem before CXL window and region discovery.
> 
> Link: https://lore.kernel.org/linux-cxl/29312c0765224ae76862d59a17748c8188fb95f1.1692638817.git.alison.schofield@intel.com/
> Co-developed-by: Alison Schofield <alison.schofield@intel.com>
> Signed-off-by: Alison Schofield <alison.schofield@intel.com>
> Co-developed-by: Zhijian Li <lizhijian@fujitsu.com>
> Signed-off-by: Zhijian Li <lizhijian@fujitsu.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>
> Reviewed-by: Dan Williams <dan.j.williams@intel.com>
One minor update needed as kmalloc_obj() has shown up in meantime.

Thanks

Jonathan
> ---
>  drivers/dax/hmem/hmem.c | 32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
> index 8c574123bd3b..15e462589b92 100644
> --- a/drivers/dax/hmem/hmem.c
> +++ b/drivers/dax/hmem/hmem.c
> @@ -72,6 +72,34 @@ void dax_hmem_flush_work(void)
>  }
>  EXPORT_SYMBOL_GPL(dax_hmem_flush_work);
>  
> +static void remove_soft_reserved(void *r)
> +{
> +	remove_resource(r);
> +	kfree(r);
> +}
> +
> +static int add_soft_reserve_into_iomem(struct device *host,
> +				       const struct resource *res)
> +{
> +	int rc;
> +
> +	struct resource *soft __free(kfree) =
> +		kmalloc(sizeof(*res), GFP_KERNEL);

Update to

	struct resource *soft __free(kfree) = kmalloc_obj(*soft);

Got added in 7.0 with lots of call sites updated via scripting.

Not sure why this had sizeof(*res) rather than sizeof(*soft).
Same type but should have been soft!  If nothing else that would
probably have broken the scripts looking for where we should
be using kmalloc_obj().


	
> +	if (!soft)
> +		return -ENOMEM;
> +
> +	*soft = DEFINE_RES_NAMED_DESC(res->start, (res->end - res->start + 1),
> +				      "Soft Reserved", IORESOURCE_MEM,
> +				      IORES_DESC_SOFT_RESERVED);
> +
> +	rc = insert_resource(&iomem_resource, soft);
> +	if (rc)
> +		return rc;
> +
> +	return devm_add_action_or_reset(host, remove_soft_reserved,
> +					no_free_ptr(soft));
> +}
> +
>  static int hmem_register_device(struct device *host, int target_nid,
>  				const struct resource *res)
>  {
> @@ -94,7 +122,9 @@ static int hmem_register_device(struct device *host, int target_nid,
>  	if (rc != REGION_INTERSECTS)
>  		return 0;
>  
> -	/* TODO: Add Soft-Reserved memory back to iomem */
> +	rc = add_soft_reserve_into_iomem(host, res);
> +	if (rc)
> +		return rc;
>  
>  	id = memregion_alloc(GFP_KERNEL);
>  	if (id < 0) {


^ permalink raw reply

* Re: [PATCH v7 6/7] dax/hmem, cxl: Defer and resolve Soft Reserved ownership
From: Jonathan Cameron @ 2026-03-19 14:29 UTC (permalink / raw)
  To: Smita Koralahalli
  Cc: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm,
	Ard Biesheuvel, Alison Schofield, 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: <20260319011500.241426-7-Smita.KoralahalliChannabasappa@amd.com>

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

> ---
>  drivers/dax/bus.h         |  7 +++++
>  drivers/dax/cxl.c         |  1 +
>  drivers/dax/hmem/device.c |  3 ++
>  drivers/dax/hmem/hmem.c   | 66 +++++++++++++++++++++++++++++++++++++--
>  4 files changed, 75 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
> index cbbf64443098..ebbfe2d6da14 100644
> --- a/drivers/dax/bus.h
> +++ b/drivers/dax/bus.h
> @@ -49,6 +49,13 @@ void dax_driver_unregister(struct dax_device_driver *dax_drv);
>  void kill_dev_dax(struct dev_dax *dev_dax);
>  bool static_dev_dax(struct dev_dax *dev_dax);
>  
> +#if IS_ENABLED(CONFIG_DEV_DAX_HMEM)
> +extern bool dax_hmem_initial_probe;
> +void dax_hmem_flush_work(void);
> +#else
> +static inline void dax_hmem_flush_work(void) { }
> +#endif
> +
>  #define MODULE_ALIAS_DAX_DEVICE(type) \
>  	MODULE_ALIAS("dax:t" __stringify(type) "*")
>  #define DAX_DEVICE_MODALIAS_FMT "dax:t%d"
> diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c
> index a2136adfa186..3ab39b77843d 100644
> --- a/drivers/dax/cxl.c
> +++ b/drivers/dax/cxl.c
> @@ -44,6 +44,7 @@ static struct cxl_driver cxl_dax_region_driver = {
>  
>  static void cxl_dax_region_driver_register(struct work_struct *work)
>  {
> +	dax_hmem_flush_work();
>  	cxl_driver_register(&cxl_dax_region_driver);
>  }
>  
> diff --git a/drivers/dax/hmem/device.c b/drivers/dax/hmem/device.c
> index 56e3cbd181b5..991a4bf7d969 100644
> --- a/drivers/dax/hmem/device.c
> +++ b/drivers/dax/hmem/device.c
> @@ -8,6 +8,9 @@
>  static bool nohmem;
>  module_param_named(disable, nohmem, bool, 0444);
>  
> +bool dax_hmem_initial_probe;
> +EXPORT_SYMBOL_GPL(dax_hmem_initial_probe);
> +
>  static bool platform_initialized;
>  static DEFINE_MUTEX(hmem_resource_lock);
>  static struct resource hmem_active = {
> 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.


> +
> +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

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

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);
-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 2/3] mm/swap: remove redundant swap device reference in alloc/free
From: Youngjun Park @ 2026-03-19 14:24 UTC (permalink / raw)
  To: rafael, akpm
  Cc: chrisl, kasong, pavel, shikemeng, nphamcs, bhe, baohua,
	youngjun.park, usama.arif, linux-mm, linux-pm
In-Reply-To: <20260319142404.3683019-1-youngjun.park@lge.com>

In the previous commit, uswsusp was modified to acquire the swap device
reference at the time of determining the swap type. As a result, it is
no longer necessary to repeatedly acquire and release the reference to
protect against swapoff every time a swap slot is allocated.

For hibernation via the sysfs interface, user-space processes are already
frozen, making swapoff inherently impossible. Thus, acquiring and
releasing the reference during allocation is unnecessary. Furthermore,
even after returning from suspend, processes are not yet thawed when
swap slots are freed, meaning reference management is not required at
that stage either.

Therefore, remove the redundant swap device reference acquire and release
operations from the hibernation swap allocation and free functions.

Additionally, remove the SWP_WRITEOK check before allocation. This check
is redundant because the cluster allocation logic already handles it.

Signed-off-by: Youngjun Park <youngjun.park@lge.com>
---
 mm/swapfile.c | 43 ++++++++++++++++++++-----------------------
 1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 5069074ab11b..f1188743037a 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1923,7 +1923,12 @@ void swap_put_entries_direct(swp_entry_t entry, int nr)
 }
 
 #ifdef CONFIG_HIBERNATION
-/* Allocate a slot for hibernation */
+/*
+ * Allocate a slot for hibernation.
+ *
+ * Note: The caller must ensure the swap device is stable, either by
+ * holding a reference or by freezing user-space before calling this.
+ */
 swp_entry_t swap_alloc_hibernation_slot(int type)
 {
 	struct swap_info_struct *si = swap_type_to_info(type);
@@ -1933,43 +1938,35 @@ swp_entry_t swap_alloc_hibernation_slot(int type)
 	if (!si)
 		goto fail;
 
-	/* This is called for allocating swap entry, not cache */
-	if (get_swap_device_info(si)) {
-		if (si->flags & SWP_WRITEOK) {
-			/*
-			 * Grab the local lock to be compliant
-			 * with swap table allocation.
-			 */
-			local_lock(&percpu_swap_cluster.lock);
-			offset = cluster_alloc_swap_entry(si, NULL);
-			local_unlock(&percpu_swap_cluster.lock);
-			if (offset)
-				entry = swp_entry(si->type, offset);
-		}
-		put_swap_device(si);
-	}
+	/*
+	 * Grab the local lock to be compliant
+	 * with swap table allocation.
+	 */
+	local_lock(&percpu_swap_cluster.lock);
+	offset = cluster_alloc_swap_entry(si, NULL);
+	local_unlock(&percpu_swap_cluster.lock);
+	if (offset)
+		entry = swp_entry(si->type, offset);
 fail:
 	return entry;
 }
 
-/* Free a slot allocated by swap_alloc_hibernation_slot */
+/*
+ * Free a slot allocated by swap_alloc_hibernation_slot.
+ * As with allocation, the caller must ensure the swap device is stable.
+ */
 void swap_free_hibernation_slot(swp_entry_t entry)
 {
-	struct swap_info_struct *si;
+	struct swap_info_struct *si = __swap_entry_to_info(entry);
 	struct swap_cluster_info *ci;
 	pgoff_t offset = swp_offset(entry);
 
-	si = get_swap_device(entry);
-	if (WARN_ON(!si))
-		return;
-
 	ci = swap_cluster_lock(si, offset);
 	swap_put_entry_locked(si, ci, offset);
 	swap_cluster_unlock(ci);
 
 	/* In theory readahead might add it to the swap cache by accident */
 	__try_to_reclaim_swap(si, offset, TTRS_ANYWAY);
-	put_swap_device(si);
 }
 
 static int swap_type_of(dev_t device, sector_t offset)
-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 1/3] mm/swap, PM: hibernate: fix swapoff race in uswsusp by getting swap reference
From: Youngjun Park @ 2026-03-19 14:24 UTC (permalink / raw)
  To: rafael, akpm
  Cc: chrisl, kasong, pavel, shikemeng, nphamcs, bhe, baohua,
	youngjun.park, usama.arif, linux-mm, linux-pm
In-Reply-To: <20260319142404.3683019-1-youngjun.park@lge.com>

Hibernation via uswsusp (/dev/snapshot ioctls) has a race: between
setting the resume swap area and allocating a swap slot, user-space is
not yet frozen, so swapoff can run and cause an incorrect slot allocation.

Fix this by keeping swap_type_of() as a static helper that requires
swap_lock to be held, and introducing new interfaces that wrap it with
proper locking and reference management:

- get_hibernation_swap_type(): Lookup under swap_lock + acquire a swap
  device reference to block swapoff (used by uswsusp).
- find_hibernation_swap_type(): Lookup under swap_lock only, no
  reference. Used by the sysfs path where user-space is already frozen,
  making swapoff impossible.
- put_hibernation_swap_type(): Release the reference.

Because the reference is held via get_swap_device(), swapoff will block
at wait_for_completion_interruptible() until put_hibernation_swap_type()
releases it. The wait is interruptible, so swapoff can be cancelled by
a signal.

Signed-off-by: Youngjun Park <youngjun.park@lge.com>
---
 include/linux/swap.h |  4 +-
 kernel/power/swap.c  |  2 +-
 kernel/power/user.c  | 15 ++++++--
 mm/swapfile.c        | 92 ++++++++++++++++++++++++++++++++++++--------
 4 files changed, 92 insertions(+), 21 deletions(-)

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 62fc7499b408..4266356f928c 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -452,7 +452,9 @@ static inline long get_nr_swap_pages(void)
 
 extern void si_swapinfo(struct sysinfo *);
 extern int add_swap_count_continuation(swp_entry_t, gfp_t);
-int swap_type_of(dev_t device, sector_t offset);
+int get_hibernation_swap_type(dev_t device, sector_t offset);
+int find_hibernation_swap_type(dev_t device, sector_t offset);
+void put_hibernation_swap_type(int type);
 int find_first_swap(dev_t *device);
 extern unsigned int count_swap_pages(int, int);
 extern sector_t swapdev_block(int, pgoff_t);
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 2e64869bb5a0..cc4764149e8f 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -341,7 +341,7 @@ static int swsusp_swap_check(void)
 	 * This is called before saving the image.
 	 */
 	if (swsusp_resume_device)
-		res = swap_type_of(swsusp_resume_device, swsusp_resume_block);
+		res = find_hibernation_swap_type(swsusp_resume_device, swsusp_resume_block);
 	else
 		res = find_first_swap(&swsusp_resume_device);
 	if (res < 0)
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 4401cfe26e5c..3e41544b99d5 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -71,7 +71,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
 	memset(&data->handle, 0, sizeof(struct snapshot_handle));
 	if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
 		/* Hibernating.  The image device should be accessible. */
-		data->swap = swap_type_of(swsusp_resume_device, 0);
+		data->swap = get_hibernation_swap_type(swsusp_resume_device, 0);
 		data->mode = O_RDONLY;
 		data->free_bitmaps = false;
 		error = pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION);
@@ -90,8 +90,10 @@ static int snapshot_open(struct inode *inode, struct file *filp)
 			data->free_bitmaps = !error;
 		}
 	}
-	if (error)
+	if (error) {
+		put_hibernation_swap_type(data->swap);
 		hibernate_release();
+	}
 
 	data->frozen = false;
 	data->ready = false;
@@ -115,6 +117,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
 	data = filp->private_data;
 	data->dev = 0;
 	free_all_swap_pages(data->swap);
+	put_hibernation_swap_type(data->swap);
 	if (data->frozen) {
 		pm_restore_gfp_mask();
 		free_basic_memory_bitmaps();
@@ -235,11 +238,17 @@ static int snapshot_set_swap_area(struct snapshot_data *data,
 		offset = swap_area.offset;
 	}
 
+	/*
+	 * Put the reference if a swap area was already
+	 * set by SNAPSHOT_SET_SWAP_AREA.
+	 */
+	put_hibernation_swap_type(data->swap);
+
 	/*
 	 * User space encodes device types as two-byte values,
 	 * so we need to recode them
 	 */
-	data->swap = swap_type_of(swdev, offset);
+	data->swap = get_hibernation_swap_type(swdev, offset);
 	if (data->swap < 0)
 		return swdev ? -ENODEV : -EINVAL;
 	data->dev = swdev;
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 94af29d1de88..5069074ab11b 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -133,7 +133,7 @@ static DEFINE_PER_CPU(struct percpu_swap_cluster, percpu_swap_cluster) = {
 /* May return NULL on invalid type, caller must check for NULL return */
 static struct swap_info_struct *swap_type_to_info(int type)
 {
-	if (type >= MAX_SWAPFILES)
+	if (type < 0 || type >= MAX_SWAPFILES)
 		return NULL;
 	return READ_ONCE(swap_info[type]); /* rcu_dereference() */
 }
@@ -1972,22 +1972,15 @@ void swap_free_hibernation_slot(swp_entry_t entry)
 	put_swap_device(si);
 }
 
-/*
- * Find the swap type that corresponds to given device (if any).
- *
- * @offset - number of the PAGE_SIZE-sized block of the device, starting
- * from 0, in which the swap header is expected to be located.
- *
- * This is needed for the suspend to disk (aka swsusp).
- */
-int swap_type_of(dev_t device, sector_t offset)
+static int swap_type_of(dev_t device, sector_t offset)
 {
 	int type;
 
+	lockdep_assert_held(&swap_lock);
+
 	if (!device)
 		return -1;
 
-	spin_lock(&swap_lock);
 	for (type = 0; type < nr_swapfiles; type++) {
 		struct swap_info_struct *sis = swap_info[type];
 
@@ -1997,16 +1990,70 @@ int swap_type_of(dev_t device, sector_t offset)
 		if (device == sis->bdev->bd_dev) {
 			struct swap_extent *se = first_se(sis);
 
-			if (se->start_block == offset) {
-				spin_unlock(&swap_lock);
+			if (se->start_block == offset)
 				return type;
-			}
 		}
 	}
-	spin_unlock(&swap_lock);
 	return -ENODEV;
 }
 
+/*
+ * Finds the swap type and safely acquires a reference to the swap device
+ * to prevent race conditions with swapoff.
+ *
+ * This should be used in environments like uswsusp where a race condition
+ * exists between configuring the resume device and allocating a swap slot.
+ * For sysfs hibernation where user-space is frozen (making swapoff
+ * impossible), use find_hibernation_swap_type() instead.
+ *
+ * The caller must drop the reference using put_hibernation_swap_type().
+ */
+int get_hibernation_swap_type(dev_t device, sector_t offset)
+{
+	int type;
+	struct swap_info_struct *sis;
+
+	spin_lock(&swap_lock);
+	type = swap_type_of(device, offset);
+	sis = swap_type_to_info(type);
+	if (!sis || !get_swap_device_info(sis))
+		type = -1;
+
+	spin_unlock(&swap_lock);
+	return type;
+}
+
+/*
+ * Drops the reference to the swap device previously acquired by
+ * get_hibernation_swap_type().
+ */
+void put_hibernation_swap_type(int type)
+{
+	struct swap_info_struct *sis;
+
+	sis = swap_type_to_info(type);
+	if (!sis)
+		return;
+
+	put_swap_device(sis);
+}
+
+/*
+ * Simple lookup without acquiring a reference. Used by the sysfs
+ * hibernation path where user-space is already frozen, making
+ * swapoff impossible.
+ */
+int find_hibernation_swap_type(dev_t device, sector_t offset)
+{
+	int type;
+
+	spin_lock(&swap_lock);
+	type = swap_type_of(device, offset);
+	spin_unlock(&swap_lock);
+
+	return type;
+}
+
 int find_first_swap(dev_t *device)
 {
 	int type;
@@ -2837,10 +2884,23 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	 * spinlock) will be waited too.  This makes it easy to
 	 * prevent folio_test_swapcache() and the following swap cache
 	 * operations from racing with swapoff.
+	 *
+	 * Note: if a hibernation session is actively holding a swap
+	 * device reference, swapoff will block here until the reference
+	 * is released via put_hibernation_swap_type() or the wait is
+	 * interrupted by a signal.
 	 */
 	percpu_ref_kill(&p->users);
 	synchronize_rcu();
-	wait_for_completion(&p->comp);
+	err = wait_for_completion_interruptible(&p->comp);
+	if (err) {
+		percpu_ref_resurrect(&p->users);
+		synchronize_rcu();
+		reinit_completion(&p->comp);
+		reinsert_swap_info(p);
+		goto out_dput;
+	}
+
 
 	flush_work(&p->discard_work);
 	flush_work(&p->reclaim_work);
-- 
2.34.1


^ permalink raw reply related

* [PATCH v5 0/3] Fix swapoff race and cleanup in hibernation swap path
From: Youngjun Park @ 2026-03-19 14:24 UTC (permalink / raw)
  To: rafael, akpm
  Cc: chrisl, kasong, pavel, shikemeng, nphamcs, bhe, baohua,
	youngjun.park, usama.arif, linux-mm, linux-pm

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.

This patch series addresses these issues:
- Patch 1: Fixes the swapoff race in uswsusp by holding the swap device
  reference from the point the swap device is looked up.
- Patch 2: Removes the overhead of per-slot reference counting in alloc/free
  paths and cleans up the redundant SWP_WRITEOK check.
- Patch 3: Fixes a spurious WARNING in the uswsusp GFP mask restore path.
  (Founded during uswsusp test)

Links:
RFC v1: https://lore.kernel.org/linux-mm/20260305202413.1888499-1-usama.arif@linux.dev/T/#m3693d45180f14f441b6951984f4b4bfd90ec0c9d
RFC v2: https://lore.kernel.org/linux-mm/20260306024608.1720991-1-youngjun.park@lge.com/
RFC v3: https://lore.kernel.org/linux-mm/20260312112511.3596781-1-youngjun.park@lge.com/
v4: https://lore.kernel.org/linux-mm/abv+rjgyArqZ2uym@yjaykim-PowerEdge-T330/T/#m924fa3e58d0f0da488300653163ee8db7e870e4a

Testing:
- Hibernate/resume via sysfs
  (echo reboot > /sys/power/disk && echo disk > /sys/power/state)
- Hibernate with suspend via sysfs
  (echo suspend > /sys/power/disk && echo disk > /sys/power/state)
- Hibernate/resume via uswsusp (suspend-utils s2disk/resume on QEMU)
  - Verified swap I/O works correctly after resume.
  - Verified swapoff succeeds after snapshot resume completes.
  - Verified pm_restore_gfp_mask() WARNING no longer triggers (Patch 3).
- swapoff during active uswsusp session:
  - Verified swapoff blocks while uswsusp holds swap reference.
  - Verified swapoff can be cancelled by signal (e.g. Ctrl+C).
  - Verified swapoff succeeds after uswsusp process terminates.

Changelog:
v4 -> v5:
 - Rebased onto v7.0-rc4 (Rafael J. Wysocki comment)
 - No functional changes. rebase conflict fix.

rfc v3 -> v4:
 - Introduced get/find/put_hibernation_swap_type() helpers per Kairui's
   feedback. find_ for lookup-only, get/put for reference management.
 - Switched to swap_type_to_info() and added type < 0 check per
   Kairui's suggestion.
 - Fixed get_hibernation_swap_type() return when ref == false (Reviewd by Kairui)
 - Made swapoff wait interruptible to prevent hang when uswsusp
   holds a swap reference.
 - Fixed spurious WARN_ON in pm_restore_gfp_mask() by introducing
   pm_restore_gfp_mask_safe() (Patch 3).
 - Updated commit messages and added comments for clarity.
 - Rebased onto latest mm-new tree.

 Note: Kairui suggested adding WARN on NULL in put_hibernation_swap_type(),
 but kept silent return instead, as type can legitimately be -1 when
 snapshot_open() fails to find a matching swap device. swap_type_to_info()
 returns NULL for type < 0, so the cleanup path stays simple.

rfc v2 -> rfc v3:
 - Split into 2 patches per Chris Li's feedback.
 - Simplified by not holding reference in normal hibernation path
   per Chris Li's suggestion.
 - Removed redundant SWP_WRITEOK check.
 - Rebased onto f543926f9d0c3f6dfb354adfe7fbaeedd1277c6b.

rfc v1 -> rfc v2:
 - Squashed into single patch per Usama Arif's feedback.

Youngjun Park (3):
  mm/swap, PM: hibernate: fix swapoff race in uswsusp by getting swap
    reference
  mm/swap: remove redundant swap device reference in alloc/free
  PM: hibernate: fix spurious GFP mask WARNING in uswsusp path

 include/linux/suspend.h |   1 +
 include/linux/swap.h    |   4 +-
 kernel/power/main.c     |   7 +++
 kernel/power/swap.c     |   2 +-
 kernel/power/user.c     |  19 ++++--
 mm/swapfile.c           | 135 ++++++++++++++++++++++++++++------------
 6 files changed, 122 insertions(+), 46 deletions(-)

base-commit: f338e77383789c0cae23ca3d48adcc5e9e137e3c
-- 
2.34.1

^ permalink raw reply

* Re: [PATCH 12/61] quota: Prefer IS_ERR_OR_NULL over manual NULL check
From: Jan Kara @ 2026-03-19 14:13 UTC (permalink / raw)
  To: Philipp Hahn
  Cc: amd-gfx, apparmor, bpf, ceph-devel, cocci, dm-devel, dri-devel,
	gfs2, intel-gfx, intel-wired-lan, iommu, kvm, linux-arm-kernel,
	linux-block, linux-bluetooth, linux-btrfs, linux-cifs, linux-clk,
	linux-erofs, linux-ext4, linux-fsdevel, linux-gpio, linux-hyperv,
	linux-input, linux-kernel, linux-leds, linux-media, linux-mips,
	linux-mm, linux-modules, linux-mtd, linux-nfs, linux-omap,
	linux-phy, linux-pm, linux-rockchip, linux-s390, linux-scsi,
	linux-sctp, linux-security-module, linux-sh, linux-sound,
	linux-stm32, linux-trace-kernel, linux-usb, linux-wireless,
	netdev, ntfs3, samba-technical, sched-ext, target-devel,
	tipc-discussion, v9fs, Jan Kara
In-Reply-To: <20260310-b4-is_err_or_null-v1-12-bd63b656022d@avm.de>

On Tue 10-03-26 12:48:38, Philipp Hahn wrote:
> Prefer using IS_ERR_OR_NULL() over using IS_ERR() and a manual NULL
> check.
> 
> Change generated with coccinelle.
> 
> To: Jan Kara <jack@suse.com>
> Cc: linux-kernel@vger.kernel.org
> Signed-off-by: Philipp Hahn <phahn-oss@avm.de>

Thanks for the patch but frankly I find the original variant clearer wrt
what is going on. So I prefer to keep the code as is.

								Honza

> ---
>  fs/quota/quota.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/quota/quota.c b/fs/quota/quota.c
> index 33bacd70758007129e0375bab44d7431195ec441..2e09fc247d0cf45b9e83a4f8a0be7ea694c8c2a1 100644
> --- a/fs/quota/quota.c
> +++ b/fs/quota/quota.c
> @@ -965,7 +965,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
>  	else
>  		drop_super_exclusive(sb);
>  out:
> -	if (pathp && !IS_ERR(pathp))
> +	if (!IS_ERR_OR_NULL(pathp))
>  		path_put(pathp);
>  	return ret;
>  }
> 
> -- 
> 2.43.0
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply

* Re: [PATCH v7 3/7] dax/cxl, hmem: Initialize hmem early and defer dax_cxl binding
From: Jonathan Cameron @ 2026-03-19 14:11 UTC (permalink / raw)
  To: Alison Schofield
  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: <abuOLq6bMPa0nNAL@aschofie-mobl2.lan>

On Wed, 18 Mar 2026 22:48:30 -0700
Alison Schofield <alison.schofield@intel.com> 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.

Not patch 6?  dax_hmem_flush_work() is in there + it doesn't
use a static declaration of the work items.

I've not figure out the path yet but it looks more suspicious to me
than this path.

Jonathan

> 
> 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
> [   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

* [PATCH] tools/power turbostat: Allow execution to continue after perf_l2_init() failure
From: David Arcari @ 2026-03-19 14:03 UTC (permalink / raw)
  To: Len Brown; +Cc: David Arcari, linux-pm, linux-kernel

Currently, if perf_l2_init() fails turbostat exits after issuing the
following error (which was encountered on AlderLake):

turbostat: perf_l2_init(cpu0, 0x0, 0xff24) REFS: Invalid argument

This occurs because perf_l2_init() calls err(). However, the code has been
written in such a manner that it is able to perform cleanup and continue.
Therefore, this issue can be addressed by changing the appropriate calls
to err() to warnx().

Additionally, correct the PMU type arguments passed to the warning strings
in the ecore and lcore blocks so the logs accurately reflect the failing
counter type.

Signed-off-by: David Arcari <darcari@redhat.com>
Cc: Len Brown <lenb@kernel.org>
Cc: linux-pm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 tools/power/x86/turbostat/turbostat.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 1a2671c28209..f1b8059a4eec 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -9403,13 +9403,13 @@ void perf_l2_init(void)
 		if (!is_hybrid) {
 			fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP);
 			if (fd_l2_percpu[cpu] == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.refs);
 				free_fd_l2_percpu();
 				return;
 			}
 			retval = open_perf_counter(cpu, perf_pmu_types.uniform, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
 			if (retval == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.uniform, perf_model_support->first.hits);
 				free_fd_l2_percpu();
 				return;
 			}
@@ -9418,39 +9418,39 @@ void perf_l2_init(void)
 		if (perf_pcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_pcore_set)) {
 			fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.refs, -1, PERF_FORMAT_GROUP);
 			if (fd_l2_percpu[cpu] == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.refs);
 				free_fd_l2_percpu();
 				return;
 			}
 			retval = open_perf_counter(cpu, perf_pmu_types.pcore, perf_model_support->first.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
 			if (retval == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->first.hits);
 				free_fd_l2_percpu();
 				return;
 			}
 		} else if (perf_ecore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_ecore_set)) {
 			fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.refs, -1, PERF_FORMAT_GROUP);
 			if (fd_l2_percpu[cpu] == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.refs);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.refs);
 				free_fd_l2_percpu();
 				return;
 			}
 			retval = open_perf_counter(cpu, perf_pmu_types.ecore, perf_model_support->second.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
 			if (retval == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->second.hits);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.ecore, perf_model_support->second.hits);
 				free_fd_l2_percpu();
 				return;
 			}
 		} else if (perf_lcore_set && CPU_ISSET_S(cpu, cpu_possible_setsize, perf_lcore_set)) {
 			fd_l2_percpu[cpu] = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.refs, -1, PERF_FORMAT_GROUP);
 			if (fd_l2_percpu[cpu] == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.refs);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) REFS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.refs);
 				free_fd_l2_percpu();
 				return;
 			}
 			retval = open_perf_counter(cpu, perf_pmu_types.lcore, perf_model_support->third.hits, fd_l2_percpu[cpu], PERF_FORMAT_GROUP);
 			if (retval == -1) {
-				err(-1, "%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.pcore, perf_model_support->third.hits);
+				warnx("%s(cpu%d, 0x%x, 0x%llx) HITS", __func__, cpu, perf_pmu_types.lcore, perf_model_support->third.hits);
 				free_fd_l2_percpu();
 				return;
 			}
-- 
2.53.0


^ permalink raw reply related

* Re: [PATCH v7 4/7] dax: Track all dax_region allocations under a global resource tree
From: Jonathan Cameron @ 2026-03-19 13:59 UTC (permalink / raw)
  To: Smita Koralahalli
  Cc: linux-cxl, linux-kernel, nvdimm, linux-fsdevel, linux-pm,
	Ard Biesheuvel, Alison Schofield, 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: <20260319011500.241426-5-Smita.KoralahalliChannabasappa@amd.com>

On Thu, 19 Mar 2026 01:14:57 +0000
Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> wrote:

> Introduce a global "DAX Regions" resource root and register each
> dax_region->res under it via request_resource(). Release the resource on
> dax_region teardown.
> 
> By enforcing a single global namespace for dax_region allocations, this
> ensures only one of dax_hmem or dax_cxl can successfully register a
> dax_region for a given range.
> 
> Suggested-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>

The comment below is about the existing code.  If we decide not to tidy that
up for now and you swap the ordering of release_resource() and sysfs_remove_groups()
in unregister.

Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>

> ---
>  drivers/dax/bus.c | 20 +++++++++++++++++---
>  1 file changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index c94c09622516..448e2bc285c3 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -10,6 +10,7 @@
>  #include "dax-private.h"
>  #include "bus.h"
>  
> +static struct resource dax_regions = DEFINE_RES_MEM_NAMED(0, -1, "DAX Regions");
>  static DEFINE_MUTEX(dax_bus_lock);
>  
>  /*
> @@ -625,6 +626,7 @@ static void dax_region_unregister(void *region)
>  {
>  	struct dax_region *dax_region = region;
>  
> +	release_resource(&dax_region->res);

Should reverse the line above and the line below so we unwind in reverse of
setup.  I doubt it matters in practice today but keeping ordering like that
makes it much easier to see if a future patch messes things up.

>  	sysfs_remove_groups(&dax_region->dev->kobj,
>  			dax_region_attribute_groups);
>  	dax_region_put(dax_region);
> @@ -635,6 +637,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
>  		unsigned long flags)
>  {
>  	struct dax_region *dax_region;
> +	int rc;
>  
>  	/*
>  	 * The DAX core assumes that it can store its private data in
> @@ -667,14 +670,25 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
>  		.flags = IORESOURCE_MEM | flags,
>  	};
>  
> -	if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
> -		kfree(dax_region);
> -		return NULL;
> +	rc = request_resource(&dax_regions, &dax_region->res);
> +	if (rc) {
> +		dev_dbg(parent, "dax_region resource conflict for %pR\n",
> +			&dax_region->res);
> +		goto err_res;
>  	}
>  
> +	if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups))
> +		goto err_sysfs;
> +
>  	if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))

This is curious. The code flips over to a kref_put() based release but we didn't
do anything with the kref in the previous call. So whilst not 'buggy' as such
it's definitely inconsistent and we should clean it up.

This should really have been doing the release via dax_region_put() from the
kref_init().  In practice that means never calling kfree(dax_regions) error paths
because the kref_init() is just after the allocation. Instead call dax_region_put()
in all those error paths.

 

>  		return NULL;
>  	return dax_region;
> +
> +err_sysfs:
> +	release_resource(&dax_region->res);
> +err_res:
> +	kfree(dax_region);

From above I think this should be
	dax_region_put(dax_region);

> +	return NULL;
>  }
>  EXPORT_SYMBOL_GPL(alloc_dax_region);
>  


^ permalink raw reply

* Re: [PATCH v4 0/3] mm/swap, PM: hibernate: fix swapoff race and optimize swap
From: YoungJun Park @ 2026-03-19 13:48 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: akpm, chrisl, kasong, pavel, shikemeng, nphamcs, bhe, baohua,
	usama.arif, linux-pm, linux-mm
In-Reply-To: <CAJZ5v0iOh46gM9YVFnvN6bYcG5_kcqASqS+38brRg2BWAtOOzw@mail.gmail.com>

On Thu, Mar 19, 2026 at 02:33:30PM +0100, Rafael J. Wysocki wrote:
> On Tue, Mar 17, 2026 at 7:13 PM 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.
> >
> > This patch series addresses these issues:
> > - Patch 1: Fixes the swapoff race in uswsusp by holding the swap device
> >   reference from the point the swap device is looked up.
> > - Patch 2: Removes the overhead of per-slot reference counting in alloc/free
> >   paths and cleans up the redundant SWP_WRITEOK check.
> > - Patch 3: Fixes a spurious WARNING in the uswsusp GFP mask restore path.
> >   (Founded during uswsusp test)
> >
> > Links:
> > RFC v1: https://lore.kernel.org/linux-mm/20260305202413.1888499-1-usama.arif@linux.dev/T/#m3693d45180f14f441b6951984f4b4bfd90ec0c9d
> > RFC v2: https://lore.kernel.org/linux-mm/20260306024608.1720991-1-youngjun.park@lge.com/
> > RFC v3: https://lore.kernel.org/linux-mm/20260312112511.3596781-1-youngjun.park@lge.com/
> >
> > Testing:
> > - Hibernate/resume via sysfs
> >   (echo reboot > /sys/power/disk && echo disk > /sys/power/state)
> > - Hibernate with suspend via sysfs
> >   (echo suspend > /sys/power/disk && echo disk > /sys/power/state)
> > - Hibernate/resume via uswsusp (suspend-utils s2disk/resume on QEMU)
> >   - Verified swap I/O works correctly after resume.
> >   - Verified swapoff succeeds after snapshot resume completes.
> >   - Verified pm_restore_gfp_mask() WARNING no longer triggers (Patch 3).
> > - swapoff during active uswsusp session:
> >   - Verified swapoff blocks while uswsusp holds swap reference.
> >   - Verified swapoff can be cancelled by signal (e.g. Ctrl+C).
> >   - Verified swapoff succeeds after uswsusp process terminates.
> >
> > Changelog:
> > rfc v3 -> v4:
> >  - Introduced get/find/put_hibernation_swap_type() helpers per Kairui's
> >    feedback. find_ for lookup-only, get/put for reference management.
> >  - Switched to swap_type_to_info() and added type < 0 check per
> >    Kairui's suggestion.
> >  - Fixed get_hibernation_swap_type() return when ref == false (Reviewd by Kairui)
> >  - Made swapoff wait interruptible to prevent hang when uswsusp
> >    holds a swap reference.
> >  - Fixed spurious WARN_ON in pm_restore_gfp_mask() by introducing
> >    pm_restore_gfp_mask_safe() (Patch 3).
> >  - Updated commit messages and added comments for clarity.
> >  - Rebased onto latest mm-new tree.
> >
> >  Note: Kairui suggested adding WARN on NULL in put_hibernation_swap_type(),
> >  but kept silent return instead, as type can legitimately be -1 when
> >  snapshot_open() fails to find a matching swap device. swap_type_to_info()
> >  returns NULL for type < 0, so the cleanup path stays simple.
> >
> > rfc v2 -> rfc v3:
> >  - Split into 2 patches per Chris Li's feedback.
> >  - Simplified by not holding reference in normal hibernation path
> >    per Chris Li's suggestion.
> >  - Removed redundant SWP_WRITEOK check.
> >  - Rebased onto f543926f9d0c3f6dfb354adfe7fbaeedd1277c6b.
> >
> > rfc v1 -> rfc v2:
> >  - Squashed into single patch per Usama Arif's feedback.
> >
> > Youngjun Park (3):
> >   mm/swap, PM: hibernate: fix swapoff race in uswsusp by getting swap
> >     reference
> >   mm/swap: remove redundant swap device reference in alloc/free
> >   PM: hibernate: fix spurious GFP mask WARNING in uswsusp path
> >
> >  include/linux/suspend.h |   1 +
> >  include/linux/swap.h    |   4 +-
> >  kernel/power/main.c     |   7 ++
> >  kernel/power/swap.c     |   2 +-
> >  kernel/power/user.c     |  19 +++--
> >  mm/swapfile.c           | 154 +++++++++++++++++++++++++++-------------
> >  6 files changed, 132 insertions(+), 55 deletions(-)
> >
> > --
> 
> Which kernel version does this series apply to?
> 
> It doesn't apply for me on top of 7.0-rc4, so please consider rebasing.

It is based on mm-new 
I will soon rebase on the top of 7.0-rc4 with build & test.

Best regards,
Youngjun Park



^ permalink raw reply

* Re: [PATCH v4 0/3] mm/swap, PM: hibernate: fix swapoff race and optimize swap
From: Rafael J. Wysocki @ 2026-03-19 13:33 UTC (permalink / raw)
  To: Youngjun Park
  Cc: rafael, akpm, chrisl, kasong, pavel, shikemeng, nphamcs, bhe,
	baohua, usama.arif, linux-pm, linux-mm
In-Reply-To: <20260317181318.2517015-1-youngjun.park@lge.com>

On Tue, Mar 17, 2026 at 7:13 PM 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.
>
> This patch series addresses these issues:
> - Patch 1: Fixes the swapoff race in uswsusp by holding the swap device
>   reference from the point the swap device is looked up.
> - Patch 2: Removes the overhead of per-slot reference counting in alloc/free
>   paths and cleans up the redundant SWP_WRITEOK check.
> - Patch 3: Fixes a spurious WARNING in the uswsusp GFP mask restore path.
>   (Founded during uswsusp test)
>
> Links:
> RFC v1: https://lore.kernel.org/linux-mm/20260305202413.1888499-1-usama.arif@linux.dev/T/#m3693d45180f14f441b6951984f4b4bfd90ec0c9d
> RFC v2: https://lore.kernel.org/linux-mm/20260306024608.1720991-1-youngjun.park@lge.com/
> RFC v3: https://lore.kernel.org/linux-mm/20260312112511.3596781-1-youngjun.park@lge.com/
>
> Testing:
> - Hibernate/resume via sysfs
>   (echo reboot > /sys/power/disk && echo disk > /sys/power/state)
> - Hibernate with suspend via sysfs
>   (echo suspend > /sys/power/disk && echo disk > /sys/power/state)
> - Hibernate/resume via uswsusp (suspend-utils s2disk/resume on QEMU)
>   - Verified swap I/O works correctly after resume.
>   - Verified swapoff succeeds after snapshot resume completes.
>   - Verified pm_restore_gfp_mask() WARNING no longer triggers (Patch 3).
> - swapoff during active uswsusp session:
>   - Verified swapoff blocks while uswsusp holds swap reference.
>   - Verified swapoff can be cancelled by signal (e.g. Ctrl+C).
>   - Verified swapoff succeeds after uswsusp process terminates.
>
> Changelog:
> rfc v3 -> v4:
>  - Introduced get/find/put_hibernation_swap_type() helpers per Kairui's
>    feedback. find_ for lookup-only, get/put for reference management.
>  - Switched to swap_type_to_info() and added type < 0 check per
>    Kairui's suggestion.
>  - Fixed get_hibernation_swap_type() return when ref == false (Reviewd by Kairui)
>  - Made swapoff wait interruptible to prevent hang when uswsusp
>    holds a swap reference.
>  - Fixed spurious WARN_ON in pm_restore_gfp_mask() by introducing
>    pm_restore_gfp_mask_safe() (Patch 3).
>  - Updated commit messages and added comments for clarity.
>  - Rebased onto latest mm-new tree.
>
>  Note: Kairui suggested adding WARN on NULL in put_hibernation_swap_type(),
>  but kept silent return instead, as type can legitimately be -1 when
>  snapshot_open() fails to find a matching swap device. swap_type_to_info()
>  returns NULL for type < 0, so the cleanup path stays simple.
>
> rfc v2 -> rfc v3:
>  - Split into 2 patches per Chris Li's feedback.
>  - Simplified by not holding reference in normal hibernation path
>    per Chris Li's suggestion.
>  - Removed redundant SWP_WRITEOK check.
>  - Rebased onto f543926f9d0c3f6dfb354adfe7fbaeedd1277c6b.
>
> rfc v1 -> rfc v2:
>  - Squashed into single patch per Usama Arif's feedback.
>
> Youngjun Park (3):
>   mm/swap, PM: hibernate: fix swapoff race in uswsusp by getting swap
>     reference
>   mm/swap: remove redundant swap device reference in alloc/free
>   PM: hibernate: fix spurious GFP mask WARNING in uswsusp path
>
>  include/linux/suspend.h |   1 +
>  include/linux/swap.h    |   4 +-
>  kernel/power/main.c     |   7 ++
>  kernel/power/swap.c     |   2 +-
>  kernel/power/user.c     |  19 +++--
>  mm/swapfile.c           | 154 +++++++++++++++++++++++++++-------------
>  6 files changed, 132 insertions(+), 55 deletions(-)
>
> --

Which kernel version does this series apply to?

It doesn't apply for me on top of 7.0-rc4, so please consider rebasing.

^ permalink raw reply

* Re: [PATCH v4 0/5] mm: zone lock tracepoint instrumentation
From: Dmitry Ilvokhin @ 2026-03-19 13:22 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Matthew Wilcox, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Masami Hiramatsu, Mathieu Desnoyers, Rafael J. Wysocki,
	Pavel Machek, Len Brown, Brendan Jackman, Johannes Weiner, Zi Yan,
	Oscar Salvador, Qi Zheng, Shakeel Butt, linux-kernel, linux-mm,
	linux-trace-kernel, linux-pm
In-Reply-To: <abhAoF5EpiPigsx7@shell.ilvokhin.com>

On Mon, Mar 16, 2026 at 05:40:50PM +0000, Dmitry Ilvokhin wrote:

[...]

> A possible generic solution is a trace_contended_release() for spin
> locks, for example:
> 
>     if (trace_contended_release_enabled() &&
>         atomic_read(&lock->val) & ~_Q_LOCKED_MASK)
>         trace_contended_release(lock);
> 
> This might work on x86, but could increase code size and regress
> performance on arches where spin_unlock() is inlined, such as arm64
> under !PREEMPTION.

I took a stab at this idea and submitted an RFC [1].

The implementation builds on your earlier observation from Matthew that
_raw_spin_unlock() is not inlined in most configurations. In those
cases, when the tracepoint is disabled, this adds a single NOP on the
fast path, with the conditional check staying out of line. The measured
text size increase in this configuration is +983 bytes.

For configurations where _raw_spin_unlock() is inlined, the
instrumentation does increase code size more noticeably
(+71 KB in my measurements), since the check and out of line call is
replicated at each call site.

This provides a generic release-side signal for contended locks,
allowing: correlation of lock holders with waiters and measurement of
contended hold times

This RFC addressing the same visibility gap without introducing per-lock
instrumentation.

If this tradeoff is acceptable, this could be a generic alternative to
lock-specific tracepoints.

[1]: https://lore.kernel.org/all/51aad0415b78c5a39f2029722118fa01eac77538.1773858853.git.d@ilvokhin.com 

^ permalink raw reply

* Re: [PATCH v1] writeback: skip sync(2) inode writeback for filesystems with no data integrity guarantees
From: Jan Kara @ 2026-03-19 12:42 UTC (permalink / raw)
  To: Joanne Koong
  Cc: brauner, linux-fsdevel, jack, miklos, david, therealgraysky,
	linux-pm, stable
In-Reply-To: <20260318225604.71545-1-joannelkoong@gmail.com>

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

> ---
>  fs/fs-writeback.c              |  7 +------
>  fs/fuse/file.c                 |  4 +---
>  fs/fuse/inode.c                |  1 +
>  fs/sync.c                      |  2 +-
>  include/linux/fs/super_types.h |  1 +
>  include/linux/pagemap.h        | 11 -----------
>  6 files changed, 5 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..88c08e2f76b2 100644
> --- a/fs/sync.c
> +++ b/fs/sync.c
> @@ -73,7 +73,7 @@ EXPORT_SYMBOL(sync_filesystem);
>  
>  static void sync_inodes_one_sb(struct super_block *sb, void *arg)
>  {
> -	if (!sb_rdonly(sb))
> +	if (!sb_rdonly(sb) && !(sb->s_iflags & SB_I_NO_DATA_INTEGRITY))
>  		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
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply

* Re: [PATCH v8 05/10] pmdomain: samsung: convert to using regmap
From: André Draszik @ 2026-03-19 11:58 UTC (permalink / raw)
  To: Marek Szyprowski, Ulf Hansson
  Cc: 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: <c5ba58fb-50f1-4067-a099-97169ea81f68@samsung.com>

Hi Marek,

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.

Cheers,
Andre'

^ 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