Linux Power Management development
 help / color / mirror / Atom feed
* Re: [PATCH v11 02/16] set_memory: add folio_{zap,restore}_direct_map helpers
From: David Hildenbrand (Arm) @ 2026-03-23 17:51 UTC (permalink / raw)
  To: Kalyazin, Nikita, kvm@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
	linux-fsdevel@vger.kernel.org, linux-mm@kvack.org,
	bpf@vger.kernel.org, linux-kselftest@vger.kernel.org,
	kernel@xen0n.name, linux-riscv@lists.infradead.org,
	linux-s390@vger.kernel.org, loongarch@lists.linux.dev,
	linux-pm@vger.kernel.org
  Cc: pbonzini@redhat.com, corbet@lwn.net, maz@kernel.org,
	oupton@kernel.org, joey.gouly@arm.com, suzuki.poulose@arm.com,
	yuzenghui@huawei.com, catalin.marinas@arm.com, will@kernel.org,
	seanjc@google.com, tglx@kernel.org, mingo@redhat.com,
	bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org,
	hpa@zytor.com, luto@kernel.org, peterz@infradead.org,
	willy@infradead.org, akpm@linux-foundation.org,
	lorenzo.stoakes@oracle.com, vbabka@kernel.org, rppt@kernel.org,
	surenb@google.com, mhocko@suse.com, ast@kernel.org,
	daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev,
	eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
	haoluo@google.com, jolsa@kernel.org, jgg@ziepe.ca,
	jhubbard@nvidia.com, peterx@redhat.com, jannh@google.com,
	pfalcato@suse.de, skhan@linuxfoundation.org, riel@surriel.com,
	ryan.roberts@arm.com, jgross@suse.com, yu-cheng.yu@intel.com,
	kas@kernel.org, coxu@redhat.com, kevin.brodsky@arm.com,
	ackerleytng@google.com, yosry@kernel.org, ajones@ventanamicro.com,
	maobibo@loongson.cn, tabba@google.com, prsampat@amd.com,
	wu.fei9@sanechips.com.cn, mlevitsk@redhat.com,
	jmattson@google.com, jthoughton@google.com,
	agordeev@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu,
	borntraeger@linux.ibm.com, chenhuacai@kernel.org,
	dev.jain@arm.com, gor@linux.ibm.com, hca@linux.ibm.com,
	palmer@dabbelt.com, pjw@kernel.org, shijie@os.amperecomputing.com,
	svens@linux.ibm.com, thuth@redhat.com, wyihan@google.com,
	yang@os.amperecomputing.com, Jonathan.Cameron@huawei.com,
	Liam.Howlett@oracle.com, urezki@gmail.com,
	zhengqi.arch@bytedance.com, gerald.schaefer@linux.ibm.com,
	jiayuan.chen@shopee.com, lenb@kernel.org, osalvador@suse.de,
	pavel@kernel.org, rafael@kernel.org, vannapurve@google.com,
	jackmanb@google.com, aneesh.kumar@kernel.org,
	patrick.roy@linux.dev, Thomson, Jack, Itazuri, Takahiro,
	Manwaring, Derek
In-Reply-To: <20260317141031.514-3-kalyazin@amazon.com>

On 3/17/26 15:10, Kalyazin, Nikita wrote:
> From: Nikita Kalyazin <kalyazin@amazon.com>
> 
> Let's provide folio_{zap,restore}_direct_map helpers as preparation for
> supporting removal of the direct map for guest_memfd folios.
> In folio_zap_direct_map(), flush TLB to make sure the data is not
> accessible.
> 
> The new helpers need to be accessible to KVM on architectures that
> support guest_memfd (x86 and arm64).
> 
> Direct map removal gives guest_memfd the same protection that
> memfd_secret does, such as hardening against Spectre-like attacks
> through in-kernel gadgets.

Maybe mention that there might be a double TLB flush on some
architectures, but that that is something to figure out later. Same
behavior in secretmem code where this will be used next.

> 
> Signed-off-by: Nikita Kalyazin <kalyazin@amazon.com>
> ---
>  include/linux/set_memory.h | 13 ++++++++++++
>  mm/memory.c                | 42 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 55 insertions(+)
> 
> diff --git a/include/linux/set_memory.h b/include/linux/set_memory.h
> index 1a2563f525fc..24caea2931f9 100644
> --- a/include/linux/set_memory.h
> +++ b/include/linux/set_memory.h
> @@ -41,6 +41,15 @@ static inline int set_direct_map_valid_noflush(const void *addr,
>  	return 0;
>  }
>  
> +static inline int folio_zap_direct_map(struct folio *folio)
> +{
> +	return 0;

Should we return -ENOSYS here or similar?

> +}
> +
> +static inline void folio_restore_direct_map(struct folio *folio)
> +{
> +}
> +
>  static inline bool kernel_page_present(struct page *page)
>  {
>  	return true;
> @@ -57,6 +66,10 @@ static inline bool can_set_direct_map(void)
>  }
>  #define can_set_direct_map can_set_direct_map
>  #endif
> +
> +int folio_zap_direct_map(struct folio *folio);
> +void folio_restore_direct_map(struct folio *folio);
> +
>  #endif /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */
>  
>  #ifdef CONFIG_X86_64
> diff --git a/mm/memory.c b/mm/memory.c
> index 07778814b4a8..cab6bb237fc0 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -78,6 +78,7 @@
>  #include <linux/sched/sysctl.h>
>  #include <linux/pgalloc.h>
>  #include <linux/uaccess.h>
> +#include <linux/set_memory.h>
>  
>  #include <trace/events/kmem.h>
>  
> @@ -7478,3 +7479,44 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma)
>  	if (is_vm_hugetlb_page(vma))
>  		hugetlb_vma_unlock_read(vma);
>  }
> +
> +#ifdef CONFIG_ARCH_HAS_SET_DIRECT_MAP
> +/**
> + * folio_zap_direct_map - remove a folio from the kernel direct map
> + * @folio: folio to remove from the direct map
> + *
> + * Removes the folio from the kernel direct map and flushes the TLB.  This may
> + * require splitting huge pages in the direct map, which can fail due to memory
> + * allocation.

Best to mention

"So far, only order-0 folios are supported." and then ...

> + *
> + * Return: 0 on success, or a negative error code on failure.
> + */
> +int folio_zap_direct_map(struct folio *folio)
> +{
> +	const void *addr = folio_address(folio);
> +	int ret;
> +

if (folio_test_large(folio))
	return -EINVAL;


With that,

Acked-by: David Hildenbrand (Arm) <david@kernel.org>

-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH v11 01/16] set_memory: set_direct_map_* to take address
From: David Hildenbrand (Arm) @ 2026-03-23 17:44 UTC (permalink / raw)
  To: Kalyazin, Nikita, kvm@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
	linux-fsdevel@vger.kernel.org, linux-mm@kvack.org,
	bpf@vger.kernel.org, linux-kselftest@vger.kernel.org,
	kernel@xen0n.name, linux-riscv@lists.infradead.org,
	linux-s390@vger.kernel.org, loongarch@lists.linux.dev,
	linux-pm@vger.kernel.org
  Cc: pbonzini@redhat.com, corbet@lwn.net, maz@kernel.org,
	oupton@kernel.org, joey.gouly@arm.com, suzuki.poulose@arm.com,
	yuzenghui@huawei.com, catalin.marinas@arm.com, will@kernel.org,
	seanjc@google.com, tglx@kernel.org, mingo@redhat.com,
	bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org,
	hpa@zytor.com, luto@kernel.org, peterz@infradead.org,
	willy@infradead.org, akpm@linux-foundation.org,
	lorenzo.stoakes@oracle.com, vbabka@kernel.org, rppt@kernel.org,
	surenb@google.com, mhocko@suse.com, ast@kernel.org,
	daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev,
	eddyz87@gmail.com, song@kernel.org, yonghong.song@linux.dev,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
	haoluo@google.com, jolsa@kernel.org, jgg@ziepe.ca,
	jhubbard@nvidia.com, peterx@redhat.com, jannh@google.com,
	pfalcato@suse.de, skhan@linuxfoundation.org, riel@surriel.com,
	ryan.roberts@arm.com, jgross@suse.com, yu-cheng.yu@intel.com,
	kas@kernel.org, coxu@redhat.com, kevin.brodsky@arm.com,
	ackerleytng@google.com, yosry@kernel.org, ajones@ventanamicro.com,
	maobibo@loongson.cn, tabba@google.com, prsampat@amd.com,
	wu.fei9@sanechips.com.cn, mlevitsk@redhat.com,
	jmattson@google.com, jthoughton@google.com,
	agordeev@linux.ibm.com, alex@ghiti.fr, aou@eecs.berkeley.edu,
	borntraeger@linux.ibm.com, chenhuacai@kernel.org,
	dev.jain@arm.com, gor@linux.ibm.com, hca@linux.ibm.com,
	palmer@dabbelt.com, pjw@kernel.org, shijie@os.amperecomputing.com,
	svens@linux.ibm.com, thuth@redhat.com, wyihan@google.com,
	yang@os.amperecomputing.com, Jonathan.Cameron@huawei.com,
	Liam.Howlett@oracle.com, urezki@gmail.com,
	zhengqi.arch@bytedance.com, gerald.schaefer@linux.ibm.com,
	jiayuan.chen@shopee.com, lenb@kernel.org, osalvador@suse.de,
	pavel@kernel.org, rafael@kernel.org, vannapurve@google.com,
	jackmanb@google.com, aneesh.kumar@kernel.org,
	patrick.roy@linux.dev, Thomson, Jack, Itazuri, Takahiro,
	Manwaring, Derek
In-Reply-To: <20260317141031.514-2-kalyazin@amazon.com>

On 3/17/26 15:10, Kalyazin, Nikita wrote:
> From: Nikita Kalyazin <kalyazin@amazon.com>
> 

Just a nit while reading over it once more: restate what the patch
subject says.

Like "Let's convert set_direct_map_*() to take an address instead of a
page to prepare for adding helpers that operate on folios; it will be
more efficient to convert from a folio directly to an address without
going through a page first."

> This is to avoid excessive conversions folio->page->address when adding
> helpers on top of set_direct_map_valid_noflush() in the next patch.
> 
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
> Signed-off-by: Nikita Kalyazin <kalyazin@amazon.com>
> ---

-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH v8 6/9] dax: Track all dax_region allocations under a global resource tree
From: Dave Jiang @ 2026-03-23 17:31 UTC (permalink / raw)
  To: Smita Koralahalli, linux-cxl, linux-kernel, nvdimm, linux-fsdevel,
	linux-pm
  Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
	Dan Williams, Jonathan Cameron, Yazen Ghannam, 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: <20260322195343.206900-7-Smita.KoralahalliChannabasappa@amd.com>



