Fix multple issues with hid-lenovo-go-s - #15
Open
pastaq wants to merge 512 commits into
Open
Conversation
Commit 2bee308 ("selftests/mm: use pattern matching in .gitignore") switched to a pattern-matching mechanism to reduce churn in .gitignore. It however accidentally excluded the page_frag test's-generated module intermediate C file with .mod.c extension, and also the local_config.h header generated if liburing is available locally. Explicitly fix both the issues, fixing the module-generated C file as a general pattern as these are always intermediate files that should be ignored. Since this is a trivial .gitignore change it doesn't seem necessary to treat it as a hotfix. Link: https://lore.kernel.org/20260831-fix-mm-selftests-gitignore-v1-1-c984bbd4c5e4@kernel.org Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Reviewed-by: Gregory Price (Meta) <gourry@gourry.net> Cc: David Hildenbrand <david@kernel.org> Cc: Liam R. Howlett <liam@infradead.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "mm: Unconditional per-VMA locks and cleanups", v7.
tl;dr: Make per-VMA locks available in all configs. Simplify some of the
per-VMA lock users now that they can rely on them being always available.
Binder and networking folks: Your code is the target of the cleanups. I'm
cc'ing you now on v2 because there's emerging consensus on the mm side
that the approach here is sane. I'm not quite sure how this pile would
get merged, but ack/review tags would be appreciated if this looks good to
you.
Longer version:
When working on some x86 shadow stack code, it was a real pain to avoid
causing recursive locking problems with mmap_lock. One way to avoid those
was to avoid mmap_lock and use per-VMA locks instead. They are great, but
they are not available in all configs which makes them unusable in generic
code, or if you want to completely avoid mmap_lock.
Make per-VMA locks available in all configs. Right now, they are only
available on select architectures when SMP and MMU are enabled. But all
of the primitives that per-VMA locks are built on (RCU, maple trees,
refcounts) work just fine without SMP or MMU.
The only real downside is that making VMAs a wee bit bigger on !MMU and
!SMP builds.
The upside is much cleaner code, lower complexity and less #ifdeffery.
Clean up a binder VMA locking site now that it can rely on per-VMA locks.
Building on top of universally-available per-VMA locks, introduce a new
helper. Since the new API does not require callers to have a fallback to
mmap_lock, it's much easier to use. Callers can potentially replace this
very common kernel idiom:
mmap_read_lock(mm);
vma = vma_lookup()
// fiddle with vma
mmap_read_unlock(mm);
with:
vma = vma_start_read_unlocked(mm, address);
// fiddle with vma
vma_end_read(vma);
Which avoids mmap_lock entirely in the fast path.
Use that new API for another binder site and one in the TCP code.
This patch (of 7):
The per-VMA locks have been around for several years. They've had some
bugs worked out of them and have seen quite wide use. However, they are
still only available when architectures explicitly enable them. Remove
the conditional compilation around the per-VMA locks, making them
available on all architectures and configs.
The approach up to now seemed to be to add ARCH_SUPPORTS_PER_VMA_LOCK when
the architecture started using per-VMA locks in the fault handler. But,
contrary to the naming, the Kconfig option does not really indicate
whether the architecture supports per-VMA locks or not. It is more of a
marker for whether the architecture is likely to benefit from per-VMA
locks.
To me, the most important thing side-effect of universal availability is
letting per-VMA locks be used in SMP=n configs. This lets us use
per-VMA locking in all x86 code without fallbacks.
Overall, this just generally makes the kernel simpler. Just look at the
diffstat. It also opens the door to users that want to use the per-VMA
locks in common code. Doing *that* brings additional simplifications.
The downside of this is adding some fields to vm_area_struct and
mm_struct. There are likely ways to optimize this, especially for things
like SMP=n configs. For now, do the simplest thing: use the same
implementation everywhere.
== Considerations for NOMMU config ==
NOMMU systems do not write-lock VMAs, therefore read-locking a VMA would
always succeed unless VMA is detached. Therefore for NOMMU config we make
vma_mark_attached() a NOOP, which keeps VMAs always in detached state.
This causes VMA read-locking to always fail and the caller falls back to
locking mmap_lock.
The following functions will have a different implementation in NOMMU
config:
- vma_mark_attached(), vma_mark_detached() are made NOOPs, keeping VMAs
always in a detached state and preventing assertions and refcount
underflows;
- vma_start_write(), vma_start_write_killable() are made NOOPs to avoid
warnings in __vma_start_write() due to VMAs being detached. These
functions are not used in NOMMU code but __vma_start_write() is an
exported function, therefore might be used by drivers.
- vma_assert_attached() is made NOOP because it's reachable from NOMMU
code via split_vma()->vma_iter_store_new()->vma_iter_store_overwrite();
- vma_assert_write_locked() is asserting vma->vm_mm is write-locked, as
was done before this change;
- vma_assert_locked() is asserting vma->vm_mm is locked, as was done
before this change;
The following functions work for both MMU and NOMMU configs:
- vma_lock_init() performs the same initialization as for MMU config;
- mm_lock_seqcount_init(), mm_lock_seqcount_begin(),
mm_lock_seqcount_end() are called from mmap_write_{lock|unlock} and
update mm_lock_seq correctly.
- mmap_lock_speculate_try_begin(), mmap_lock_speculate_retry() work as
is because mm_lock_seq is updated correctly;
- vma_start_read(), vma_start_read_locked() will always fail because
VMAs are always detached;
- vma_end_read() will never be called because vma_start_read() never
succeeds;
- vma_is_attached() always return false because VMAs are always
detached;
- vma_assert_detached() will never trigger because VMAs are never
attached;
- vma_start_read_locked() always return false because VMAs are always
detached;
- lock_vma_under_rcu() will be safe as the attempted read lock will bail;
Changes in the following files are not affecting NOMMU config:
task_mmu.c - not compiled when CONFIG_MMU=n;
pagewalk.c - not compiled when CONFIG_MMU=n;
userfaultfd.c - not compiled when CONFIG_MMU=n (CONFIG_USERFAULTFD depends
on CONFIG_MMU);
The following changes in the BPF code are made to keep NOMMU config
working like before:
stack_map_lock_vma() - keeps mmap_lock in NOMMU config;
bpf_iter_task_vma_new() - bails out in NOMMU config;
Link: https://lore.kernel.org/20260831203056.838265-1-surenb@google.com
Link: https://lore.kernel.org/20260831203056.838265-2-surenb@google.com
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Todd Kjos <tkjos@android.com>
Cc: Christian Brauner <christian@brauner.io>
Cc: Carlos Llamas <cmllamas@google.com>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: David Ahern <dsahern@kernel.org>
Cc: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
tl;dr: lock_vma_under_rcu() is already a trylock. No need to do both it and mmap_read_trylock(). Long Version: == Background == Historically, binder used an mmap_read_trylock() in its shrinker code. This ensures that reclaim is not blocked on an mmap_lock. Commit 95bc2d4 ("binder: use per-vma lock in page reclaiming") added support for the per-VMA lock, but left mmap_read_trylock() as a fallback. This was presumably because the per-VMA locking can fail for several reasons and most (all?) lock_vma_under_rcu() callers have a fallback to mmap_read_trylock(). == Problem == The fallback is not worth the complexity here. lock_vma_under_rcu() is essentially already a non-blocking trylock. The main reason it fails is also the reason mmap_read_trylock() fails: something is holding mmap_write_lock(). The only remedy for a collision with mmap_write_lock() is to wait, which this code can not do. So the "fallback" after lock_vma_under_rcu() failure is not really a fallback: it is really likely to just be retrying in vain. That retry in an of itself isn't horrible. But it adds complexity. == Solution == Now that per-VMA locks are universally available, lock_vma_under_rcu() will not persistently fail. Rely on it alone and simplify the code. The removal of the fallback does not affect NOMMU case because binder driver depends on CONFIG_MMU. While at it we also make the handling of the cases where the original binder VMA is gone consistent. There are two cases to consider when Binder VMA is gone: 1. there is no VMA at that location anymore. 2. there is now another unrelated VMA at that location. Before this change we handle case 1 by having the shrinker proceed to free the page, and just skip the zap_vma_range() call. And we handle case 2 by having the shrinker return LRU_SKIP. While either behavior is acceptable, we need to handle them in a consistent way. Handle both cases by freeing the page without touching the VMA (skipping the zap_vma_range()). Full disclosure: I originally tried to do this with lock_vma_under_rcu_wait(), but it did not fit well with the mmap_lock trylock semantics. Claude caught this in a review and suggested the approach in this path. It seemed sane to me. So, Suggesed-by: Claude, I guess. Link: https://lore.kernel.org/20260831203056.838265-3-surenb@google.com Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Suren Baghdasaryan <surenb@google.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Acked-by: Carlos Llamas <cmllamas@google.com> Cc: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Todd Kjos <tkjos@android.com> Cc: Christian Brauner <christian@brauner.io> Cc: David S. Miller <davem@davemloft.net> Cc: David Ahern <dsahern@kernel.org> Cc: Arve Hjønnevåg <arve@android.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
There are basically two parallel ways to look up a VMA: the traditional way, which is protected by mmap_read_lock, and the RCU-based per-VMA lock way which is based on RCU and refcounts. However, per-VMA locks will fail if the lock is help by a writer and therefore never waits. In a number of places we need to wait for the lock and it's done by falling back to mmap_read_lock, locking the VMA and releasing the mmap_lock once VMA is locked. Add vma_start_read_unlocked() - a variant of the RCU-based lookup that waits for writers. This is basically the same as the existing RCU-based lookup, but on a failure to lock it temporarily takes mmap_lock for read and waits for writers to finish before locking the VMA, dropping the mmap_read_lock and returning the locked VMA. This has some advantages: 1. Callers do not need to have a fallback path for when they collide with writers. 2. Its fast path does not require taking mmap_lock for read. Basically, when applied correctly, this approach results in faster *and* simpler code. While at it, fix the comments for vma_start_read_locked(), vma_start_read_locked_nested(), and uffd_lock_vma(). Link: https://lore.kernel.org/20260831203056.838265-4-surenb@google.com Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Suren Baghdasaryan <surenb@google.com> Suggested-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Cc: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Todd Kjos <tkjos@android.com> Cc: Christian Brauner <christian@brauner.io> Cc: Carlos Llamas <cmllamas@google.com> Cc: Alice Ryhl <aliceryhl@google.com> Cc: David S. Miller <davem@davemloft.net> Cc: David Ahern <dsahern@kernel.org> Cc: Arve Hjønnevåg <arve@android.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Previously, the per-VMA locking could fail in the face of writers which necessitate a fallback to mmap_lock. The new vma_start_read_unlocked() will wait for writers instead of failing. Use the new helper. Wait for writers. Remove the fallback to mmap_lock. Link: https://lore.kernel.org/20260831203056.838265-5-surenb@google.com Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Suren Baghdasaryan <surenb@google.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org> Cc: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Todd Kjos <tkjos@android.com> Cc: Christian Brauner <christian@brauner.io> Cc: Carlos Llamas <cmllamas@google.com> Cc: Alice Ryhl <aliceryhl@google.com> Cc: David S. Miller <davem@davemloft.net> Cc: David Ahern <dsahern@kernel.org> Cc: Arve Hjønnevåg <arve@android.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Previously, the per-VMA locking could fail in the face of writers which necessitates a fallback to mmap_lock. The new vma_start_read_unlocked() will wait for writers instead of failing. Use the new helper. Wait for writers. Remove the fallback to mmap_lock. The fallback removal does not affect NOMMU case because TCP_ZEROCOPY is gated on CONFIG_MMU. This really is a nice cleanup. It removes the need to pass the lock state back and forth to find_tcp_vma(). Link: https://lore.kernel.org/20260831203056.838265-6-surenb@google.com Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Signed-off-by: Suren Baghdasaryan <surenb@google.com> Acked-by: Lorenzo Stoakes <ljs@kernel.org> Acked-by: Vlastimil Babka (SUSE) <vbabka@kernel.org> Tested-by: syzbot@syzkaller.appspotmail.com Cc: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Vlastimil Babka <vbabka@kernel.org> Cc: Shakeel Butt <shakeel.butt@linux.dev> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Arve Hjønnevåg <arve@android.com> Cc: Todd Kjos <tkjos@android.com> Cc: Christian Brauner <christian@brauner.io> Cc: Carlos Llamas <cmllamas@google.com> Cc: Alice Ryhl <aliceryhl@google.com> Cc: David S. Miller <davem@davemloft.net> Cc: David Ahern <dsahern@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Charges that exceed memory.max and return through the nomem label can raise no event and simply return -ENOMEM. A non-blocking charge can hit the limit, get rejected, but is not visible in memory.events. This was noticed in a production setting where bpf_mem_alloc() attempted to refill its per-cpu freelists, which triggered a non-blocking charge while at the limit. Commit d6e103a ("mm: memcontrol: do not miss MEMCG_MAX events for enforced allocations") added raised_max_event to cover charges that are force charged without ever reaching reclaim, but charges that are rejected outright were left out. Getting an allocation failure without the corresponding MEMCG_MAX event is unexpected and makes debugging and monitoring harder. Raise the event on the way out for rejected charges as well, by routing the -ENOMEM return through the same exit path that already covers forced charges. The existing behavior of raising a MEMCG_MAX event on every charge/reclaim/retry iteration is left unchanged. Tested with a module that performs accounted GFP_NOWAIT page allocations from a task in a cgroup at its memory.max, and measures the resulting memory.events:max delta. Without this patch the rejected charges raise no event at all; with it the delta matches the number of rejected charges exactly. A GFP_KERNEL|__GFP_NORETRY control, which reaches reclaim, raises the same two events per failed charge before and after, confirming the existing charge/reclaim/retry accounting is unchanged. Link: https://lore.kernel.org/20260831174836.3102406-1-joe@dama.to Fixes: d6e103a ("mm: memcontrol: do not miss MEMCG_MAX events for enforced allocations") Signed-off-by: Joe Damato <joe@dama.to> Suggested-by: Shakeel Butt <shakeel.butt@linux.dev> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "mm/damon: add kunit tests for probe_hits handling and probe params validation", v2. DAMON recently introduced probes and probe weights. Add kunit tests for the propagation of probe_hits at region split and merge, and the rejection of invalid probe parameters by damon_valid_probe_params(). This patch (of 2): damon_split_region_at() copies probe_hits[] and last_probe_hits[] to the new split region. damon_merge_two_regions() sets probe_hits[] to the size-weighted average of the merged regions. Extend damon_test_split_at() and damon_test_merge_two() tests to cover those fields. Link: https://lore.kernel.org/20260831150650.84829-1-sj@kernel.org Link: https://lore.kernel.org/20260831150650.84829-2-sj@kernel.org Signed-off-by: Jason Angelov <jasonangelov@ucla.edu> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Gow <davidgow@davidgow.net> Cc: Brendan Higgins <brendan.higgins@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
damon_valid_probe_params() makes damon_commit_ctx() reject probe configurations that could overflow a probe_hits counter, a single (weight * probe_hits) product, or the sum of those products. Add a kunit test covering each rejection at its boundary: - samples per aggregation interval: U8_MAX is allowed, one more could overflow a probe_hits counter - single weight: the largest whose product fits in unsigned int is allowed, one larger is rejected - multiple probes: each product fits, but their sum overflows - no weight set: the validation is skipped Link: https://lore.kernel.org/20260831150650.84829-3-sj@kernel.org Signed-off-by: Jason Angelov <jasonangelov@ucla.edu> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Brendan Higgins <brendan.higgins@linux.dev> Cc: David Gow <davidgow@davidgow.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "docs/mm/damon/design: add explanation of nr_snapshots", v3. Add an explanation of nr_snapshots to avoid misunderstandings. This patch (of 3): Change "tried to be applied" -> "completely tried to be applied" to maintain consistency between the documentation and the code. Link: https://lore.kernel.org/20260831150227.83416-1-sj@kernel.org Link: https://lore.kernel.org/20260831150227.83416-2-sj@kernel.org Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Explain the difference between nr_snapshots reaches max_nr_snapshots and watermarks. Link: https://lore.kernel.org/20260831150227.83416-3-sj@kernel.org Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Fix a typo (nr_snapshots -> max_nr_snapshots) and corrects a grammar error. Link: https://lore.kernel.org/20260831150227.83416-4-sj@kernel.org Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "mm/damon/core: remove unused helper functions", v2. Both damon_targets_empty() and damon_nr_running_ctxs() have had no in-tree users since commit 5ec4333 ("mm/damon: remove DAMON debugfs interface") removed their remaining callers. Remove the unused declarations and definitions. This patch (of 2): damon_targets_empty() has had no in-tree users since commit 5ec4333 ("mm/damon: remove DAMON debugfs interface") removed its last caller. Remove the unused declaration and definition. Link: https://lore.kernel.org/20260831145724.82387-1-sj@kernel.org Link: https://lore.kernel.org/20260831145724.82387-2-sj@kernel.org Signed-off-by: Cheng-Han Wu <hank20010209@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
damon_nr_running_ctxs() has had no in-tree users since commit 5ec4333 ("mm/damon: remove DAMON debugfs interface") removed all of its callers. Remove the unused declaration and definition. Link: https://lore.kernel.org/20260831145724.82387-3-sj@kernel.org Signed-off-by: Cheng-Han Wu <hank20010209@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "mm/damon: Introduce a huge page collapsing mechanism using auto tuning", v4. Overview ======== This patchset introduces a new autotuning which allows to collapse hot regions into hugepages. Motivation ========== Since TLB is a bottleneck for many systems[1], a way to optimize TLB misses (or hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory fragmentation and memory waste. For this reason, most application guides and system administrators suggest to disable THP. Selective huge page collapse per process is possible using prctl and a launcher. However, this does not solve the issue with hot region detection. Additionally, it the sysadmin should create a launcher that uses PRCTL to enable THP for a particular process. We can use the DAMON support for DAMOS_HUGEPAGE and DAMOS_COLLAPSE, to target a certain process. DAMOS_COLLAPSE can also target the hot regions in that process. Still, there is an issue with the amount of huge page consumption. Since huge pages can lead to memory fragmentation and waste, there should be a way to limit the amount of huge page consumption. There is hugetlbfs, but it requires changes to the application code or the use of libhugetlbfs. DAMON has now a way to autotune some of the variables and adjust quotas automatically, so that DAMON is fired only under the right circumstances. It would be nice to have something similar, but for huge pages. Solution ======== A new autotuning quota goal[2], damos_hugepage_mem_bp, is introduced, which checks the huge page consumption to total memory consumption. This new quota mechanism reuses current autotuning architecture. In order to test this new mechanism, a sample module[3] was created, but not included in this patch series. To demonstrate the tool, damo user space tool was modified[4], which sets up huge pages collapse autotuning. Benchmarks ========== Setup: physical server with arm64 processor with 4 NUMA nodes, 1 TB RAM and running mariaDB 10.5.29. Sysbench was used for the benchmark, with 20 tables and 3 million rows per table. The database was pinned to one of the nodes, and the benchmark framework to a different node. No network traffic involved in the benchmark. Damo user space tool was forked and hugepage_mem_bp support added[4]. DAMON was lauched using this command line: sudo ./damo start $(pidof mariadbd) \ --monitoring_nr_regions_range 10 1000 \ --monitoring_intervals 5000 100000 60000000 \ --damos_quota_time 0 --damos_quota_space 128000000 \ --damos_quota_interval 1000 \ --damos_quota_weights 0 1 1 \ --damos_quota_goal hugepage_mem_bp <target> \ --damos_quota_goal_tuner temporal \ --damos_apply_interval 50000 \ --damos_access_rate 0 max --damos_age 50 max \ --damos_action collapse --debug_damon <target> was 1000 to taget 10% hugepage to total memory ratio, or 2500 to target 25%. Tuner was also tested with consistent and temporal. Results ======= After the last timestamp, there was no change in huge page use, and the total huge page to memory consumption ratio barely moved. hugepage_mem_bp: 1000 goal tuner: temporal +-----------+----------------+----------------+----------------------+ | timestamp | total mem used | huge page used | percentage hugepage | +-----------+----------------+----------------+----------------------+ | 0 | 16945.04297 | 0 | 0 | | 7 | 17008.69531 | 74 | 0.435071583 | | 8 | 17036.40234 | 194 | 1.138738074 | | 9 | 17017.01563 | 314 | 1.845211916 | | 10 | 17029.67969 | 434 | 2.548491856 | | 61 | 17111.30859 | 584 | 3.412947623 | | 120 | 17071.05859 | 694 | 4.065360072 | | 180 | 17133.88281 | 804 | 4.692456513 | | 203 | 17088.16406 | 916 | 5.360435426 | | 204 | 17126.34766 | 1046 | 6.107548562 | | 205 | 17093.84375 | 1176 | 6.879669764 | | 206 | 17142.77734 | 1298 | 7.571701913 | | 209 | 17149.17969 | 1686 | 9.831374041 | | 210 | 17097.30859 | 1754 | 10.25892462 | +-----------+----------------+----------------+----------------------+ hugepage_mem_bp: 1000 goal tuner: consistent +-----------+----------------+----------------+----------------------+ | timestamp | total mem used | huge page used | percentage hugepage | +-----------+----------------+----------------+----------------------+ | 0 | 16955.24609 | 0 | 0 | | 34 | 17039.71875 | 106 | 0.622075995 | | 78 | 17009.47656 | 554 | 3.257007927 | | 90 | 17048.92188 | 596 | 3.495822225 | | 150 | 17092.90625 | 706 | 4.130368409 | | 180 | 17053.08984 | 764 | 4.480126517 | | 233 | 17100.50391 | 1496 | 8.748280216 | | 239 | 17098.89063 | 2216 | 12.95990511 | | 240 | 17135.44531 | 2334 | 13.62088908 | | 245 | 17132.55078 | 2932 | 17.11362212 | | 246 | 17117.95313 | 3052 | 17.82923448 | | 250 | 17163.12109 | 3532 | 20.57900763 | +-----------+----------------+----------------+----------------------+ hugepage_mem_bp: 2500 goal tuner: temporal +-----------+----------------+----------------+----------------------+ | timestamp | total mem used | huge page used | percentage hugepage | +-----------+----------------+----------------+----------------------+ | 0 | 17010.31641 | 0 | 0 | | 9 | 17063.6875 | 50 | 0.2930199 | | 10 | 17051.75781 | 170 | 0.996964664 | | 60 | 17133.85547 | 572 | 3.338419663 | | 90 | 17192.07813 | 626 | 3.641211932 | | 120 | 17221.44531 | 682 | 3.960178647 | | 181 | 17199.76172 | 790 | 4.593086886 | | 208 | 17222.77734 | 1206 | 7.002354939 | | 214 | 17245.17969 | 1904 | 11.04076637 | | 215 | 17240.45703 | 2024 | 11.73982799 | | 220 | 17234.79688 | 2624 | 15.22501262 | | 228 | 17222.83594 | 3584 | 20.80958103 | | 231 | 17247.55469 | 3944 | 22.86700968 | | 235 | 17229.37109 | 4424 | 25.67708349 | +-----------+----------------+----------------+----------------------+ hugepage_mem_bp: 1000 goal tuner: consist +-----------+----------------+----------------+----------------------+ | timestamp | total mem used | huge page used | percentage hugepage | +-----------+----------------+----------------+----------------------+ | 0 | 17125.85156 | 0 | 0 | | 38 | 17081.23438 | 76 | 0.444932716 | | 39 | 17133.11719 | 196 | 1.143983304 | | 40 | 17119.83984 | 316 | 1.84581166 | | 60 | 17109.72656 | 554 | 3.237924335 | | 90 | 17164.11328 | 628 | 3.65879664 | | 180 | 17177.66016 | 792 | 4.610639591 | | 220 | 17180.86719 | 1378 | 8.020549749 | | 226 | 17187.82031 | 1980 | 11.51978531 | | 233 | 17143.48438 | 2818 | 16.4377319 | | 240 | 17137.38281 | 3656 | 21.33347921 | | 250 | 17175.5 | 4856 | 28.27283049 | | 260 | 17199.66406 | 6056 | 35.20999002 | | 270 | 17203.98438 | 7254 | 42.16465118 | | 275 | 17207.21875 | 7762 | 45.10897498 | +-----------+----------------+----------------+----------------------+ More detailed tables are provided here[5] From this, we can conclude that the huge page autotuner works fine, achieving the target. When using consistent autotuner, it actually over-achieves the target, which is expected, since quota esz_bp is not set to 0 to cap the DAMOS policy. Patches Sequence ================ Patch 1 -> Introduce DAMOS_QUOTA_HUGEPAGE_MEM_BP and autotuning Patch 2 -> sysfs support for the new quota goal Patch 3 -> Document hugepage_mem_bp parameter This patch (of 3): Introduce DAMOS_QUOTA_HUGEPAGE_MEM_BP auto tuning. Add a new DAMOS quota goal metric to measure the amount of huge page consumption to total memory consumption ratio. Vmstat may lag, which in some cases may lead to NR_FREE_PAGES being greater than or equal to the amount of RAM in the system. A guard is added to avoid the extremely unlikely case [6]. In the case, return 100% (10000 bp). Link: https://lore.kernel.org/20260831144732.80910-1-sj@kernel.org Link: https://lore.kernel.org/20260831144732.80910-2-sj@kernel.org Link: https://dl.acm.org/doi/pdf/10.1145/3307650.3322227 [1] Link: https://lore.kernel.org/e67f05ad-dbb9-45e6-ba30-b167a99ac67d@huawei-partners.com [2] Link: https://lore.kernel.org/20260616150316.580819-3-gutierrez.asier@huawei-partners.com [3] Link: asierHuawei/damo@79ae1a4 [4] Link: https://lore.kernel.org/all/03f678dd-9ef3-4b97-b753-c2e4554c5159@huawei-partners.com/ [5] Link: https://lore.kernel.org/all/20260715151615.99767-1-sj@kernel.org/ [6] Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
DAMOS has a new autotune policy metric: DAMOS_QUOTA_HUGEPAGE_MEM_BP. This patch exposes DAMOS_QUOTA_HUGEPAGE_MEM_BP through sysfs. Add the "hugepage_mem_bp" to the sysfs-schemes interface. Link: https://lore.kernel.org/20260831144732.80910-3-sj@kernel.org Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Document hugepage_mem_bp metric exposed by sysfs. Link: https://lore.kernel.org/20260831144732.80910-4-sj@kernel.org Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Liam R. Howlett <liam@infradead.org> Cc: Lorenzo Stoakes <ljs@kernel.org> Cc: Michal Hocko <mhocko@suse.com> Cc: Mike Rapoport <rppt@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "mm/damon: misc cleanups". Cleanup the code, tests and samples for clarifications and readability. The patches are individually sent by the authors. I'm reposting those as one series for convenience of handling. For this reason, changelog is on each patch's commentary section. This patch (of 7): __damon_commit_ctx() was added by commit b1471af ("mm/damon/core: do parameter testing commit on damon_start()") but is actually not needed. Remove it. Link: https://lore.kernel.org/20260831142611.77572-1-sj@kernel.org Link: https://lore.kernel.org/20260831142611.77572-2-sj@kernel.org Signed-off-by: Zenghui Yu (Huawei) <zenghui.yu@linux.dev> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Shuah Khan <shuah@kernel.org> Cc: Zenghui Yu <zenghui.yu@linux.dev> Cc: Enze Li <lienze@kylinos.cn> Cc: Hari Mishal <harimishal1@gmail.com> Cc: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Cc: Li Youhong <liyouhong@kylinos.cn> Cc: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
The logic that finds the struct pid for a given pid number and assigns it to a damon_target is duplicated in multiple places. Including damon_sysfs_add_target() of mm/damon/sysfs.c and the start functions of the two sample modules, samples/damon/wsse.c and samples/damon/prcl.c. Add a function that does the work, and replace the duplicated code in the places with calls to the function. Link: https://lore.kernel.org/20260831142611.77572-3-sj@kernel.org Signed-off-by: Enze Li <lienze@kylinos.cn> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Hari Mishal <harimishal1@gmail.com> Cc: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Cc: Li Youhong <liyouhong@kylinos.cn> Cc: Shuah Khan <shuah@kernel.org> Cc: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev> Cc: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
The putback loop is duplicated in damon_migrate_folio_list() and on the invalid-nid path of damon_migrate_pages(). Factor it into a small helper for readability. No functional change. Link: https://lore.kernel.org/20260831142611.77572-4-sj@kernel.org Signed-off-by: Li Youhong <liyouhong@kylinos.cn> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Enze Li <lienze@kylinos.cn> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Hari Mishal <harimishal1@gmail.com> Cc: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Cc: Shuah Khan <shuah@kernel.org> Cc: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev> Cc: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
…get test The obsolete_target test spawns three sh processes and uses their pids as DAMON monitoring targets. These processes are never terminated or waited on, so they are left running (or become zombies) as orphaned children after the test program exits. Terminate each process and communicate() with it after the targets are no longer needed, so it exits and gets reaped instead of being leaked. Link: https://lore.kernel.org/20260831142611.77572-5-sj@kernel.org Signed-off-by: Hari Mishal <harimishal1@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Enze Li <lienze@kylinos.cn> Cc: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Cc: Li Youhong <liyouhong@kylinos.cn> Cc: Shuah Khan <shuah@kernel.org> Cc: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev> Cc: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Replace manual mutex_lock() and mutex_unlock() calls with the scoped_guard() macro. This simplifies the code, improves readability, and ensures that the lock is automatically released when the scope ends, preventing potential lock leaks in the future. Link: https://lore.kernel.org/20260831142611.77572-6-sj@kernel.org Signed-off-by: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Enze Li <lienze@kylinos.cn> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Hari Mishal <harimishal1@gmail.com> Cc: Li Youhong <liyouhong@kylinos.cn> Cc: Shuah Khan <shuah@kernel.org> Cc: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev> Cc: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
_damon_sysfs.py defines constructors with mutable default arguments, including DamosAccessPattern(), DamosQuota(), DamosWatermarks(), DamosDests(), IntervalsGoal(), and empty lists. Default arguments are evaluated once at function definition time. Damos() instances created without explicit arguments therefore share the same DamosQuota(), and the other default-constructed sub-objects and lists are shared in the same way. The sub-objects keep back-pointers to their owner scheme, so constructing the second Damos() rebinds the shared quota's scheme pointer to the second object. An item appended to one object's default contexts or filters list is also visible from other default-constructed objects. The shared state can corrupt test configurations. DamosQuota.sysfs_dir() derives the sysfs directory from its scheme pointer, so operating on the first scheme's default quota may write to the second scheme's directory. The wrong values often match the defaults, so tests still pass, but the behavior depends on object creation order. Commit 8319dad ("selftests/damon: prevent cross-context state pollution in DamonCtx") fixed the same pattern in DamonCtx only. Fix the remaining constructors by defaulting to None and creating fresh objects or lists inside each constructor. Explicit arguments keep their previous behavior. Link: https://lore.kernel.org/20260831142611.77572-7-sj@kernel.org Signed-off-by: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Enze Li <lienze@kylinos.cn> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Hari Mishal <harimishal1@gmail.com> Cc: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Cc: Li Youhong <liyouhong@kylinos.cn> Cc: Shuah Khan <shuah@kernel.org> Cc: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
The mtier sample defines a local struct region_range using phys_addr_t instead of damon_addr_range which uses unsigned long. Add a comment explaining the rationale: on 32-bit systems with more than 4GiB memory, phys_addr_t will be 64-bit while unsigned long is 32-bit. Link: https://lore.kernel.org/20260831142611.77572-8-sj@kernel.org Signed-off-by: Enze Li <lienze@kylinos.cn> Signed-off-by: SJ Park <sj@kernel.org> Reviewed-by: SJ Park <sj@kernel.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Hari Mishal <harimishal1@gmail.com> Cc: Jaeyeon Lee <jaeyeon.lee.dev@gmail.com> Cc: Li Youhong <liyouhong@kylinos.cn> Cc: Shuah Khan <shuah@kernel.org> Cc: "Zenghui Yu (Huawei)" <zenghui.yu@linux.dev> Cc: zhaozhengzhuo <zhaozhengzhuo@uniontech.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Patch series "mm: optimize zone-device memmap initialization", v11. memmap_init_zone_device() can take a noticeable amount of time when large pmem namespaces are bound or rebound, because it initializes nearly identical struct page descriptors one PFN at a time. This series reduces that ZONE_DEVICE memmap initialization overhead by reusing prepared struct page templates and, on x86, using memcpy_nontemporal() for the template copy path. The main target is large fsdax/devdax pmem configurations, where the cost of initializing the memmap shows up directly in nd_pmem/dax_pmem bind and rebind latency. This matters because the cost is paid in the synchronous probe/bind path for large DAX/PMEM ZONE_DEVICE mappings. Userspace workflows such as provisioning or reconfiguring nd_pmem/dax_pmem namespaces, bringing hot-added PMEM-backed capacity online, and recovering or rebinding a device after driver or device changes all wait for this initialization to finish. Reducing this cost will yield benefits as lower user-visible provisioning, hot-add, recovery, and rebind latency for large DAX/PMEM devices. Patches 1-2 are preparatory cleanups and helper extraction. Patches 3-4 add the template-copy path for head pages and compound tails. Patch 5 introduces memcpy_nontemporal(). Patch 6 switches the ZONE_DEVICE template-copy path over to memcpy_nontemporal(). Patch 7 extends the x86 fixed-size memcpy_flushcache() inline cases used by the x86 memcpy_nontemporal() backend for struct page sized copies. Architectures without a specialized memcpy_nontemporal() backend fall back to memcpy(), so the generic template-copy optimization remains available without arch-specific support. On x86, memcpy_nontemporal() maps to the existing memcpy_flushcache() backend and can use the fixed-size MOVNTI paths added by this series for struct page sized copies. memcpy_nontemporal() is only a copy primitive. It does not imply a drain or a publication barrier. Callers that use it before a producer-consumer or device-visible handoff must provide the required ordering. The ZONE_DEVICE template-copy path uses it only while initializing struct page metadata, so the copy primitive itself does not grow a separate drain contract. The numbers below measure the time spent in memmap_init_zone_device() during driver bind/rebind. They are not measurements of the full nd_pmem or dax_pmem bind/rebind operation. Tested in an x86_64 QEMU/KVM VM with a 100 GB fsdax namespace device configured with map=dev and a 100 GB devdax namespace (align=2097152) on Intel Ice Lake server. Test procedure: Rebind the nd_pmem and dax_pmem drivers 30 times and collect the memmap initialization time from the pr_debug() output of memmap_init_zone_device(). Base(v7.3-rc1): Average of nd_pmem rebinds: 221.07 ms Average of dax_pmem rebinds: 191.20 ms With this series applied: Average of nd_pmem rebinds: 71.93 ms Average of dax_pmem rebinds: 87.37 ms This reduces the average memmap initialization time measured during rebind by about 67.5% for nd_pmem and 54.3% for dax_pmem. As an additional x86_64 data point, I also ran measurements on the same physical host with a 100 GB PMEM region created via the memmap= kernel command line, configured as fsdax and devdax namespaces with map=dev and 2 MiB alignment. For brevity, the individual patches keep only the VM results rather than including a second set of physical-host measurements throughout the series. The physical-host numbers below are included only as supplemental evidence that the same optimization also provides a similar benefit on a non-virtualized system. Test procedure: Reconfigure the namespace mode, rebind the nd_pmem or dax_pmem driver 30 times, and collect the memmap initialization time from the pr_debug() output of memmap_init_zone_device(). Base (v7.3-rc1): nd_pmem / fsdax: 205.90 ms dax_pmem / devdax: 225.43 ms With this series applied: nd_pmem / fsdax: 69.13 ms dax_pmem / devdax: 90.67 ms This reduces the measured memmap initialization time during rebind by about 66.4% for nd_pmem and 59.8% for dax_pmem on that setup, which is broadly consistent with the VM results above. As another supplemental data point, I measured the test_hmm.ko module on the same physical x86_64 host, using the test_hmm.ko setup from the previous discussion that times ten 64 GB memremap_pages()/memunmap_pages() iterations during module insertion[1]. By default, module insertion initializes two DEVICE_PRIVATE dmirror devices, so two avg memremap values are reported; each value is the average for one 64 GB chunk. This is not the primary target workload of the series, but it exercises the same large ZONE_DEVICE memmap initialization path and shows the same direction of improvement. Base (v7.3-rc1): avg memremap reported during module insertion: 116500596 ns, 116438028 ns With this series applied: avg memremap reported during module insertion: 46953088 ns, 4642839 ns This corresponds to about a 59.9% reduction based on the mean of the reported values, which is again consistent with the pmem bind/rebind results above. I also include an arm64 data point for the generic template-copy part. It was measured on an arm64 QEMU virt VM with 64 KB pages and a 100 GB ACPI NVDIMM sparse backend. This setup does not use the x86 MOVNTI fast paths, so it exercises the architecture-independent part of the optimization. For devdax, 2 MiB alignment is rejected in this 64 KB page setup, so the devdax namespace was tested with the supported default 512 MiB alignment. Base (v7.3-rc1): Average of rebinds for nd_pmem driver: 27.93 ms Average of rebinds for dax_pmem driver: 27.87 ms With this series applied: Average of rebinds for nd_pmem driver: 14.53 ms Average of rebinds for dax_pmem driver: 16.27 ms This reduces the average memmap initialization time measured during rebind by about 48.0% for nd_pmem and 41.6% for dax_pmem on that arm64 VM setup. Since this arm64 setup does not use the x86 MOVNTI fast paths, the result also suggests that the generic template-copy optimization can benefit architectures without an architecture-specific memcpy_nontemporal() backend. This patch (of 7): The comment in __init_zone_device_page() still uses the old MEMORY_TYPE_* names and implies that FS_DAX pages regain a refcount of 1 in the free path. That no longer matches the code. Update the comment to describe the current policy correctly: MEMORY_DEVICE_GENERIC pages regain a refcount of 1 in the free path, while the remaining ZONE_DEVICE types start from 0 here and raise the count again when the allocator or driver hands the page out. No functional change intended. Link: https://lore.kernel.org/20260831111638.76012-1-lizhe.67@bytedance.com Link: https://lore.kernel.org/20260831111638.76012-2-lizhe.67@bytedance.com Link: https://lore.kernel.org/all/aiEoByaQdRR3xtM5@nvdebian.thelocal/ [1] Signed-off-by: Li Zhe <lizhe.67@bytedance.com> Reviewed-by: David Hildenbrand (Arm) <david@kernel.org> Reviewed-by: Alistair Popple <apopple@nvidia.com> Reviewed-by: Muchun Song <muchun.song@linux.dev> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Balbir Singh <balbirs@nvidia.com> Cc: "Borislav Petkov (AMD)" <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kees Cook <kees@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Callers that want to update section bits from a PFN currently need to open-code: set_page_section(page, pfn_to_section_nr(pfn)); and guard that sequence with #ifdef SECTION_IN_PAGE_FLAGS. Add set_page_section_from_pfn() to wrap that update in one place. When section bits are stored in page flags, the helper derives the section number from the PFN and updates the page flags. Otherwise keep it as a no-op so callers can use one helper without open-coding SECTION_IN_PAGE_FLAGS. Convert set_page_links() to use the new helper so later ZONE_DEVICE fast-path patches can also update section bits without open-coding SECTION_IN_PAGE_FLAGS at each callsite. This keeps the PFN-to-section translation local to the configurations that actually store section bits in struct page flags, and avoids exposing that detail to generic callers. No functional change intended. Link: https://lore.kernel.org/20260831111638.76012-3-lizhe.67@bytedance.com Signed-off-by: Li Zhe <lizhe.67@bytedance.com> Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org> Acked-by: Muchun Song <muchun.song@linux.dev> Reviewed-by: Balbir Singh <balbirs@nvidia.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: "Borislav Petkov (AMD)" <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Hildenbrand (Arm) <david@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kees Cook <kees@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
memmap_init_zone_device() repeats nearly identical head-page initialization for each PFN. Initialize the first real ZONE_DEVICE head page through the existing path, copy that final state into a reusable template, refresh the PFN-dependent fields in that template before each copy, and copy it into the remaining destination pages. Use the template path unconditionally. The page_ref_set tracepoint is primarily a debugging aid, while this code is still initializing struct pages before they are handed out. From the perspective of users of those pages, the initialization-time refcount transitions are not part of the observable page lifetime. This means page_ref_set will no longer observe every initialization-time refcount assignment for copied ZONE_DEVICE head pages. The impact is controlled because the final initialized struct page state is unchanged, and keeping a separate non-template path only for this local tracepoint observability would add complexity to the common path. This patch accelerates head-page initialization. The pfns_per_compound == 1 case gets the full benefit here, compound tails are handled in the next patch. Tested in a VM with a 100 GB fsdax namespace device configured with map=dev on Intel Ice Lake server. This test exercises the nd_pmem rebind path (pfns_per_compound == 1). Test procedure: Rebind the nd_pmem driver 30 times and collect the memmap initialization time from the pr_debug() output of memmap_init_zone_device(). Base(v7.3-rc1): Average of rebinds for nd_pmem driver: 221.07 ms With this patch and its prerequisites applied: Average of rebinds for nd_pmem driver: 155.00 ms This reduces the average memmap initialization time measured during rebind from 221.07 ms to 155.00 ms, or about 29.9%. Link: https://lore.kernel.org/20260831111638.76012-4-lizhe.67@bytedance.com Signed-off-by: Li Zhe <lizhe.67@bytedance.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Balbir Singh <balbirs@nvidia.com> Cc: "Borislav Petkov (AMD)" <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Hildenbrand (Arm) <david@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kees Cook <kees@kernel.org> Cc: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
The template fast path from the previous patch only accelerates head pages. Compound tails in memmap_init_compound() still go through the normal initialization path one by one. Build separate head and tail templates and reuse one prepared tail template across the tail pages in a compound range. Head pages preserve the existing refcount policy, while compound tails always start with a refcount of 0 after prep_compound_tail(). This extends the template-copy fast path to pfns_per_compound > 1. Tail-page PFN-dependent fields are refreshed in the reusable tail template before each copy. Do not keep a separate non-template fallback for compound tails either. These pages are still under memmap initialization, and the initialization-time refcount updates are not part of the observable lifetime of pages handed out later. The impact is controlled for the same reason as for head pages. The first tail page still seeds the reusable tail template through the normal tail initialization sequence, and the copied tail pages have the same final initialized state except for the PFN-dependent fields refreshed before each copy. Tested in a VM with a 100 GB devdax namespace (align=2097152) on Intel Ice Lake server. This test exercises the dax_pmem rebind path and measures memmap initialization latency. Test procedure: Unbind and rebind the dax_pmem driver 30 times, collect memmap initialization time from the pr_debug() output of memmap_init_zone_device(). Base(v7.3-rc1): Average of rebinds for dax_pmem driver: 191.20 ms With this patch and its prerequisites applied: Average of rebinds for dax_pmem driver: 176.87 ms This reduces the average memmap initialization time measured during rebind from 191.20 ms to 176.87 ms, or about 7.5%. Link: https://lore.kernel.org/20260831111638.76012-5-lizhe.67@bytedance.com Signed-off-by: Li Zhe <lizhe.67@bytedance.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Balbir Singh <balbirs@nvidia.com> Cc: "Borislav Petkov (AMD)" <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Hildenbrand (Arm) <david@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kees Cook <kees@kernel.org> Cc: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Introduce memcpy_nontemporal() for write-once copy sites that want a named non-temporal copy primitive. On x86_64, override the helper in arch/x86/include/asm/string_64.h using the usual self-macro pattern, next to the existing memcpy_flushcache() backend that memcpy_nontemporal() wraps. include/linux/string.h provides the generic memcpy_nontemporal() fallback as #define memcpy_nontemporal(dst, src, len) \ ((void)memcpy(dst, src, len)) instead of an inline wrapper, so architectures without a specialized backend keep the usual memcpy() FORTIFY coverage when the compiler can still see object sizes at the original call site. It also makes the memcpy_nontemporal() API uniformly void, matching memcpy_flushcache() and the x86 backend, so callers cannot accidentally depend on a return value on fallback architectures. memcpy_nontemporal() is only a copy primitive. It does not imply a drain or a publication barrier. Callers that use it before a producer-consumer or device-visible handoff must provide the required ordering at that handoff point. The immediate user is the ZONE_DEVICE template-copy path. It populates struct page descriptors in a write-once pattern, so a regular cached memcpy() can incur avoidable write-allocate traffic and cache pollution for data with little near-term reuse. Link: https://lore.kernel.org/20260831111638.76012-6-lizhe.67@bytedance.com Signed-off-by: Li Zhe <lizhe.67@bytedance.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Balbir Singh <balbirs@nvidia.com> Cc: "Borislav Petkov (AMD)" <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Hildenbrand (Arm) <david@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kees Cook <kees@kernel.org> Cc: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
The template fast path currently uses memcpy() for the actual struct page copy. Switch zone_device_page_init_from_template() to memcpy_nontemporal(). ZONE_DEVICE memmap initialization is largely write-once: each struct page is populated once, and most destination cachelines are not expected to be reused immediately afterwards. On x86, a regular cached memcpy() can therefore incur write-allocate traffic by pulling destination cachelines into the cache before writeback, and can populate the cache with data that has little near-term reuse. Using memcpy_nontemporal() lets this path request nontemporal stores for that copy pattern, which can reduce cache pollution and avoid part of the associated write-allocate overhead, while architectures without a specialized backend still fall back to memcpy(). Do not add a KASAN/KMSAN-specific fallback around this call site. As Muchun pointed out, special KASAN handling for memcpy_flushcache() or memcpy_nontemporal(), if needed, belongs in the low-level helper rather than in this ZONE_DEVICE caller. No separate drain is added here. memcpy_nontemporal() is used only as the copy primitive while memmap_init_zone_device() is still initializing the struct page array. The ordinary stores that follow in this path, such as compound-page setup, are part of the same CPU's initialization sequence; they are not used as a publication store that tells another CPU or device to consume data written by the non-temporal copy. Therefore this call site does not need a helper-level drain for correctness. Callers that use memcpy_nontemporal() as part of a producer-consumer or device-visible handoff must add the required ordering themselves. Tested in a VM with a 100 GB fsdax namespace device configured with map=dev and a 100 GB devdax namespace (align=2097152) on Intel Ice Lake server. Test procedure: Rebind the nd_pmem and dax_pmem driver 30 times and collect the memmap initialization time from the pr_debug() output of memmap_init_zone_device(). Base(v7.3-rc1): Average of rebinds for nd_pmem driver: 221.07 ms Average of rebinds for dax_pmem driver: 191.20 ms With this patch and its prerequisites applied: Average of rebinds for nd_pmem driver: 150.40 ms Average of rebinds for dax_pmem driver: 161.83 ms This reduces the average memmap initialization time measured during rebind by about 32.0% for nd_pmem and 15.4% for dax_pmem. Link: https://lore.kernel.org/20260831111638.76012-7-lizhe.67@bytedance.com Signed-off-by: Li Zhe <lizhe.67@bytedance.com> Cc: Alistair Popple <apopple@nvidia.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Balbir Singh <balbirs@nvidia.com> Cc: "Borislav Petkov (AMD)" <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Hildenbrand (Arm) <david@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Kees Cook <kees@kernel.org> Cc: Mike Rapoport (Microsoft) <rppt@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[Why] Chrontel CH7218 found in Ugreen DP -> HDMI 2.1 adapter (model 85564) works perfectly with VRR after testing. VRR and FreeSync compatibility is explicitly advertised as a feature so it's addition is a formality. Support FreeSync info packet passthrough and "generic" HDMI VRR. [How] Add CH7218's ID to dm_helpers_is_vrr_pcon_allowed() Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4773 Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com> (cherry picked from commit 7b2436287ed953496ad1c9eb5820f00b75db597f)
… Block why: HDMI FRL sinks were not parsed for the AMD VSDB and no VTEM info packet was emitted for them, so 2.1 FreeSync over HDMI FRL did not work. It is backward-compatible with 2.0 FreeSync. how: - Accept SIGNAL_TYPE_HDMI_FRL alongside SIGNAL_TYPE_HDMI_TYPE_A when parsing the AMD VSDB in amdgpu_dm_update_freesync_caps(). - Build and send the VTEM info packet via mod_build_infopacket_vtem() when the stream signal is HDMI FRL during the freesync state update. - Set the VTEM Data_Set_Length to 0 when no VTEM feature is enabled. build_infopacket_header_vtem() hardcodes Data_Set_Length = 4, so a VTEM with Data_Set_Length = 4 would be transmitted even when no VTEM feature is enabled (VRR_EN = 0 and no FVA), e.g. when the sink advertises VRRMIN = 0 and vrr_capable is false. This fails HDMI GCTS HF1-58 step 6.2. The VTEM must keep being transmitted every MTW while VRR is enabled (HF1-58 steps 8.1 and 8.3), so it cannot simply be suppressed per frame. Instead, follow the MLDS option in HDMI 2.1 10.10.2.4: keep transmitting the VTEM but set Data_Set_Length = 0 when no feature is enabled. When VRR becomes active the full Data_Set_Length = 4 payload with VRR_EN = 1 is sent as before. Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> (cherry picked from commit 62ac74defba77c84daee2adc56b19b2c0b4e9afd)
…m HF-VSDB Parse the HDMI 2.1 gaming-related capabilities advertised in the HDMI Forum VSDB (HF-VSDB) and expose them through struct drm_hdmi_info so drivers can consume them. Add struct drm_hdmi_vrr_cap describing the sink's VRR capabilities: Fast VActive (Quick Frame Transport), Negative M VRR, Cinema VRR, MDelta, and the VRRmin/VRRmax range, together with a "supported" flag derived from that range. Add the fapa_start_location and allm (Auto Low Latency Mode) flags to struct drm_hdmi_info. drm_parse_hdmi_gaming_info() reads byte 8 of the HF-VSDB for the FAPA/ALLM/FVA/CNMVRR/CinemaVRR/MDelta flags and bytes 9-10 for VRRmin/VRRmax. Per HDMI 2.1, VRR is considered supported when VRRmin is within 1-48 and VRRmax is either 0 (maximum based on the video mode) or >= 100. It is invoked from drm_parse_hdmi_forum_scds(), and the parsed values are logged for debugging. Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com> Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> Tested-by: Bernhard Berger <bernhard.berger@gmail.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> (cherry picked from commit 26e1509c3ec24f6314e972edd64d9dc18d8be779)
why: HDMI 2.1 sinks advertise their VRR range in the HDMI Forum VSDB (HF-VSDB), but amdgpu derived FreeSync capability only from the AMD VSDB. Sinks that expose just the HDMI Forum VRR capability (e.g. HDMI compliance EDIDs) were therefore reported as not VRR capable. how: - In amdgpu_dm_update_freesync_caps(), when the AMD VSDB does not provide a valid FreeSync range, fall back to the HDMI 2.1 VRR range parsed by DRM core from the HF-VSDB (connector->display_info.hdmi.vrr_cap). VRRMAX = 0 means "up to the Base Refresh Rate"; when the EDID provides no monitor range maximum either, fall back to the Base Refresh Rate (the highest refresh-rate mode of the preferred timing) so a valid VRR range is still reported to userspace. - Add VRR debug logging along the FreeSync capability and config paths. Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> Reviewed-by: Harry Wentland <harry.wentland@amd.com> (cherry picked from commit c5010ee089293c52c6489d308f1e659ba74f6ed5)
why: HDMI 2.1 Auto Low-Latency Mode (ALLM) lets a Source request the Sink's low-latency mode through the HF-VSIF. HDMI 2.1 Section 7.6.6 requires that when Gaming-VRR is enabled (VRR_EN=1) and the Sink advertises ALLM in the SCDS, the Source shall transmit the HF-VSIF and set ALLM_Mode=1. amdgpu never set ALLM_Mode, so this requirement was not met. how: - In update_freesync_state_on_stream(), set ALLM_Mode=1 in the HF-VSIF when Gaming-VRR is active (vrr state ACTIVE_VARIABLE/ACTIVE_FIXED, i.e. VRR_EN=1) and the sink advertises ALLM, per HDMI 2.1 Section 7.6.6, and push the updated HF-VSIF (vsp_infopacket) as a stream update. ALLM is driven only by the mandatory Gaming-VRR case. Signed-off-by: Fangzhi Zuo <Jerry.Zuo@amd.com> (cherry picked from commit 7cafa47e65ace3daf0758553da2d6131c4290b5f)
Enable freesync_on_desktop for HDMI streams so the display can keep FreeSync enabled during normal desktop use. This allows the HDMI VRR path to support fixed-refresh desktop operation while retaining FreeSync signaling for the display. Signed-off-by: Andy East <andy10115@gmail.com>
…acket.c Treat VRR_STATE_INACTIVE as VRR-active when freesync_on_desktop is enabled so HDMI VTEM continues advertising VRR during fixed-refresh desktop use. Use a single vrr_active value for both the VTEM VRR_EN bit and the Data_Set_Length decision. This keeps VTEM signaling consistent while allowing the display to remain in its VRR mode without varying the actual refresh rate. Signed-off-by: Andy East <andy10115@gmail.com>
The detachable keyboard shipped with the ROG Zephyrus Duo GX651AR (0b05:1ce6) is a ROG N-Key keyboard, but it is not listed in asus_devices[], so its interfaces are left to hid-generic and its vendor usages are never mapped by asus_input_mapping(). Add it with QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD, matching the other ROG N-Key keyboards. Tested-by: Cymirk <cymirk@icloud.com> Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
… interfaces On the ROG Zephyrus Duo GX651AR (0b05:1ce6) the hotkeys live on report 0x5a on an interface whose descriptor holds nothing but two ASUS vendor collections. Neither satisfies IS_INPUT_APPLICATION(), so hidinput_connect() creates no input device, asus_input_mapping() never runs and every hotkey is dropped by asus_event() as unmapped. Set HID_QUIRK_HIDINPUT_FORCE on ROG N-Key interfaces that carry an ASUS vendor input report so those usages get mapped. Interfaces left with no mapped usage are still discarded by hidinput_has_been_populated(). The vendor check reads report_enum[HID_INPUT_REPORT], so interfaces with no input reports, such as the RGB control interface, are unaffected. Tested-by: Cymirk <cymirk@icloud.com> Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
…Bluetooth The GX651AR keyboard enumerates as 0b05:1ce6 over USB but pairs as 0b05:1ce7 in Bluetooth mode, where the keyboard, consumer and both ASUS vendor collections (reports 0x5a and 0x5d) sit on a single HID device. Add it with the same quirks as the USB entry. Bind to HID_GROUP_GENERIC so that hid-multitouch keeps the digitizer. Tested-by: Cymirk <cymirk@icloud.com> Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
…X651AR Fn+F12 on the GX651AR keyboard emits ASUS vendor code 0x9c, which asus_input_mapping() does not know about, so asus_event() drops it as unmapped. Map it to KEY_F19. F13 to F18 are already used for ASUS toggles that have no generic keycode. Tested-by: Cymirk <cymirk@icloud.com> Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
Add support for the AMD IOMMU Performance Optimization (PerfOpt) feature as defined in the AMD I/O Virtualization Technology (IOMMU) Specification, Section 3.4.9 (MMIO Offset 016Ch). This feature allows privileged integrated I/O devices (GPUs) to bypass the IOMMU when directly accessing system memory. The IOMMU only enforces the IR/IW permission bits without GPA->SPA translations. amd_iommu_enable_perfopt() performs a detach/reattach cycle to rehome devices already on the identity domain with ATS/PRI/PASID/GCR3 disabled (skip_caps path). amd_iommu_disable_perfopt() restores those capabilities. The per-device dev_data->perfopt flag tracks state. PERF_OPT_EN is a single control bit per IOMMU, shared by every device behind that IOMMU, while enablement is requested per device. It is therefore reference counted (amd_iommu->perfopt_refcount): armed on the first requesting device and cleared on the last, so one device's teardown never clears the bit while a peer behind the same IOMMU still needs it. The per-device flag is cleared on every teardown path (blocked_domain_attach, release_device, and amd_iommu_disable_perfopt), dropping the reference with it, so a reused dev_data never carries stale PerfOpt state onto its next bind. On suspend/resume the hardware is reprogrammed from scratch: amd_iommu_perfopt_clear() forces the bit off without touching the reference count, and amd_iommu_perfopt_restore() re-asserts it from the count after early_enable_iommu(), so armed devices keep the optimization across resume without relying on each consumer driver to re-arm. The exported amd_iommu_enable_perfopt()/amd_iommu_disable_perfopt() run only from a consumer driver's bind/unbind path. group->mutex is not exposed to drivers, but a device bound to its native driver cannot have its IOMMU domain changed concurrently by the core, which serializes the detach/attach pair against core-driven attach. PerfOpt is opt-in -- only enabled when explicitly requested by a driver. Co-developed-by: Jatin Kataria <jkataria@netflix.com> Signed-off-by: Jatin Kataria <jkataria@netflix.com> Link: https://patch.msgid.link/20260831055108.1893285-2-mario.limonciello@amd.com Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
… in identity domain Enable PerfOpt via amd_iommu_enable_perfopt() when the GPU's iommu_perfopt module parameter is enabled (default 1) and the GPU resides in the identity domain. The identity domain means the GPU is already performing direct DMA with the IOMMU only enforcing IR/IW permission bits -- no GPA->SPA translations. amd_iommu_enable_perfopt() clears ATS, PRI, PASID and SVA for the device. This is safe in identity domain because DTE[I]=0 means the IOMMU already returns target abort for ATS requests from this peripheral and the GPU manages its own TLB. PerfOpt is a soft, optional latency optimization: failing to arm it (for example on an IOMMU that does not implement the feature, which returns -ENODEV) must not be fatal, so probe and resume warn and continue rather than aborting. PERF_OPT_EN is a per-IOMMU control shared by all devices behind that IOMMU; the IOMMU driver reference counts it so that on systems where multiple devices share one IOMMU, one GPU's teardown does not clear the bit while a peer still requires it. Arming PerfOpt trades IOMMU DMA containment for lower DMA latency. This is enabled by default for GPUs in the identity domain as a deliberate, documented policy and can be disabled with iommu_perfopt=0. The AMD IOMMU spec indicates this is only supported on integrated GPUs so check explicitly for AMD_IS_APU (which is set by amdgpu_device_ip_early_init()). PerfOpt is disabled during GPU init teardown and restored on resume. Link: https://patch.msgid.link/20260831055108.1893285-3-mario.limonciello@amd.com Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Commit 0919db9 ("HID: asus: always fully initialize devices") added a loop during asus_probe() to send keyboard feature report initializations (asus_kbd_init) to all ASUS HID devices. On ASUS laptops with I2C/HID touchpads (such as the ASUS E200HA), sending keyboard feature reports (FEATURE_KBD_REPORT_ID) to touchpad endpoints sends invalid feature requests to touchpad hardware, corrupting probe state and causing the touchpad to become unresponsive. Wrap the asus_report_id_init loop in an `if (!drvdata->tp)` check so keyboard feature initialization only runs for actual keyboards. Tested on ASUS E200HA (where touchpad functionality is fully restored) and ASUS VivoBook Flip 14 TP401MA (confirming zero regressions). Fixes: 0919db9 ("HID: asus: always fully initialize devices") Cc: stable@vger.kernel.org Signed-off-by: Panz Dev <panz.development@gmail.com>
The AYANEO 3 handheld has a detachable controller with swappable
modules ("Magic Modules"). The controller exposes three USB HID
interfaces behind 1c4f:0002 (a generic SigmaMicro VID/PID, hence the
DMI gate): a gamepad, a keyboard for the extra buttons, and a vendor
interface accepting 65-byte commands.
Add a driver for the vendor interface providing module identification
(module_left/module_right sysfs attributes), software eject of the
modules (eject sysfs attribute, blocking until the firmware confirms
the release handshake), and RGB control of the joystick rings as a
multicolor LED class device ("<device name>:rgb:joystick_rings";
userspace such as InputPlumber matches the function suffix). The
firmware's fixed breathing pattern is exposed through the hw_pattern
trigger ABI.
This complements the ayaneo-ec platform driver, which exposes module
attach state and controller power. A full physical eject is performed
by writing to eject and then cutting power through ayaneo-ec's
controller_power attribute; that orchestration is deliberately left
to userspace.
The protocol was reverse engineered in the Handheld Daemon project by
Antheas Kapenekakis. Tested on an AYANEO 3: module identification,
RGB solid and breathing, a full eject/reinsert/repower cycle, and
repeated driver unbinds under a concurrent brightness-write load.
Signed-off-by: Matías Martínez <hello@matias.me>
Reviewed-by: Denis Benato <denis.benato@linux.dev>
Lets the build workflow compile the new driver. The real OGC config change is OpenGamingCollective/kernel-packages#35, which lands once the driver merges. Signed-off-by: Matías Martínez <hello@matias.me>
pastaq
force-pushed
the
pastaq/ogc-next/7.3/hid/hid-lenovo-go-s
branch
2 times, most recently
from
September 3, 2026 02:26
a06835c to
39adfc9
Compare
Currently mcu_property_out() blanket returns 0, discarding the ret value and any errors with it. Wait completion returns a positive value when it is not timed out, which would error on all successes, so if it is positive return the ret value from the raw event handler. Only if it is 0 set it to -EBUSY, otherwise pass the actual error. Fixes: a23f349 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
…d_complete mcu_property_out() reinits send_cmd_complete immediately after a timeout is detected, before the next command that reuses it is sent. If the MCU's reply to the timed-out command arrives after this reinit but before the next command's wait begins, it silently satisfies the next, unrelated command's wait instead of the one it actually answers, handing that caller stale data with no way to detect the mismatch. Track when a command has timed out via cmd_orphaned. Before the next command reuses the completion, wait a bounded 25ms for a stale reply to arrive and be consumed, then unconditionally clear the flag and reinit the completion. This does not fully eliminate the window in which an unrelated reply could still be received, but bounds it to a short interval right before a new command is sent. Behavior matches the solution to the same problem in hid-msi. Fixes: a23f349 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
hid_gos_cfg_remove() calls a mutex before canceling delayed work. That delayed work function calls mcu_property_out(), which holds the same mutex. Prevent deadlock my removing the mutex prior to stopping the work. Additionally, since cancle_delayed_work has the potential to re-arm, switch to disable_delayed_work. Fixes: a23f349 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
Adds missing pm_ptr to the .reset_reusme callback for hid-lenovo-go-s Fixes: 3524900 ("HID: hid-lenovo-go-s: restore OS_TYPE after resume from s2idle") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
Adds kobject_uevent notification after setting os_mode attribute on resume. Fixes: 3524900 ("HID: hid-lenovo-go-s: restore OS_TYPE after resume from s2idle") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
Currently a device can suspend while delayed work is pending or executing. Cancel delayed work if it was pending and restart it if it hasn't run yet. Gate access to show/store functions behind a bool to prevent access prior to cfg_setup being completed. Fixes: a23f349 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
Currently this driver registers attributes before the MCU is ready to accept commands. This can lead to attribute access that blocks the MCU in some rare cases. Move attribute construction to gos_cfg_setup, after the device has been queried. Gate creation to drvdata.gp_registered and drvdata.rgb_registered so a resume before setup has run doesn't prevent attribute creation or attempt to re-register the same attributes. Fixes: a23f349 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
Renames hid_gos_cfg struct to gos_cfg_drvdata in preparation for later fixes. Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
In the next patch I will switch drvdata from static global to a devm_kzalloc struct. In preparation for that, move the led_classdev_mc to be a member of the gos_cfg_drvdata struct. As part of that effort, provide a constant name when accessing it and access the led_classdev through the led_classdev_mc. Fixes: be6d7db ("HID: hid-lenovo-go-s: Add RGB LED control interface") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
Changes drvdata from static global to devm allocation per device. Fixes: a23f349 ("HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver") Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
pastaq
force-pushed
the
pastaq/ogc-next/7.3/hid/hid-lenovo-go-s
branch
from
September 3, 2026 02:33
39adfc9 to
dd071b9
Compare
github-actions
Bot
force-pushed
the
master
branch
from
September 4, 2026 13:12
af0e02d to
743e77c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.