On 3/22/26 12:53 PM, Smita Koralahalli 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>
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.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 299134c9b294..68437c05e21d 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);
>  
>  /*
> @@ -627,6 +628,7 @@ static void dax_region_unregister(void *region)
>  
>  	sysfs_remove_groups(&dax_region->dev->kobj,
>  			dax_region_attribute_groups);
> +	release_resource(&dax_region->res);
>  	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)) {
> -		dax_region_put(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))
>  		return NULL;
>  	return dax_region;
> +
> +err_sysfs:
> +	release_resource(&dax_region->res);
> +err_res:
> +	dax_region_put(dax_region);
> +	return NULL;
>  }
>  EXPORT_SYMBOL_GPL(alloc_dax_region);
>  


^ permalink raw reply

* Re: [PATCH v6 6/9] dt-bindings: connector: m2: Add M.2 1620 LGA soldered down connector
From: Mark Pearson @ 2026-03-23 17:23 UTC (permalink / raw)
  To: Manivannan Sadhasivam, Dmitry Baryshkov
  Cc: Rob Herring, Manivannan Sadhasivam, Greg KH, Jiri Slaby,
	Nathan Chancellor, Nicolas Schier, Hans de Goede,
	Ilpo Järvinen, Derek J . Clark, Krzysztof Kozlowski,
	Conor Dooley, Marcel Holtmann, Luiz Augusto von Dentz,
	Bartosz Golaszewski, Andy Shevchenko, Bartosz Golaszewski,
	linux-serial, linux-kernel, linux-kbuild,
	platform-driver-x86@vger.kernel.org, linux-pci, devicetree,
	linux-arm-msm, linux-bluetooth, linux-pm, Stephan Gerhold,
	linux-acpi@vger.kernel.org
In-Reply-To: <m44mupdmg7kgco62n4evcviagqo7wwgyt3gybugbxwesd4ekjz@o24r6v4tpezc>



On Mon, Mar 23, 2026, at 12:52 PM, Manivannan Sadhasivam wrote:
> On Mon, Mar 23, 2026 at 06:45:15PM +0200, Dmitry Baryshkov wrote:
>> On Mon, Mar 23, 2026 at 09:26:04PM +0530, Manivannan Sadhasivam wrote:
>> > On Mon, Mar 23, 2026 at 05:14:30PM +0200, Dmitry Baryshkov wrote:
>> > > On Mon, Mar 23, 2026 at 07:14:25PM +0530, Manivannan Sadhasivam wrote:
>> > > > On Mon, Mar 23, 2026 at 08:39:55AM -0500, Rob Herring wrote:
>> > > > > On Mon, Mar 23, 2026 at 7:16 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
>> > > > > >
>> > > > > > On Sun, Mar 22, 2026 at 06:37:13PM -0500, Rob Herring wrote:
>> > > > > > > On Tue, Mar 17, 2026 at 09:59:56AM +0530, Manivannan Sadhasivam wrote:
>> > > > > > > > Lenovo Thinkpad T14s is found to have a soldered down version of M.2 1620
>> > > > > > > > LGA connector. Though, there is no 1620 LGA form factor defined in the M.2
>> > > > > > > > spec, it looks very similar to the M.2 Key E connector. So add the
>> > > > > > > > "pcie-m2-1620-lga-connector" compatible with "pcie-m2-e-connector" fallback
>> > > > > > > > to reuse the Key E binding.
>> > > > > > >
>> > > > > > > What is LGA?
>> > > > > > >
>> > > > > >
>> > > > > > Land Grid Array
>> > > > > >
>> > > > > > > If not in the spec, is it really something generic?
>> > > > > > >
>> > > > > >
>> > > > > > Good question. Yes and No! LGA is not something that Lenovo only uses. Other
>> > > > > > vendors may also use this form factor. PCIe connectors are full of innovation as
>> > > > > > the spec gives room for hardware designers to be as innovative as possible to
>> > > > > > save the BOM cost.
>> > > > > 
>> > > > > innovation == incompatible changes
>> > > > > 
>> > > > 
>> > > > Yes, I was trying to sound nice :)
>> > > > 
>> > > > > > This is why I do not want to make it Lenovo specific. But if you prefer that, I
>> > > > > > can name it as "lenovo,pcie-m2-1620-lga-connector".
>> > > > > 
>> > > > > Depends if you think that s/w needs to know the differences. Hard to
>> > > > > say with a sample size of 1.
>> > > > > 
>> > > > 
>> > > > Sure. Will add the 'lenovo' prefix then.
>> > > 
>> > > Is it really Lenovo? Or is it some other module vendor, whose LGAs are
>> > > being used by Lenovo?
>> > > 
>> > > I remember that DB820c also used some kind of a module for the WiFi card
>> > > (which might be M.2 compatible or might not, I can't find exact docs at
>> > > this point).
>> > > 
>> > 
>> > I don't know. These kind of designs might be reused by several vendors. But
>> > considering that we should not make it generic, I'd go with Lenovo as that's
>> > the only vendor we know as of now.
>> 
>> ... and later we learn that other vendors use the same idea /pinout,
>> then nothing stops us from still telling that it's a
>> "lenovo,pcie-m2-something-lga". 
>> 
>
> How do you possibly know whether a single vendor has introduced this form factor
> or reused by multiple ones? Atleast, I don't have access to such a source to
> confirm.
>
I've not really been following this thread/patchset in detail; but want me to try and check with the T14s platform team if this device is specifically made for us (Lenovo) or not?
I doubt it is - we just don't do that usually, but I can go and ask the question if it will help resolve this (with the caveat that it could hold up the review for a bit and I may not be able to get a straight answer)

My vote (for what little it's worth) would be to make it non-Lenovo specific. Then when the same part causes issues on another vendors platform I won't get asked questions about why Lenovo is breaking <other vendor> :)

Mark

^ permalink raw reply

* Re: [PATCH v8 2/9] dax/hmem: Factor HMEM registration into __hmem_register_device()
From: Dave Jiang @ 2026-03-23 17:14 UTC (permalink / raw)
  To: Smita Koralahalli, linux-cxl, linux-kernel, nvdimm, linux-fsdevel,
	linux-pm
  Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
	Dan Williams, Jonathan Cameron, Yazen Ghannam, 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: <20260322195343.206900-3-Smita.KoralahalliChannabasappa@amd.com>



On 3/22/26 12:53 PM, Smita Koralahalli wrote:
> Separate the CXL overlap check from the HMEM registration path and keep
> the platform-device setup in a dedicated __hmem_register_device().
> 
> This makes hmem_register_device() the policy entry point for deciding
> whether a range should be deferred to CXL, while __hmem_register_device()
> handles the HMEM registration flow.
> 
> No functional changes.
> 
> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>

> ---
>  drivers/dax/hmem/hmem.c | 24 +++++++++++++++---------
>  1 file changed, 15 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/dax/hmem/hmem.c b/drivers/dax/hmem/hmem.c
> index 1cf7c2a0ee1c..a3d45032355c 100644
> --- a/drivers/dax/hmem/hmem.c
> +++ b/drivers/dax/hmem/hmem.c
> @@ -58,21 +58,14 @@ static void release_hmem(void *pdev)
>  	platform_device_unregister(pdev);
>  }
>  
> -static int hmem_register_device(struct device *host, int target_nid,
> -				const struct resource *res)
> +static int __hmem_register_device(struct device *host, int target_nid,
> +				  const struct resource *res)
>  {
>  	struct platform_device *pdev;
>  	struct memregion_info info;
>  	long id;
>  	int rc;
>  
> -	if (IS_ENABLED(CONFIG_CXL_REGION) &&
> -	    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;
> -	}
> -
>  	rc = region_intersects_soft_reserve(res->start, resource_size(res));
>  	if (rc != REGION_INTERSECTS)
>  		return 0;
> @@ -123,6 +116,19 @@ static int hmem_register_device(struct device *host, int target_nid,
>  	return rc;
>  }
>  
> +static int hmem_register_device(struct device *host, int target_nid,
> +				const struct resource *res)
> +{
> +	if (IS_ENABLED(CONFIG_CXL_REGION) &&
> +	    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;
> +	}
> +
> +	return __hmem_register_device(host, target_nid, res);
> +}
> +
>  static int dax_hmem_platform_probe(struct platform_device *pdev)
>  {
>  	return walk_hmem_resources(&pdev->dev, hmem_register_device);


^ permalink raw reply

* Re: [PATCH v8 1/9] dax/bus: Use dax_region_put() in alloc_dax_region() error path
From: Dave Jiang @ 2026-03-23 17:11 UTC (permalink / raw)
  To: Smita Koralahalli, linux-cxl, linux-kernel, nvdimm, linux-fsdevel,
	linux-pm
  Cc: Ard Biesheuvel, Alison Schofield, Vishal Verma, Ira Weiny,
	Dan Williams, Jonathan Cameron, Yazen Ghannam, 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: <20260322195343.206900-2-Smita.KoralahalliChannabasappa@amd.com>



On 3/22/26 12:53 PM, Smita Koralahalli wrote:
> alloc_dax_region() calls kref_init() on the dax_region early in the
> function, but the error path for sysfs_create_groups() failure uses
> kfree() directly to free the dax_region. This bypasses the kref lifecycle.
> 
> Use dax_region_put() instead to handle kref lifecycle correctly.
> 
> Suggested-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>

Reviewed-by: Dave Jiang <dave.jiang@intel.com>

> ---
>  drivers/dax/bus.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index c94c09622516..299134c9b294 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -668,7 +668,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
>  	};
>  
>  	if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
> -		kfree(dax_region);
> +		dax_region_put(dax_region);
>  		return NULL;
>  	}
>  


^ permalink raw reply

* Re: [PATCH v6 6/9] dt-bindings: connector: m2: Add M.2 1620 LGA soldered down connector
From: Manivannan Sadhasivam @ 2026-03-23 16:52 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Herring, Manivannan Sadhasivam, Greg Kroah-Hartman,
	Jiri Slaby, Nathan Chancellor, Nicolas Schier, Hans de Goede,
	Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Andy Shevchenko,
	Bartosz Golaszewski, linux-serial, linux-kernel, linux-kbuild,
	platform-driver-x86, linux-pci, devicetree, linux-arm-msm,
	linux-bluetooth, linux-pm, Stephan Gerhold, linux-acpi
In-Reply-To: <blhm4csjyw6r667cleljgzd6rpwagttjo5rau7wjrlnjakq2qm@ekyhc4jvwmwf>

On Mon, Mar 23, 2026 at 06:45:15PM +0200, Dmitry Baryshkov wrote:
> On Mon, Mar 23, 2026 at 09:26:04PM +0530, Manivannan Sadhasivam wrote:
> > On Mon, Mar 23, 2026 at 05:14:30PM +0200, Dmitry Baryshkov wrote:
> > > On Mon, Mar 23, 2026 at 07:14:25PM +0530, Manivannan Sadhasivam wrote:
> > > > On Mon, Mar 23, 2026 at 08:39:55AM -0500, Rob Herring wrote:
> > > > > On Mon, Mar 23, 2026 at 7:16 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > > > >
> > > > > > On Sun, Mar 22, 2026 at 06:37:13PM -0500, Rob Herring wrote:
> > > > > > > On Tue, Mar 17, 2026 at 09:59:56AM +0530, Manivannan Sadhasivam wrote:
> > > > > > > > Lenovo Thinkpad T14s is found to have a soldered down version of M.2 1620
> > > > > > > > LGA connector. Though, there is no 1620 LGA form factor defined in the M.2
> > > > > > > > spec, it looks very similar to the M.2 Key E connector. So add the
> > > > > > > > "pcie-m2-1620-lga-connector" compatible with "pcie-m2-e-connector" fallback
> > > > > > > > to reuse the Key E binding.
> > > > > > >
> > > > > > > What is LGA?
> > > > > > >
> > > > > >
> > > > > > Land Grid Array
> > > > > >
> > > > > > > If not in the spec, is it really something generic?
> > > > > > >
> > > > > >
> > > > > > Good question. Yes and No! LGA is not something that Lenovo only uses. Other
> > > > > > vendors may also use this form factor. PCIe connectors are full of innovation as
> > > > > > the spec gives room for hardware designers to be as innovative as possible to
> > > > > > save the BOM cost.
> > > > > 
> > > > > innovation == incompatible changes
> > > > > 
> > > > 
> > > > Yes, I was trying to sound nice :)
> > > > 
> > > > > > This is why I do not want to make it Lenovo specific. But if you prefer that, I
> > > > > > can name it as "lenovo,pcie-m2-1620-lga-connector".
> > > > > 
> > > > > Depends if you think that s/w needs to know the differences. Hard to
> > > > > say with a sample size of 1.
> > > > > 
> > > > 
> > > > Sure. Will add the 'lenovo' prefix then.
> > > 
> > > Is it really Lenovo? Or is it some other module vendor, whose LGAs are
> > > being used by Lenovo?
> > > 
> > > I remember that DB820c also used some kind of a module for the WiFi card
> > > (which might be M.2 compatible or might not, I can't find exact docs at
> > > this point).
> > > 
> > 
> > I don't know. These kind of designs might be reused by several vendors. But
> > considering that we should not make it generic, I'd go with Lenovo as that's
> > the only vendor we know as of now.
> 
> ... and later we learn that other vendors use the same idea /pinout,
> then nothing stops us from still telling that it's a
> "lenovo,pcie-m2-something-lga". 
> 

How do you possibly know whether a single vendor has introduced this form factor
or reused by multiple ones? Atleast, I don't have access to such a source to
confirm.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH v6 6/9] dt-bindings: connector: m2: Add M.2 1620 LGA soldered down connector
From: Dmitry Baryshkov @ 2026-03-23 16:45 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Rob Herring, Manivannan Sadhasivam, Greg Kroah-Hartman,
	Jiri Slaby, Nathan Chancellor, Nicolas Schier, Hans de Goede,
	Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Andy Shevchenko,
	Bartosz Golaszewski, linux-serial, linux-kernel, linux-kbuild,
	platform-driver-x86, linux-pci, devicetree, linux-arm-msm,
	linux-bluetooth, linux-pm, Stephan Gerhold, linux-acpi
In-Reply-To: <bguhzabwryayyqkv4ilzwr3ixwv6bzxncblo3ircz2wm3fs52k@66zvcrfcb4oe>

On Mon, Mar 23, 2026 at 09:26:04PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Mar 23, 2026 at 05:14:30PM +0200, Dmitry Baryshkov wrote:
> > On Mon, Mar 23, 2026 at 07:14:25PM +0530, Manivannan Sadhasivam wrote:
> > > On Mon, Mar 23, 2026 at 08:39:55AM -0500, Rob Herring wrote:
> > > > On Mon, Mar 23, 2026 at 7:16 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > > >
> > > > > On Sun, Mar 22, 2026 at 06:37:13PM -0500, Rob Herring wrote:
> > > > > > On Tue, Mar 17, 2026 at 09:59:56AM +0530, Manivannan Sadhasivam wrote:
> > > > > > > Lenovo Thinkpad T14s is found to have a soldered down version of M.2 1620
> > > > > > > LGA connector. Though, there is no 1620 LGA form factor defined in the M.2
> > > > > > > spec, it looks very similar to the M.2 Key E connector. So add the
> > > > > > > "pcie-m2-1620-lga-connector" compatible with "pcie-m2-e-connector" fallback
> > > > > > > to reuse the Key E binding.
> > > > > >
> > > > > > What is LGA?
> > > > > >
> > > > >
> > > > > Land Grid Array
> > > > >
> > > > > > If not in the spec, is it really something generic?
> > > > > >
> > > > >
> > > > > Good question. Yes and No! LGA is not something that Lenovo only uses. Other
> > > > > vendors may also use this form factor. PCIe connectors are full of innovation as
> > > > > the spec gives room for hardware designers to be as innovative as possible to
> > > > > save the BOM cost.
> > > > 
> > > > innovation == incompatible changes
> > > > 
> > > 
> > > Yes, I was trying to sound nice :)
> > > 
> > > > > This is why I do not want to make it Lenovo specific. But if you prefer that, I
> > > > > can name it as "lenovo,pcie-m2-1620-lga-connector".
> > > > 
> > > > Depends if you think that s/w needs to know the differences. Hard to
> > > > say with a sample size of 1.
> > > > 
> > > 
> > > Sure. Will add the 'lenovo' prefix then.
> > 
> > Is it really Lenovo? Or is it some other module vendor, whose LGAs are
> > being used by Lenovo?
> > 
> > I remember that DB820c also used some kind of a module for the WiFi card
> > (which might be M.2 compatible or might not, I can't find exact docs at
> > this point).
> > 
> 
> I don't know. These kind of designs might be reused by several vendors. But
> considering that we should not make it generic, I'd go with Lenovo as that's
> the only vendor we know as of now.

... and later we learn that other vendors use the same idea /pinout,
then nothing stops us from still telling that it's a
"lenovo,pcie-m2-something-lga". 

-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH v5 00/21] Virtual Swap Space
From: Kairui Song @ 2026-03-23 16:40 UTC (permalink / raw)
  To: Nhat Pham
  Cc: Liam.Howlett, akpm, apopple, axelrasmussen, baohua, baolin.wang,
	bhe, byungchul, cgroups, chengming.zhou, chrisl, corbet, david,
	dev.jain, gourry, hannes, hughd, jannh, joshua.hahnjy, lance.yang,
	lenb, linux-doc, linux-kernel, linux-mm, linux-pm,
	lorenzo.stoakes, matthew.brost, mhocko, muchun.song, npache,
	pavel, peterx, peterz, pfalcato, rafael, rakie.kim,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
	zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAKEwX=PBjMVfMvKkNfqbgiw7o10NFyZBSB62ODzsqogv-WDYKQ@mail.gmail.com>

On Mon, Mar 23, 2026 at 11:33 PM Nhat Pham <nphamcs@gmail.com> wrote:
>
> On Mon, Mar 23, 2026 at 6:09 AM Kairui Song <ryncsn@gmail.com> wrote:
> >
> > On Sat, Mar 21, 2026 at 3:29 AM Nhat Pham <nphamcs@gmail.com> wrote:
> > > This patch series is based on 6.19. There are a couple more
> > > swap-related changes in mainline that I would need to coordinate
> > > with, but I still want to send this out as an update for the
> > > regressions reported by Kairui Song in [15]. It's probably easier
> > > to just build this thing rather than dig through that series of
> > > emails to get the fix patch :)
> > >
> > > Changelog:
> > > * v4 -> v5:
> > >     * Fix a deadlock in memcg1_swapout (reported by syzbot [16]).
> > >     * Replace VM_WARN_ON(!spin_is_locked()) with lockdep_assert_held(),
> > >       and use guard(rcu) in vswap_cpu_dead
> > >       (reported by Peter Zijlstra [17]).
> > > * v3 -> v4:
> > >     * Fix poor swap free batching behavior to alleviate a regression
> > >       (reported by Kairui Song).
> >
>
> Hi Kairui! Thanks a lot for the testing big boss :) I will focus on
> the regression in this patch series - we can talk more about
> directions in another thread :)

Hi Nhat,

> Interesting. Normally "lots of zero-filled page" is a very beneficial
> case for vswap. You don't need a swapfile, or any zram/zswap metadata
> overhead - it's a native swap backend. If production workload has this
> many zero-filled pages, I think the numbers of vswap would be much
> less alarming - perhaps even matching memory overhead because you
> don't need to maintain a zram entry metadata (it's at least 2 words
> per zram entry right?), while there's no reverse map overhead induced
> (so it's 24 bytes on both side), and no need to do zram-side locking
> :)
>
> So I was surprised to see that it's not working out very well here. I
> checked the implementation of memhog - let me know if this is wrong
> place to look:
>
> https://man7.org/linux/man-pages/man8/memhog.8.html
> https://github.com/numactl/numactl/blob/master/memhog.c#L52
>
> I think this is what happened here: memhog was populating the memory
> 0xff, which triggers the full overhead of a swapfile-backed swap entry
> because even though it's "same-filled" it's not zero-filled! I was
> following Usama's observation - "less than 1% of the same-filled pages
> were non-zero" - and so I only handled the zero-filled case here:
>
> https://lore.kernel.org/all/20240530102126.357438-1-usamaarif642@gmail.com/
>
> This sounds a bit artificial IMHO - as Usama pointed out above, I
> think most samefilled pages are zero pages, in real production
> workloads. However, if you think there are real use cases with a lot

I vaguely remember some workloads like Java or some JS engine
initialize their heap with fixed value, same fill might not be that
common but not a rare thing, it strongly depends on the workload.

> of non-zero samefilled pages, please let me know I can fix this real
> quick. We can support this in vswap with zero extra metadata overhead
> - change the VSWAP_ZERO swap entry type to VSWAP_SAME_FILLED, then use
> the backend field to store that value. I can send you a patch if
> you're interested.

Actually I don't think that's the main problem. For example, I just
wrote a few lines C bench program to zerofill ~50G of memory
and swapout sequentially:

Before:
Swapout: 4415467us
Swapin: 49573297us

After:
Swapout: 4955874us
Swapin: 56223658us

And vmstat:
cat /proc/vmstat | grep zero
thp_zero_page_alloc 0
thp_zero_page_alloc_failed 0
swpin_zero 12239329
swpout_zero 21516634

There are all zero filled pages, but still slower. And what's more, a
more critical issue, I just found the cgroup and global swap usage
accounting are both somehow broken for zero page swap,
maybe because you skipped some allocation? Users can
no longer see how many pages are swapped out. I don't think you can
break that, that's one major reason why we use a zero entry instead of
mapping to a zero readonly page. If that is acceptable, we can have
a very nice optimization right away with current swap.

That's still just an example. bypassing the accounting and still
slower is not a good sign. We should focus on the generic
performance and design.

Yet this is just another new found issue, there are many other parts
like the folio swap allocation may still occur even if a lower device
can no longer accept more whole folios, which I'm currently
unsure how it will affect swap.

> 1. Regarding pmem backend - I'm not sure if I can get my hands on one
> of these, but if you think SSD has the same characteristics maybe I
> can give that a try? The problem with SSD is for some reason variance
> tends to be pretty high, between iterations yes, but especially across
> reboots. Or maybe zram?

Yeah, ZRAM has a very similar number for some cases, but storage is
getting faster and faster and swap occurs through high speed networks
too. We definitely shouldn't ignore that.

> 2. What about the other numbers below? Are they also on pmem? FTR I
> was running most of my benchmarks on zswap, except for one kernel
> build benchmark on SSD.
>
> 3. Any other backends and setup you're interested in?
>
> BTW, sounds like you have a great benchmark suite - is it open source
> somewhere? If not, can you share it with us :) Vswap aside, I think
> this would be a good suite to run all swap related changes for every
> swap contributor.

I can try to post that somewhere, really nothing fancy just some
wrapper to make use of systemd for reboot and auto test. But all test
steps I mentioned before are already posted and publically available.

^ permalink raw reply

* Re: [PATCH v1 0/2] *** Support BPF traversal of wakeup sources ***
From: Samuel Wu @ 2026-03-23 16:20 UTC (permalink / raw)
  To: Kumar Kartikeya Dwivedi
  Cc: Rafael J. Wysocki, Pavel Machek, Len Brown, Greg Kroah-Hartman,
	Danilo Krummrich, andrii, bpf, kernel-team, linux-pm, driver-core,
	linux-kernel
In-Reply-To: <CAP01T77hy3j5BZMBcYdadLfPe7dYb3zEGDF9daUxJHYy=+fcgA@mail.gmail.com>

On Sat, Mar 21, 2026 at 10:52 AM Kumar Kartikeya Dwivedi
<memxor@gmail.com> wrote:
>

[ ... ]

> >
> > The initial attempts for BPF traversal of wakeup_sources was with BPF
> > iterators [1]. However, BPF already allows for traversing of a simple list
> > with bpf_for(), and this current patchset has the added benefit of being
> > ~2-3x more performant than BPF iterators.
>
> See, it ended up being faster ;-).

Yup, thanks for the suggestion!

>
> That said, I didn't understand why you dropped the test. We still need
> unit tests that ensure the verifier causes the bpf_ws_lock to be
> released before exit, and an example program (like the one you
> benchmarked with) to demonstrate usage. Both are mandatory. See
> various *_fail.c files in progs/ and RUN_TESTS() macro for running
> negative tests easily. I doubt we will have any wakeup_sources in the
> CI environment, but the example has value nonetheless.
>
> pw-bot: cr
>

Sounds good, in v2 I can add a test for the lock/unlock kfunc. And
thanks for the thorough feedback, let me take a look at the *_fail.c
files and test macros.

^ permalink raw reply

* [PATCH v8 2/2] mm/swap: remove redundant swap device reference in alloc/free
From: Youngjun Park @ 2026-03-23 16:08 UTC (permalink / raw)
  To: Rafael J . Wysocki, Andrew Morton
  Cc: Chris Li, Kairui Song, Pavel Machek, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, Usama Arif, linux-pm,
	linux-mm
In-Reply-To: <20260323160822.1409904-1-youngjun.park@lge.com>

In the previous commit, uswsusp was modified to pin the swap device
when the swap type is determined, ensuring the device remains valid
throughout the hibernation I/O path.

Therefore, it is no longer necessary to repeatedly get and put the swap
device reference for each swap slot allocation and free operation.

For hibernation via the sysfs interface, user-space tasks are frozen
before swap allocation begins, so swapoff cannot race with allocation.
After resume, tasks remain frozen while swap slots are freed, so
additional reference management is not required there either.

Remove the redundant swap device get/put operations from the
hibernation swap allocation and free paths.

Also remove the SWP_WRITEOK check before allocation, as the cluster
allocation logic already validates the swap device state.

Update function comments to document the caller's responsibility for
ensuring swap device stability.

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

diff --git a/mm/swapfile.c b/mm/swapfile.c
index c5b459a18f43..ff315b752afd 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2077,7 +2077,16 @@ void swap_put_entries_direct(swp_entry_t entry, int nr)
 }
 
 #ifdef CONFIG_HIBERNATION
-/* Allocate a slot for hibernation */
+/**
+ * swap_alloc_hibernation_slot() - Allocate a swap slot for hibernation.
+ * @type: swap device type index to allocate from.
+ *
+ * The caller must ensure the swap device is stable, either by pinning
+ * it (SWP_HIBERNATION) or by freezing user-space.
+ *
+ * Return: a valid swp_entry_t on success, or an empty entry (val == 0)
+ * on failure.
+ */
 swp_entry_t swap_alloc_hibernation_slot(int type)
 {
 	struct swap_info_struct *pcp_si, *si = swap_type_to_info(type);
@@ -2088,46 +2097,42 @@ 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) {
-			/*
-			 * Try the local cluster first if it matches the device. If
-			 * not, try grab a new cluster and override local cluster.
-			 */
-			local_lock(&percpu_swap_cluster.lock);
-			pcp_si = this_cpu_read(percpu_swap_cluster.si[0]);
-			pcp_offset = this_cpu_read(percpu_swap_cluster.offset[0]);
-			if (pcp_si == si && pcp_offset) {
-				ci = swap_cluster_lock(si, pcp_offset);
-				if (cluster_is_usable(ci, 0))
-					offset = alloc_swap_scan_cluster(si, ci, NULL, pcp_offset);
-				else
-					swap_cluster_unlock(ci);
-			}
-			if (!offset)
-				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);
+	/*
+	 * Try the local cluster first if it matches the device. If
+	 * not, try grab a new cluster and override local cluster.
+	 */
+	local_lock(&percpu_swap_cluster.lock);
+	pcp_si = this_cpu_read(percpu_swap_cluster.si[0]);
+	pcp_offset = this_cpu_read(percpu_swap_cluster.offset[0]);
+	if (pcp_si == si && pcp_offset) {
+		ci = swap_cluster_lock(si, pcp_offset);
+		if (cluster_is_usable(ci, 0))
+			offset = alloc_swap_scan_cluster(si, ci, NULL, pcp_offset);
+		else
+			swap_cluster_unlock(ci);
 	}
+	if (!offset)
+		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 */
+/**
+ * swap_free_hibernation_slot() - Free a swap slot allocated for hibernation.
+ * @entry: swap entry to free.
+ *
+ * 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_cluster_put_entry(ci, offset % SWAPFILE_CLUSTER);
 	__swap_cluster_free_entries(si, ci, offset % SWAPFILE_CLUSTER, 1);
@@ -2135,7 +2140,6 @@ void swap_free_hibernation_slot(swp_entry_t entry)
 
 	/* 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 __find_hibernation_swap_type(dev_t device, sector_t offset)
-- 
2.34.1


^ permalink raw reply related

* [PATCH v8 1/2] mm/swap, PM: hibernate: fix swapoff race in uswsusp by pinning swap device
From: Youngjun Park @ 2026-03-23 16:08 UTC (permalink / raw)
  To: Rafael J . Wysocki, Andrew Morton
  Cc: Chris Li, Kairui Song, Pavel Machek, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, Usama Arif, linux-pm,
	linux-mm
In-Reply-To: <20260323160822.1409904-1-youngjun.park@lge.com>

Hibernation via uswsusp (/dev/snapshot ioctls) has a race window:
after selecting the resume swap area but before user space is frozen,
swapoff may run and invalidate the selected swap device.

Fix this by pinning the swap device with SWP_HIBERNATION while it is
in use.  The pin is exclusive, which is sufficient since
hibernate_acquire() already prevents concurrent hibernation sessions.

The kernel swsusp path (sysfs-based hibernate/resume) uses
find_hibernation_swap_type() which is not affected by the pin.  It
freezes user space before touching swap, so swapoff cannot race.

Introduce dedicated helpers:
- pin_hibernation_swap_type(): Look up and pin the swap device.
  Used by the uswsusp path.
- find_hibernation_swap_type(): Lookup without pinning.
  Used by the kernel swsusp path.
- unpin_hibernation_swap_type(): Clear the hibernation pin.

While a swap device is pinned, swapoff is prevented from proceeding.

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

diff --git a/include/linux/swap.h b/include/linux/swap.h
index 7a09df6977a5..1930f81e6be4 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -213,6 +213,7 @@ enum {
 	SWP_PAGE_DISCARD = (1 << 10),	/* freed swap page-cluster discards */
 	SWP_STABLE_WRITES = (1 << 11),	/* no overwrite PG_writeback pages */
 	SWP_SYNCHRONOUS_IO = (1 << 12),	/* synchronous IO is efficient */
+	SWP_HIBERNATION = (1 << 13),	/* pinned for hibernation */
 					/* add others here before... */
 };
 
@@ -433,7 +434,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);
+extern int pin_hibernation_swap_type(dev_t device, sector_t offset);
+extern void unpin_hibernation_swap_type(int type);
+extern int find_hibernation_swap_type(dev_t device, sector_t offset);
 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..4406f5644a56 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 = pin_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) {
+		unpin_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);
+	unpin_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;
 	}
 
+	/*
+	 * Unpin the swap device if a swap area was already
+	 * set by SNAPSHOT_SET_SWAP_AREA.
+	 */
+	unpin_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 = pin_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 802332850e24..c5b459a18f43 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() */
 }
@@ -2138,22 +2138,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 __find_hibernation_swap_type(dev_t device, sector_t offset)
 {
 	int type;
 
+	lockdep_assert_held(&swap_lock);
+
 	if (!device)
-		return -1;
+		return -EINVAL;
 
-	spin_lock(&swap_lock);
 	for (type = 0; type < nr_swapfiles; type++) {
 		struct swap_info_struct *sis = swap_info[type];
 
@@ -2163,16 +2156,118 @@ 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;
 }
 
+/**
+ * pin_hibernation_swap_type - Pin the swap device for hibernation
+ * @device: Block device containing the resume image
+ * @offset: Offset identifying the swap area
+ *
+ * Locate the swap device for @device/@offset and mark it as pinned
+ * for hibernation. While pinned, swapoff() is prevented.
+ *
+ * Only one uswsusp context may pin a swap device at a time.
+ * If already pinned, this function returns -EBUSY.
+ *
+ * Return:
+ * >= 0 on success (swap type).
+ * -EINVAL if @device is invalid.
+ * -ENODEV if the swap device is not found.
+ * -EBUSY if the device is already pinned for hibernation.
+ */
+int pin_hibernation_swap_type(dev_t device, sector_t offset)
+{
+	int type;
+	struct swap_info_struct *si;
+
+	spin_lock(&swap_lock);
+
+	type = __find_hibernation_swap_type(device, offset);
+	if (type < 0) {
+		spin_unlock(&swap_lock);
+		return type;
+	}
+
+	si = swap_type_to_info(type);
+	if (WARN_ON_ONCE(!si)) {
+		spin_unlock(&swap_lock);
+		return -ENODEV;
+	}
+
+	/*
+	 * hibernate_acquire() prevents concurrent hibernation sessions.
+	 * This check additionally guards against double-pinning within
+	 * the same session.
+	 */
+	if (WARN_ON_ONCE(si->flags & SWP_HIBERNATION)) {
+		spin_unlock(&swap_lock);
+		return -EBUSY;
+	}
+
+	si->flags |= SWP_HIBERNATION;
+
+	spin_unlock(&swap_lock);
+	return type;
+}
+
+/**
+ * unpin_hibernation_swap_type - Unpin the swap device for hibernation
+ * @type: Swap type previously returned by pin_hibernation_swap_type()
+ *
+ * Clear the hibernation pin on the given swap device, allowing
+ * swapoff() to proceed normally.
+ *
+ * If @type does not refer to a valid swap device, this function
+ * does nothing.
+ */
+void unpin_hibernation_swap_type(int type)
+{
+	struct swap_info_struct *si;
+
+	spin_lock(&swap_lock);
+	si = swap_type_to_info(type);
+	if (!si) {
+		spin_unlock(&swap_lock);
+		return;
+	}
+	si->flags &= ~SWP_HIBERNATION;
+	spin_unlock(&swap_lock);
+}
+
+/**
+ * find_hibernation_swap_type - Find swap type for hibernation
+ * @device: Block device containing the resume image
+ * @offset: Offset within the device identifying the swap area
+ *
+ * Locate the swap device corresponding to @device and @offset.
+ *
+ * Unlike pin_hibernation_swap_type(), this function only performs a
+ * lookup and does not mark the swap device as pinned for hibernation.
+ *
+ * This is safe in the sysfs-based hibernation path where user space
+ * is already frozen and swapoff() cannot run concurrently.
+ *
+ * Return:
+ * A non-negative swap type on success.
+ * -EINVAL if @device is invalid.
+ * -ENODEV if no matching swap device is found.
+ */
+int find_hibernation_swap_type(dev_t device, sector_t offset)
+{
+	int type;
+
+	spin_lock(&swap_lock);
+	type = __find_hibernation_swap_type(device, offset);
+	spin_unlock(&swap_lock);
+
+	return type;
+}
+
 int find_first_swap(dev_t *device)
 {
 	int type;
@@ -2936,6 +3031,14 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 		spin_unlock(&swap_lock);
 		goto out_dput;
 	}
+
+	/* Refuse swapoff while the device is pinned for hibernation */
+	if (p->flags & SWP_HIBERNATION) {
+		err = -EBUSY;
+		spin_unlock(&swap_lock);
+		goto out_dput;
+	}
+
 	if (!security_vm_enough_memory_mm(current->mm, p->pages))
 		vm_unacct_memory(p->pages);
 	else {
-- 
2.34.1


^ permalink raw reply related

* [PATCH v8 0/2] mm/swap, PM: hibernate: fix swapoff race in uswsusp by pinning swap device
From: Youngjun Park @ 2026-03-23 16:08 UTC (permalink / raw)
  To: Rafael J . Wysocki, Andrew Morton
  Cc: Chris Li, Kairui Song, Pavel Machek, Kemeng Shi, Nhat Pham,
	Baoquan He, Barry Song, Youngjun Park, Usama Arif, linux-pm,
	linux-mm

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 pinning the swap device
  from the point it is looked up until the session completes.
- Patch 2: Removes the overhead of per-slot reference counting in alloc/free
  paths and cleans up the redundant SWP_WRITEOK check.

Rebased onto mm-new per Andrew's suggestion [1]. The si->flags race
flagged by AI review in v7 (between SWP_HIBERNATION and cont_lock in
add_swap_count_continuation) and the proposed fixes discussed there
(atomic ops for si->flags, or serializing with swap_lock) are all moot
on mm-new since Kairui's series removed that code path entirely.
kernel/power/ changes are small, so Andrew proposed carrying everything
through mm-new.

Rafael, could you ack the PM-side changes?

Re-tested on mm-new (c51ea78c5466) with hibernate/resume cycles and
uswsusp paths. Also ran an additional round of AI review against the
rebased version, no new issues found.

[1] https://lore.kernel.org/linux-mm/20260322093038.25a7fd51f5d564b85815db7a@linux-foundation.org/

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
v5: https://lore.kernel.org/linux-mm/ab0YEn+Fd41q6LM7@yjaykim-PowerEdge-T330/T/#m8409d470c68cb152b0849940759bff7d7806f397
v6: https://lore.kernel.org/linux-mm/20260320182227.896f9ab62d62961b2caab5f7@linux-foundation.org/T/#m10ee3346cd8dcd052749105d9a8e2052dbf3bc80
v7: https://lore.kernel.org/linux-mm/ab/20260321103309.439265-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.
- swapoff during active uswsusp session:
  - Verified swapoff returns -EBUSY while swap device is pinned (Patch 1).
  - Verified swapoff succeeds after uswsusp process terminates.

Changelog:
v7 -> v8:
 - Rebased onto mm-new per Andrew Morton's suggestion.
 - Clarified function comments (SWP_HIBERNATION pinning).
 - Re-tested and AI-reviewed on mm-new; no new issues found.

v6 -> v7:
 - Dropped Patch 3 (pm_restore_gfp_mask fix) from series as it has
   no dependency on Patches 1-2. Will be sent separately.
   (Rafael J. Wysocki feedback)

v5 -> v6:
 - Replaced get/put reference approach with SWP_HIBERNATION
   pinning to prevent swapoff, per Kairui's feedback.  Renamed helpers
   from get/find/put_hibernation_swap_type() to
   pin/find/unpin_hibernation_swap_type().
 - Renamed swap_type_of() to __find_hibernation_swap_type() since
   it is now an internal helper with no external callers.
 - Removed swapoff waiting on hibernation reference.
   swapoff now returns -EBUSY immediately when the swap device is
   pinned.
 - Updated function comments per Kairui's review.

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

rfc v3 -> v4:
 - Introduced get/find/put_hibernation_swap_type() helpers per Kairui's
   feedback.
 - Switched to swap_type_to_info() and added type < 0 check.
 - Fixed get_hibernation_swap_type() return when ref == false.
 - Made swapoff wait interruptible to prevent hang when uswsusp
   holds a swap reference.

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

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

Youngjun Park (2):
  mm/swap, PM: hibernate: fix swapoff race in uswsusp by pinning swap
    device
  mm/swap: remove redundant swap device reference in alloc/free

 include/linux/swap.h |   5 +-
 kernel/power/swap.c  |   2 +-
 kernel/power/user.c  |  15 +++-
 mm/swapfile.c        | 203 +++++++++++++++++++++++++++++++++----------
 4 files changed, 172 insertions(+), 53 deletions(-)

base-commit: c51ea78c5466be89914cbfbe2618dea67026c2b1
-- 
2.34.1


^ permalink raw reply

* [PATCH v3 1/2] dt-bindings: power: supply: gpio-charger: add support for fast-charge timer
From: Dimitri Fedrau via B4 Relay @ 2026-03-23 16:04 UTC (permalink / raw)
  To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-pm, devicetree, linux-kernel, Dimitri Fedrau,
	Dimitri Fedrau
In-Reply-To: <20260323-gpio-charger-timer-v3-0-885796d681a5@liebherr.com>

From: Dimitri Fedrau <dimitri.fedrau@liebherr.com>

On some devices like TIs BQ24081 battery charger it is possible to activate
or deactivate a fast-charge timer that provides a backup safety for charge
termination via GPIO. In case of the BQ24081 it is a fixed 7-hour timer.

Signed-off-by: Dimitri Fedrau <dimitri.fedrau@liebherr.com>
---
 .../bindings/power/supply/gpio-charger.yaml        | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml b/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml
index 25826bfc289c1c00c338fd0cee2ae6932529cfc3..fefa09cb24ec2f501099f486c9a4eb77e64cda67 100644
--- a/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml
+++ b/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml
@@ -16,7 +16,12 @@ description:
 
 properties:
   compatible:
-    const: gpio-charger
+    oneOf:
+      - const: gpio-charger
+      - items:
+          - enum:
+              - ti,bq24081
+          - const: gpio-charger
 
   charger-type:
     enum:
@@ -62,6 +67,10 @@ properties:
     description: Default charge current limit. Must be listed in
       charge-current-limit-mapping.
 
+  fast-charge-timer-gpios:
+    maxItems: 1
+    description: GPIO used for enabling/disabling the fast-charge timer
+
 required:
   - compatible
 
@@ -98,3 +107,14 @@ examples:
                                      <0 0x02>; // 0 mA => GPIO A.11 high
       charge-current-limit-default-microamp = <700000>;
     };
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    charger {
+      compatible = "ti,bq24081", "gpio-charger";
+      charger-type = "battery";
+      charge-status-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+      charge-current-limit-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
+      charge-current-limit-mapping = <206000 0x1>, <0 0x0>;
+      fast-charge-timer-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
+    };

-- 
2.39.5



^ permalink raw reply related

* [PATCH v3 2/2] power: supply: gpio-charger: add support for fast-charge timer
From: Dimitri Fedrau via B4 Relay @ 2026-03-23 16:04 UTC (permalink / raw)
  To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-pm, devicetree, linux-kernel, Dimitri Fedrau,
	Dimitri Fedrau
In-Reply-To: <20260323-gpio-charger-timer-v3-0-885796d681a5@liebherr.com>

From: Dimitri Fedrau <dimitri.fedrau@liebherr.com>

On some devices like TIs BQ24081 battery charger it is possible to activate
or deactivate a fast-charge timer that provides a backup safety for charge
termination. In case of the BQ24081 it is a fixed 7-hour timer. Add support
for enabling/disabling the fast-charge timer via GPIO.

Signed-off-by: Dimitri Fedrau <dimitri.fedrau@liebherr.com>
---
 .../ABI/testing/sysfs-class-power-gpio-charger     | 14 ++++++
 drivers/power/supply/gpio-charger.c                | 56 +++++++++++++++++++++-
 2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-class-power-gpio-charger b/Documentation/ABI/testing/sysfs-class-power-gpio-charger
new file mode 100644
index 0000000000000000000000000000000000000000..4a14d1d1bee3b96b6c77865e693c892d9bc3e5d6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-power-gpio-charger
@@ -0,0 +1,14 @@
+What:		/sys/class/power_supply/<supply_name>/fast_charge_timer
+Date:		March 2026
+KernelVersion:	7.1.0
+Contact:	Dimitri Fedrau <dimitri.fedrau@liebherr.com>
+Description:
+		This entry enables or disables the timer in fast-charge mode.
+		When enabled the timer is started with a fixed timeout. After
+		timing out, charging is disabled. This provides a backup safety
+		for charge termination. Disabling the timer doesn't have any
+		impact on charge termination.
+
+		Access: Write
+
+		Valid values: 0 (disabled) or 1 (enabled)
diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c
index 2504190eba82e69b79382320e67de6b8f3dedc77..8b67118be38ffd974a67f8bee3b47973903196c5 100644
--- a/drivers/power/supply/gpio-charger.c
+++ b/drivers/power/supply/gpio-charger.c
@@ -32,6 +32,7 @@ struct gpio_charger {
 	struct power_supply_desc charger_desc;
 	struct gpio_desc *gpiod;
 	struct gpio_desc *charge_status;
+	struct gpio_desc *timer;
 
 	struct gpio_descs *current_limit_gpios;
 	struct gpio_mapping *current_limit_map;
@@ -39,6 +40,18 @@ struct gpio_charger {
 	u32 charge_current_limit;
 };
 
+struct gpio_charger_data {
+	bool has_fast_charge_timer;
+};
+
+static const struct gpio_charger_data gpio_charger_data = {
+	.has_fast_charge_timer = false,
+};
+
+static const struct gpio_charger_data bq24081_data = {
+	.has_fast_charge_timer = true,
+};
+
 static irqreturn_t gpio_charger_irq(int irq, void *devid)
 {
 	struct power_supply *charger = devid;
@@ -259,6 +272,36 @@ static int init_charge_current_limit(struct device *dev,
 	return 0;
 }
 
+static ssize_t fast_charge_timer_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct gpio_charger *gpio_charger = power_supply_get_drvdata(psy);
+	int ret;
+	bool en;
+
+	if (kstrtobool(buf, &en))
+		return -EINVAL;
+
+	if (!gpio_charger->timer)
+		return -ENODEV;
+
+	ret = gpiod_set_value_cansleep(gpio_charger->timer, en);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static DEVICE_ATTR_WO(fast_charge_timer);
+
+static struct attribute *gpio_charger_attrs[] = {
+	&dev_attr_fast_charge_timer.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(gpio_charger);
+
 /*
  * The entries will be overwritten by driver's probe routine depending
  * on the available features. This list ensures, that the array is big
@@ -274,6 +317,7 @@ static int gpio_charger_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct gpio_charger_platform_data *pdata = dev->platform_data;
+	const struct gpio_charger_data *data = device_get_match_data(dev);
 	struct power_supply_config psy_cfg = {};
 	struct gpio_charger *gpio_charger;
 	struct power_supply_desc *charger_desc;
@@ -308,6 +352,13 @@ static int gpio_charger_probe(struct platform_device *pdev)
 		num_props++;
 	}
 
+	gpio_charger->timer = devm_gpiod_get_optional(dev, "fast-charge-timer",
+						      GPIOD_OUT_HIGH);
+	if (IS_ERR(gpio_charger->timer)) {
+		return dev_err_probe(dev, PTR_ERR(gpio_charger->timer),
+				     "error getting fast-charge timer GPIO descriptor\n");
+	}
+
 	charge_status = devm_gpiod_get_optional(dev, "charge-status", GPIOD_IN);
 	if (IS_ERR(charge_status))
 		return PTR_ERR(charge_status);
@@ -336,6 +387,8 @@ static int gpio_charger_probe(struct platform_device *pdev)
 
 	psy_cfg.fwnode = dev_fwnode(dev);
 	psy_cfg.drv_data = gpio_charger;
+	if (data->has_fast_charge_timer)
+		psy_cfg.attr_grp = gpio_charger_groups;
 
 	if (pdata) {
 		charger_desc->name = pdata->name;
@@ -402,7 +455,8 @@ static SIMPLE_DEV_PM_OPS(gpio_charger_pm_ops,
 		gpio_charger_suspend, gpio_charger_resume);
 
 static const struct of_device_id gpio_charger_match[] = {
-	{ .compatible = "gpio-charger" },
+	{ .compatible = "gpio-charger", .data = &gpio_charger_data, },
+	{ .compatible = "ti,bq24081", .data = &bq24081_data, },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, gpio_charger_match);

-- 
2.39.5



^ permalink raw reply related

* [PATCH v3 0/2] power: supply: gpio-charger: add support for fast-charge timer
From: Dimitri Fedrau via B4 Relay @ 2026-03-23 16:04 UTC (permalink / raw)
  To: Sebastian Reichel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: linux-pm, devicetree, linux-kernel, Dimitri Fedrau,
	Dimitri Fedrau

On some devices like TIs BQ24081 battery charger it is possible to activate
or deactivate a fast-charge timer that provides a backup safety for charge
termination. In case of the BQ24081 it is a fixed 7-hour timer. Add support
for enabling/disabling the fast-charge timer via GPIO.

Signed-off-by: Dimitri Fedrau <dimitri.fedrau@liebherr.com>
---
Changes in v3:
- Add documentation for fast_charge_timer
- Add a compatible for the BQ24081 (using gpio-charger as fallback) and
  then only allow 'fast-charge-timer-gpios' for the BQ24081.
- Add sample in device-tree bindings
- Removed acked-by from Connor because device-tree bindings changed
- Link to v2: https://lore.kernel.org/r/20260109-gpio-charger-timer-v2-0-63fd1ba75830@liebherr.com

Changes in v2:
- Added Acked-by tag
- Link to v1: https://lore.kernel.org/r/20251022-gpio-charger-timer-v1-0-b557409400f2@liebherr.com

---
Dimitri Fedrau (2):
      dt-bindings: power: supply: gpio-charger: add support for fast-charge timer
      power: supply: gpio-charger: add support for fast-charge timer

 .../ABI/testing/sysfs-class-power-gpio-charger     | 14 ++++++
 .../bindings/power/supply/gpio-charger.yaml        | 22 ++++++++-
 drivers/power/supply/gpio-charger.c                | 56 +++++++++++++++++++++-
 3 files changed, 90 insertions(+), 2 deletions(-)
---
base-commit: aa2132799817fb052d95a87f0c23cc6af38541c0
change-id: 20251022-gpio-charger-timer-cddae1619714

Best regards,
-- 
Dimitri Fedrau <dimitri.fedrau@liebherr.com>



^ permalink raw reply

* [PATCH v2 01/19] tracepoint: Add trace_call__##name() API
From: Vineeth Pillai (Google) @ 2026-03-23 16:00 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra, Dmitry Ilvokhin
  Cc: Vineeth Pillai (Google), Masami Hiramatsu, Mathieu Desnoyers,
	Ingo Molnar, Jens Axboe, io-uring, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Marcelo Ricardo Leitner, Xin Long, Jon Maloy, Aaron Conole,
	Eelco Chaudron, Ilya Maximets, netdev, bpf, linux-sctp,
	tipc-discussion, dev, Jiri Pirko, Oded Gabbay, Koby Elbaz,
	dri-devel, Rafael J. Wysocki, Viresh Kumar, Gautham R. Shenoy,
	Huang Rui, Mario Limonciello, Len Brown, Srinivas Pandruvada,
	linux-pm, MyungJoo Ham, Kyungmin Park, Chanwoo Choi,
	Christian König, Sumit Semwal, linaro-mm-sig, Eddie James,
	Andrew Jeffery, Joel Stanley, linux-fsi, David Airlie,
	Simona Vetter, Alex Deucher, Danilo Krummrich, Matthew Brost,
	Philipp Stanner, Harry Wentland, Leo Li, amd-gfx, Jiri Kosina,
	Benjamin Tissoires, linux-input, Wolfram Sang, linux-i2c,
	Mark Brown, Michael Hennerich, Nuno Sá, linux-spi,
	James E.J. Bottomley, Martin K. Petersen, linux-scsi, Chris Mason,
	David Sterba, linux-btrfs, Thomas Gleixner, Andrew Morton,
	SeongJae Park, linux-mm, Borislav Petkov, Dave Hansen, x86,
	linux-trace-kernel, linux-kernel
In-Reply-To: <20260323160052.17528-1-vineeth@bitbyteword.org>

Add trace_call__##name() as a companion to trace_##name().  When a
caller already guards a tracepoint with an explicit enabled check:

  if (trace_foo_enabled() && cond)
      trace_foo(args);

trace_foo() internally repeats the static_branch_unlikely() test, which
the compiler cannot fold since static branches are patched binary
instructions.  This results in two static-branch evaluations for every
guarded call site.

trace_call__##name() calls __do_trace_##name() directly, skipping the
redundant static-branch re-check.  This avoids leaking the internal
__do_trace_##name() symbol into call sites while still eliminating the
double evaluation:

  if (trace_foo_enabled() && cond)
      trace_invoke_foo(args);   /* calls __do_trace_foo() directly */

Three locations are updated:
- __DECLARE_TRACE: invoke form omits static_branch_unlikely, retains
  the LOCKDEP RCU-watching assertion.
- __DECLARE_TRACE_SYSCALL: same, plus retains might_fault().
- !TRACEPOINTS_ENABLED stub: empty no-op so callers compile cleanly
  when tracepoints are compiled out.

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Vineeth Pillai (Google) <vineeth@bitbyteword.org>
Assisted-by: Claude:claude-sonnet-4-6
---
 include/linux/tracepoint.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 22ca1c8b54f32..ed969705341f1 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -294,6 +294,10 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
 			WARN_ONCE(!rcu_is_watching(),			\
 				  "RCU not watching for tracepoint");	\
 		}							\
+	}								\
+	static inline void trace_call__##name(proto)			\
+	{								\
+		__do_trace_##name(args);				\
 	}
 
 #define __DECLARE_TRACE_SYSCALL(name, proto, args, data_proto)		\
@@ -313,6 +317,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
 			WARN_ONCE(!rcu_is_watching(),			\
 				  "RCU not watching for tracepoint");	\
 		}							\
+	}								\
+	static inline void trace_call__##name(proto)			\
+	{								\
+		might_fault();						\
+		__do_trace_##name(args);				\
 	}
 
 /*
@@ -398,6 +407,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
 #define __DECLARE_TRACE_COMMON(name, proto, args, data_proto)		\
 	static inline void trace_##name(proto)				\
 	{ }								\
+	static inline void trace_call__##name(proto)			\
+	{ }								\
 	static inline int						\
 	register_trace_##name(void (*probe)(data_proto),		\
 			      void *data)				\
-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 07/19] devfreq: Use trace_call__##name() at guarded tracepoint call sites
From: Vineeth Pillai (Google) @ 2026-03-23 16:00 UTC (permalink / raw)
  Cc: Vineeth Pillai (Google), Steven Rostedt, Peter Zijlstra,
	MyungJoo Ham, Kyungmin Park, Chanwoo Choi, linux-pm, linux-kernel,
	linux-trace-kernel
In-Reply-To: <20260323160052.17528-1-vineeth@bitbyteword.org>

Replace trace_foo() with the new trace_call__foo() at sites already
guarded by trace_foo_enabled(), avoiding a redundant
static_branch_unlikely() re-evaluation inside the tracepoint.
trace_call__foo() calls the tracepoint callbacks directly without
utilizing the static branch again.

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Vineeth Pillai (Google) <vineeth@bitbyteword.org>
Assisted-by: Claude:claude-sonnet-4-6
---
 drivers/devfreq/devfreq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index c0a74091b9041..d1b27d9b753df 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -370,7 +370,7 @@ static int devfreq_set_target(struct devfreq *devfreq, unsigned long new_freq,
 	 * change order of between devfreq device and passive devfreq device.
 	 */
 	if (trace_devfreq_frequency_enabled() && new_freq != cur_freq)
-		trace_devfreq_frequency(devfreq, new_freq, cur_freq);
+		trace_call__devfreq_frequency(devfreq, new_freq, cur_freq);
 
 	freqs.new = new_freq;
 	devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 06/19] cpufreq: Use trace_call__##name() at guarded tracepoint call sites
From: Vineeth Pillai (Google) @ 2026-03-23 16:00 UTC (permalink / raw)
  Cc: Vineeth Pillai (Google), Steven Rostedt, Peter Zijlstra,
	Huang Rui, Gautham R. Shenoy, Mario Limonciello, Perry Yuan,
	Rafael J. Wysocki, Viresh Kumar, Srinivas Pandruvada, Len Brown,
	linux-pm, linux-kernel, linux-trace-kernel
In-Reply-To: <20260323160052.17528-1-vineeth@bitbyteword.org>

Replace trace_foo() with the new trace_call__foo() at sites already
guarded by trace_foo_enabled(), avoiding a redundant
static_branch_unlikely() re-evaluation inside the tracepoint.
trace_call__foo() calls the tracepoint callbacks directly without
utilizing the static branch again.

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Vineeth Pillai (Google) <vineeth@bitbyteword.org>
Assisted-by: Claude:claude-sonnet-4-6
---
 drivers/cpufreq/amd-pstate.c   | 10 +++++-----
 drivers/cpufreq/cpufreq.c      |  2 +-
 drivers/cpufreq/intel_pstate.c |  2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 5aa9fcd80cf51..4c47324aa2f73 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -247,7 +247,7 @@ static int msr_update_perf(struct cpufreq_policy *policy, u8 min_perf,
 	if (trace_amd_pstate_epp_perf_enabled()) {
 		union perf_cached perf = READ_ONCE(cpudata->perf);
 
-		trace_amd_pstate_epp_perf(cpudata->cpu,
+		trace_call__amd_pstate_epp_perf(cpudata->cpu,
 					  perf.highest_perf,
 					  epp,
 					  min_perf,
@@ -298,7 +298,7 @@ static int msr_set_epp(struct cpufreq_policy *policy, u8 epp)
 	if (trace_amd_pstate_epp_perf_enabled()) {
 		union perf_cached perf = cpudata->perf;
 
-		trace_amd_pstate_epp_perf(cpudata->cpu, perf.highest_perf,
+		trace_call__amd_pstate_epp_perf(cpudata->cpu, perf.highest_perf,
 					  epp,
 					  FIELD_GET(AMD_CPPC_MIN_PERF_MASK,
 						    cpudata->cppc_req_cached),
@@ -343,7 +343,7 @@ static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp)
 	if (trace_amd_pstate_epp_perf_enabled()) {
 		union perf_cached perf = cpudata->perf;
 
-		trace_amd_pstate_epp_perf(cpudata->cpu, perf.highest_perf,
+		trace_call__amd_pstate_epp_perf(cpudata->cpu, perf.highest_perf,
 					  epp,
 					  FIELD_GET(AMD_CPPC_MIN_PERF_MASK,
 						    cpudata->cppc_req_cached),
@@ -507,7 +507,7 @@ static int shmem_update_perf(struct cpufreq_policy *policy, u8 min_perf,
 	if (trace_amd_pstate_epp_perf_enabled()) {
 		union perf_cached perf = READ_ONCE(cpudata->perf);
 
-		trace_amd_pstate_epp_perf(cpudata->cpu,
+		trace_call__amd_pstate_epp_perf(cpudata->cpu,
 					  perf.highest_perf,
 					  epp,
 					  min_perf,
@@ -588,7 +588,7 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf,
 	}
 
 	if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) {
-		trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
+		trace_call__amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
 			cpudata->cur.mperf, cpudata->cur.aperf, cpudata->cur.tsc,
 				cpudata->cpu, fast_switch);
 	}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 277884d91913c..58901047eae5a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2222,7 +2222,7 @@ unsigned int cpufreq_driver_fast_switch(struct cpufreq_policy *policy,
 
 	if (trace_cpu_frequency_enabled()) {
 		for_each_cpu(cpu, policy->cpus)
-			trace_cpu_frequency(freq, cpu);
+			trace_call__cpu_frequency(freq, cpu);
 	}
 
 	return freq;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 11c58af419006..70be952209144 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -3132,7 +3132,7 @@ static void intel_cpufreq_trace(struct cpudata *cpu, unsigned int trace_type, in
 		return;
 
 	sample = &cpu->sample;
-	trace_pstate_sample(trace_type,
+	trace_call__pstate_sample(trace_type,
 		0,
 		old_pstate,
 		cpu->pstate.current_pstate,
-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 00/19] tracepoint: Avoid double static_branch evaluation at guarded call sites
From: Vineeth Pillai (Google) @ 2026-03-23 16:00 UTC (permalink / raw)
  To: Steven Rostedt, Peter Zijlstra, Dmitry Ilvokhin
  Cc: Vineeth Pillai (Google), Masami Hiramatsu, Mathieu Desnoyers,
	Ingo Molnar, Jens Axboe, io-uring, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Alexei Starovoitov, Daniel Borkmann,
	Marcelo Ricardo Leitner, Xin Long, Jon Maloy, Aaron Conole,
	Eelco Chaudron, Ilya Maximets, netdev, bpf, linux-sctp,
	tipc-discussion, dev, Jiri Pirko, Oded Gabbay, Koby Elbaz,
	dri-devel, Rafael J. Wysocki, Viresh Kumar, Gautham R. Shenoy,
	Huang Rui, Mario Limonciello, Len Brown, Srinivas Pandruvada,
	linux-pm, MyungJoo Ham, Kyungmin Park, Chanwoo Choi,
	Christian König, Sumit Semwal, linaro-mm-sig, Eddie James,
	Andrew Jeffery, Joel Stanley, linux-fsi, David Airlie,
	Simona Vetter, Alex Deucher, Danilo Krummrich, Matthew Brost,
	Philipp Stanner, Harry Wentland, Leo Li, amd-gfx, Jiri Kosina,
	Benjamin Tissoires, linux-input, Wolfram Sang, linux-i2c,
	Mark Brown, Michael Hennerich, Nuno Sá, linux-spi,
	James E.J. Bottomley, Martin K. Petersen, linux-scsi, Chris Mason,
	David Sterba, linux-btrfs, Thomas Gleixner, Andrew Morton,
	SeongJae Park, linux-mm, Borislav Petkov, Dave Hansen, x86,
	linux-trace-kernel, linux-kernel

When a caller already guards a tracepoint with an explicit enabled check:

  if (trace_foo_enabled() && cond)
      trace_foo(args);

trace_foo() internally re-evaluates the static_branch_unlikely() key.
Since static branches are patched binary instructions the compiler cannot
fold the two evaluations, so every such site pays the cost twice.

This series introduces trace_call__##name() as a companion to
trace_##name().  It calls __do_trace_##name() directly, bypassing the
redundant static-branch re-check, while preserving all other correctness
properties of the normal path (RCU-watching assertion, might_fault() for
syscall tracepoints).  The internal __do_trace_##name() symbol is not
leaked to call sites; trace_call__##name() is the only new public API.

  if (trace_foo_enabled() && cond)
      trace_call__foo(args);   /* calls __do_trace_foo() directly */

The first patch adds the three-location change to
include/linux/tracepoint.h (__DECLARE_TRACE, __DECLARE_TRACE_SYSCALL,
and the !TRACEPOINTS_ENABLED stub).  The remaining 18 patches
mechanically convert all guarded call sites found in the tree:
kernel/, io_uring/, net/, accel/habanalabs, cpufreq/, devfreq/,
dma-buf/, fsi/, drm/, HID, i2c/, spi/, scsi/ufs/, btrfs/,
net/devlink/, kernel/time/, kernel/trace/, mm/damon/, and arch/x86/.

This series is motivated by Peter Zijlstra's observation in the discussion
around Dmitry Ilvokhin's locking tracepoint instrumentation series, where
he noted that compilers cannot optimize static branches and that guarded
call sites end up evaluating the static branch twice for no reason, and
by Steven Rostedt's suggestion to add a proper API instead of exposing
internal implementation details like __do_trace_##name() directly to
call sites:

  https://lore.kernel.org/linux-trace-kernel/8298e098d3418cb446ef396f119edac58a3414e9.1772642407.git.d@ilvokhin.com

Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Suggested-by: Peter Zijlstra <peterz@infradead.org>

Changes in v2:
- Renamed trace_invoke_##name() to trace_call__##name() (double
  underscore) per review comments.
- Added 4 new patches covering sites missed in v1, found using
  coccinelle to scan the tree (Keith Busch):
    * net/devlink: guarded tracepoint_enabled() block in trap.c
    * kernel/time: early-return guard in tick-sched.c (tick_stop)
    * kernel/trace: early-return guard in trace_benchmark.c
    * mm/damon: early-return guard in core.c
    * arch/x86: do_trace_*() wrapper functions in lib/msr.c, which
      are called exclusively from tracepoint_enabled()-guarded sites
      in asm/msr.h

v1: https://lore.kernel.org/linux-trace-kernel/abSqrJ1J59RQC47U@kbusch-mbp/

Vineeth Pillai (Google) (19):
  tracepoint: Add trace_call__##name() API
  kernel: Use trace_call__##name() at guarded tracepoint call sites
  io_uring: Use trace_call__##name() at guarded tracepoint call sites
  net: Use trace_call__##name() at guarded tracepoint call sites
  accel/habanalabs: Use trace_call__##name() at guarded tracepoint call
    sites
  cpufreq: Use trace_call__##name() at guarded tracepoint call sites
  devfreq: Use trace_call__##name() at guarded tracepoint call sites
  dma-buf: Use trace_call__##name() at guarded tracepoint call sites
  fsi: Use trace_call__##name() at guarded tracepoint call sites
  drm: Use trace_call__##name() at guarded tracepoint call sites
  HID: Use trace_call__##name() at guarded tracepoint call sites
  i2c: Use trace_call__##name() at guarded tracepoint call sites
  spi: Use trace_call__##name() at guarded tracepoint call sites
  scsi: ufs: Use trace_call__##name() at guarded tracepoint call sites
  btrfs: Use trace_call__##name() at guarded tracepoint call sites
  net: devlink: Use trace_call__##name() at guarded tracepoint call
    sites
  kernel: time, trace: Use trace_call__##name() at guarded tracepoint
    call sites
  mm: damon: Use trace_call__##name() at guarded tracepoint call sites
  x86: msr: Use trace_call__##name() at guarded tracepoint call sites

 arch/x86/lib/msr.c                                |  6 +++---
 drivers/accel/habanalabs/common/device.c          | 12 ++++++------
 drivers/accel/habanalabs/common/mmu/mmu.c         |  3 ++-
 drivers/accel/habanalabs/common/pci/pci.c         |  4 ++--
 drivers/cpufreq/amd-pstate.c                      | 10 +++++-----
 drivers/cpufreq/cpufreq.c                         |  2 +-
 drivers/cpufreq/intel_pstate.c                    |  2 +-
 drivers/devfreq/devfreq.c                         |  2 +-
 drivers/dma-buf/dma-fence.c                       |  4 ++--
 drivers/fsi/fsi-master-aspeed.c                   |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c            |  2 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c            |  4 ++--
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  2 +-
 drivers/gpu/drm/scheduler/sched_entity.c          |  4 ++--
 drivers/hid/intel-ish-hid/ipc/pci-ish.c           |  2 +-
 drivers/i2c/i2c-core-slave.c                      |  2 +-
 drivers/spi/spi-axi-spi-engine.c                  |  4 ++--
 drivers/ufs/core/ufshcd.c                         | 12 ++++++------
 fs/btrfs/extent_map.c                             |  4 ++--
 fs/btrfs/raid56.c                                 |  4 ++--
 include/linux/tracepoint.h                        | 11 +++++++++++
 io_uring/io_uring.h                               |  2 +-
 kernel/irq_work.c                                 |  2 +-
 kernel/sched/ext.c                                |  2 +-
 kernel/smp.c                                      |  2 +-
 kernel/time/tick-sched.c                          | 12 ++++++------
 kernel/trace/trace_benchmark.c                    |  2 +-
 mm/damon/core.c                                   |  2 +-
 net/core/dev.c                                    |  2 +-
 net/core/xdp.c                                    |  2 +-
 net/devlink/trap.c                                |  2 +-
 net/openvswitch/actions.c                         |  2 +-
 net/openvswitch/datapath.c                        |  2 +-
 net/sctp/outqueue.c                               |  2 +-
 net/tipc/node.c                                   |  2 +-
 35 files changed, 74 insertions(+), 62 deletions(-)

-- 
2.53.0


^ permalink raw reply

* Re: [PATCH v6 6/9] dt-bindings: connector: m2: Add M.2 1620 LGA soldered down connector
From: Manivannan Sadhasivam @ 2026-03-23 15:56 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Herring, Manivannan Sadhasivam, Greg Kroah-Hartman,
	Jiri Slaby, Nathan Chancellor, Nicolas Schier, Hans de Goede,
	Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Andy Shevchenko,
	Bartosz Golaszewski, linux-serial, linux-kernel, linux-kbuild,
	platform-driver-x86, linux-pci, devicetree, linux-arm-msm,
	linux-bluetooth, linux-pm, Stephan Gerhold, linux-acpi
In-Reply-To: <fsvmmgoe5wslmxebhrrwmdg2ldcmhzvj53gjkdfnfg2m2rz2lw@dcfboaakz7ae>

On Mon, Mar 23, 2026 at 05:14:30PM +0200, Dmitry Baryshkov wrote:
> On Mon, Mar 23, 2026 at 07:14:25PM +0530, Manivannan Sadhasivam wrote:
> > On Mon, Mar 23, 2026 at 08:39:55AM -0500, Rob Herring wrote:
> > > On Mon, Mar 23, 2026 at 7:16 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > > >
> > > > On Sun, Mar 22, 2026 at 06:37:13PM -0500, Rob Herring wrote:
> > > > > On Tue, Mar 17, 2026 at 09:59:56AM +0530, Manivannan Sadhasivam wrote:
> > > > > > Lenovo Thinkpad T14s is found to have a soldered down version of M.2 1620
> > > > > > LGA connector. Though, there is no 1620 LGA form factor defined in the M.2
> > > > > > spec, it looks very similar to the M.2 Key E connector. So add the
> > > > > > "pcie-m2-1620-lga-connector" compatible with "pcie-m2-e-connector" fallback
> > > > > > to reuse the Key E binding.
> > > > >
> > > > > What is LGA?
> > > > >
> > > >
> > > > Land Grid Array
> > > >
> > > > > If not in the spec, is it really something generic?
> > > > >
> > > >
> > > > Good question. Yes and No! LGA is not something that Lenovo only uses. Other
> > > > vendors may also use this form factor. PCIe connectors are full of innovation as
> > > > the spec gives room for hardware designers to be as innovative as possible to
> > > > save the BOM cost.
> > > 
> > > innovation == incompatible changes
> > > 
> > 
> > Yes, I was trying to sound nice :)
> > 
> > > > This is why I do not want to make it Lenovo specific. But if you prefer that, I
> > > > can name it as "lenovo,pcie-m2-1620-lga-connector".
> > > 
> > > Depends if you think that s/w needs to know the differences. Hard to
> > > say with a sample size of 1.
> > > 
> > 
> > Sure. Will add the 'lenovo' prefix then.
> 
> Is it really Lenovo? Or is it some other module vendor, whose LGAs are
> being used by Lenovo?
> 
> I remember that DB820c also used some kind of a module for the WiFi card
> (which might be M.2 compatible or might not, I can't find exact docs at
> this point).
> 

I don't know. These kind of designs might be reused by several vendors. But
considering that we should not make it generic, I'd go with Lenovo as that's
the only vendor we know as of now.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH v5 00/21] Virtual Swap Space
From: Nhat Pham @ 2026-03-23 15:32 UTC (permalink / raw)
  To: Kairui Song
  Cc: Liam.Howlett, akpm, apopple, axelrasmussen, baohua, baolin.wang,
	bhe, byungchul, cgroups, chengming.zhou, chrisl, corbet, david,
	dev.jain, gourry, hannes, hughd, jannh, joshua.hahnjy, lance.yang,
	lenb, linux-doc, linux-kernel, linux-mm, linux-pm,
	lorenzo.stoakes, matthew.brost, mhocko, muchun.song, npache,
	pavel, peterx, peterz, pfalcato, rafael, rakie.kim,
	roman.gushchin, rppt, ryan.roberts, shakeel.butt, shikemeng,
	surenb, tglx, vbabka, weixugc, ying.huang, yosry.ahmed, yuanchu,
	zhengqi.arch, ziy, kernel-team, riel
In-Reply-To: <CAMgjq7AiUr_Ntj51qoqvV+=XbEATjr7S4MH+rgD32T5pHfF7mg@mail.gmail.com>

On Mon, Mar 23, 2026 at 6:09 AM Kairui Song <ryncsn@gmail.com> wrote:
>
> On Sat, Mar 21, 2026 at 3:29 AM Nhat Pham <nphamcs@gmail.com> wrote:
> > This patch series is based on 6.19. There are a couple more
> > swap-related changes in mainline that I would need to coordinate
> > with, but I still want to send this out as an update for the
> > regressions reported by Kairui Song in [15]. It's probably easier
> > to just build this thing rather than dig through that series of
> > emails to get the fix patch :)
> >
> > Changelog:
> > * v4 -> v5:
> >     * Fix a deadlock in memcg1_swapout (reported by syzbot [16]).
> >     * Replace VM_WARN_ON(!spin_is_locked()) with lockdep_assert_held(),
> >       and use guard(rcu) in vswap_cpu_dead
> >       (reported by Peter Zijlstra [17]).
> > * v3 -> v4:
> >     * Fix poor swap free batching behavior to alleviate a regression
> >       (reported by Kairui Song).
>

Hi Kairui! Thanks a lot for the testing big boss :) I will focus on
the regression in this patch series - we can talk more about
directions in another thread :)

> I tested the v5 (including the batched-free hotfix) and am still
> seeing significant regressions in both sequential and concurrent swap
> workloads
>
> Thanks for the update as I can see It's a lot of thoughtful work.
> Actually I did run some tests already with your previously posted
> hotfix based on v3. I didn't update the result because very
> unfortunately, I still see a major performance regression even with a
> very simple setup.
>
> BTW there seems a simpler way to reproduce that, just use memhog:
> sudo mkswap /dev/pmem0; sudo swapon /dev/pmem0; time memhog 48G; sudo swapoff -a
>
> Before:
> (I'm using fish shell on that test machine so this is fish time format):
> ________________________________________________________
> Executed in   20.80 secs    fish           external
>    usr time    5.14 secs    0.00 millis    5.14 secs
>    sys time   15.65 secs    1.17 millis   15.65 secs
> ________________________________________________________
> Executed in   21.69 secs    fish           external
>    usr time    5.31 secs  725.00 micros    5.31 secs
>    sys time   16.36 secs  579.00 micros   16.36 secs
> ________________________________________________________
> Executed in   21.86 secs    fish           external
>    usr time    5.39 secs    1.02 millis    5.39 secs
>    sys time   16.46 secs    0.27 millis   16.46 secs
>
> After:
> ________________________________________________________
> Executed in   30.77 secs    fish           external
>    usr time    5.16 secs  767.00 micros    5.16 secs
>    sys time   25.59 secs  580.00 micros   25.59 secs
> ________________________________________________________
> Executed in   37.47 secs    fish           external
>    usr time    5.48 secs    0.00 micros    5.48 secs
>    sys time   31.98 secs  674.00 micros   31.98 secs
> ________________________________________________________
> Executed in   31.34 secs    fish           external
>    usr time    5.22 secs    0.00 millis    5.22 secs
>    sys time   26.09 secs    1.30 millis   26.09 secs
>
> It's obviously a lot slower.
>
> pmem may seem rare but SSDs are good at sequential, and memhog uses
> the same filled page and backend like ZRAM has extremely low overhead
> for same filled pages. Results with ZRAM are very similar, and many
> production workloads have massive amounts of samefill memory.
>
> For example on the Android phone I'm using right now at this moment:
> # cat /sys/block/zram0/mm_stat
> 4283899904 1317373036 1370259456        0 1475977216   116457  1991851
>    87273  1793760
> ~450M of samefill page in ZRAM, we may see more on some server
> workload. And I'm seeing similar memhog results with ZRAM, pmem is
> just easier to setup and less noisy. also simulates high speed
> storage.

Interesting. Normally "lots of zero-filled page" is a very beneficial
case for vswap. You don't need a swapfile, or any zram/zswap metadata
overhead - it's a native swap backend. If production workload has this
many zero-filled pages, I think the numbers of vswap would be much
less alarming - perhaps even matching memory overhead because you
don't need to maintain a zram entry metadata (it's at least 2 words
per zram entry right?), while there's no reverse map overhead induced
(so it's 24 bytes on both side), and no need to do zram-side locking
:)

So I was surprised to see that it's not working out very well here. I
checked the implementation of memhog - let me know if this is wrong
place to look:

https://man7.org/linux/man-pages/man8/memhog.8.html
https://github.com/numactl/numactl/blob/master/memhog.c#L52

I think this is what happened here: memhog was populating the memory
0xff, which triggers the full overhead of a swapfile-backed swap entry
because even though it's "same-filled" it's not zero-filled! I was
following Usama's observation - "less than 1% of the same-filled pages
were non-zero" - and so I only handled the zero-filled case here:

https://lore.kernel.org/all/20240530102126.357438-1-usamaarif642@gmail.com/

This sounds a bit artificial IMHO - as Usama pointed out above, I
think most samefilled pages are zero pages, in real production
workloads. However, if you think there are real use cases with a lot
of non-zero samefilled pages, please let me know I can fix this real
quick. We can support this in vswap with zero extra metadata overhead
- change the VSWAP_ZERO swap entry type to VSWAP_SAME_FILLED, then use
the backend field to store that value. I can send you a patch if
you're interested.

>
> I also ran the previous usemem matrix, which seems better than V3 but
> still pretty bad:
> Test: usemem --init-time -O -n 1 56G, 16G mem, 48G swap, avgs of 8 run.
> Before:
> Throughput (Sum): 528.98 MB/s Throughput (Mean): 526.113333 MB/s Free
> Latency: 3037932.888889
> After:
> Throughput (Sum): 453.74 MB/s Throughput (Mean): 454.875000 MB/s Free
> Latency: 5001144.500000 (~10%, 64% slower)
>
> I'm not sure why our results differ so much — perhaps different LRU
> settings, memory pressure ratios, or THP/mTHP configs? Here's my exact
> config in the attachment. Also includes the full log and info, with
> all debug options disabled for close to production. I ran it 8 times
> and just attached the first result log, it's all similar anyway, my
> test framework reboot the machine after each test run to reduce any
> potential noise.

Ohh interesting - I see that you're testing with MGLRU. I can give that a try.

I'm not enabling THP/mTHP, but I don't see that you're enabling it
either - there's some 2MB swpout but that seems incidental.

Another difference is the swap backend:

1. Regarding pmem backend - I'm not sure if I can get my hands on one
of these, but if you think SSD has the same characteristics maybe I
can give that a try? The problem with SSD is for some reason variance
tends to be pretty high, between iterations yes, but especially across
reboots. Or maybe zram?

2. What about the other numbers below? Are they also on pmem? FTR I
was running most of my benchmarks on zswap, except for one kernel
build benchmark on SSD.

3. Any other backends and setup you're interested in?

BTW, sounds like you have a great benchmark suite - is it open source
somewhere? If not, can you share it with us :) Vswap aside, I think
this would be a good suite to run all swap related changes for every
swap contributor.

Once again, thank you so much for your engagement, Kairui. Very much
appreciated - I owe you a beverage of your choice whenever we meet.
And have a great rest of your day :)

^ permalink raw reply

* [PATCH v1] ACPI: TAD: Use DC wakeup only if AC wakeup is supported
From: Rafael J. Wysocki @ 2026-03-23 15:26 UTC (permalink / raw)
  To: Linux ACPI; +Cc: LKML, Linux PM

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

According to Section 9.17.2 of ACPI 6.6 [1], setting ACPI_TAD_DC_WAKE in
the capabilities without setting ACPI_TAD_AC_WAKE is invalid, so don't
support wakeup if that's the case.

Moreover, it is sufficient to check ACPI_TAD_AC_WAKE alone to determine
if wakeup is supported at all, so use this observation to simplify one
check.

Link: https://uefi.org/specs/ACPI/6.6/09_ACPI_Defined_Devices_and_Device_Specific_Objects.html#gcp-get-capability [1]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---

This change is on top of linux-next.

---
 drivers/acpi/acpi_tad.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- a/drivers/acpi/acpi_tad.c
+++ b/drivers/acpi/acpi_tad.c
@@ -706,6 +706,9 @@ static int acpi_tad_probe(struct platfor
 		caps &= ~(ACPI_TAD_AC_WAKE | ACPI_TAD_DC_WAKE);
 	}
 
+	if (!(caps & ACPI_TAD_AC_WAKE))
+		caps &= ~ACPI_TAD_DC_WAKE;
+
 	dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL);
 	if (!dd)
 		return -ENOMEM;
@@ -719,7 +722,7 @@ static int acpi_tad_probe(struct platfor
 	 * runtime suspend.  Everything else should be taken care of by the ACPI
 	 * PM domain callbacks.
 	 */
-	if (ACPI_TAD_AC_WAKE | ACPI_TAD_DC_WAKE) {
+	if (ACPI_TAD_AC_WAKE) {
 		device_init_wakeup(dev, true);
 		dev_pm_set_driver_flags(dev, DPM_FLAG_SMART_SUSPEND |
 					     DPM_FLAG_MAY_SKIP_RESUME);




^ permalink raw reply

* Re: [PATCH] PM: hibernate: call preallocate_image after freeze prepare
From: YoungJun Park @ 2026-03-23 15:23 UTC (permalink / raw)
  To: Matthew Leach
  Cc: Rafael J. Wysocki, Pavel Machek, Len Brown, Mario Limonciello,
	linux-pm, linux-kernel, kernel
In-Reply-To: <20260321-hibernation-fixes-v1-1-5fe9637b6ff9@collabora.com>

On Sat, Mar 21, 2026 at 08:51:31AM +0000, Matthew Leach wrote:

Hi Matthew,

> +     /* Preallocate image memory before shutting down devices. */
> +     error = hibernate_preallocate_memory();

The shrink_shmem_memory() below is also intended to run after
dpm_prepare(), and the motivation is the same. Since
hibernate_preallocate_memory() already does shrinking internally,
how about pulling out the shrink-related parts and consolidating
them together?

> +     if (error)
> +             goto Thaw;

Don't we need to call dpm_complete(PMSG_RECOVER) in this error path?

>  Thaw:
>       thaw_kernel_threads();
> - Cleanup:
> -     swsusp_free();
>       goto Close;

Thanks,
Youngjun Park

^ permalink raw reply

* Re: [PATCH v6 6/9] dt-bindings: connector: m2: Add M.2 1620 LGA soldered down connector
From: Dmitry Baryshkov @ 2026-03-23 15:14 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Rob Herring, Manivannan Sadhasivam, Greg Kroah-Hartman,
	Jiri Slaby, Nathan Chancellor, Nicolas Schier, Hans de Goede,
	Ilpo Järvinen, Mark Pearson, Derek J. Clark,
	Krzysztof Kozlowski, Conor Dooley, Marcel Holtmann,
	Luiz Augusto von Dentz, Bartosz Golaszewski, Andy Shevchenko,
	Bartosz Golaszewski, linux-serial, linux-kernel, linux-kbuild,
	platform-driver-x86, linux-pci, devicetree, linux-arm-msm,
	linux-bluetooth, linux-pm, Stephan Gerhold, linux-acpi
In-Reply-To: <6aef3xxjjd4nbgrfx6jc6jt6rpqmttoui6hil5zqgdpas2j6gj@ie6j72orenou>

On Mon, Mar 23, 2026 at 07:14:25PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Mar 23, 2026 at 08:39:55AM -0500, Rob Herring wrote:
> > On Mon, Mar 23, 2026 at 7:16 AM Manivannan Sadhasivam <mani@kernel.org> wrote:
> > >
> > > On Sun, Mar 22, 2026 at 06:37:13PM -0500, Rob Herring wrote:
> > > > On Tue, Mar 17, 2026 at 09:59:56AM +0530, Manivannan Sadhasivam wrote:
> > > > > Lenovo Thinkpad T14s is found to have a soldered down version of M.2 1620
> > > > > LGA connector. Though, there is no 1620 LGA form factor defined in the M.2
> > > > > spec, it looks very similar to the M.2 Key E connector. So add the
> > > > > "pcie-m2-1620-lga-connector" compatible with "pcie-m2-e-connector" fallback
> > > > > to reuse the Key E binding.
> > > >
> > > > What is LGA?
> > > >
> > >
> > > Land Grid Array
> > >
> > > > If not in the spec, is it really something generic?
> > > >
> > >
> > > Good question. Yes and No! LGA is not something that Lenovo only uses. Other
> > > vendors may also use this form factor. PCIe connectors are full of innovation as
> > > the spec gives room for hardware designers to be as innovative as possible to
> > > save the BOM cost.
> > 
> > innovation == incompatible changes
> > 
> 
> Yes, I was trying to sound nice :)
> 
> > > This is why I do not want to make it Lenovo specific. But if you prefer that, I
> > > can name it as "lenovo,pcie-m2-1620-lga-connector".
> > 
> > Depends if you think that s/w needs to know the differences. Hard to
> > say with a sample size of 1.
> > 
> 
> Sure. Will add the 'lenovo' prefix then.

Is it really Lenovo? Or is it some other module vendor, whose LGAs are
being used by Lenovo?

I remember that DB820c also used some kind of a module for the WiFi card
(which might be M.2 compatible or might not, I can't find exact docs at
this point).

-- 
With best wishes
Dmitry

^ 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