Recreate RHEL kernel-6.12.0-211.43.1.el10_2 from CS10/upstream backports

This commit is contained in:
AlmaLinux RelEng Bot 2026-08-06 12:09:46 +00:00
parent 19dff4196b
commit 67588c0c82
28 changed files with 2385 additions and 7 deletions

View File

@ -0,0 +1,73 @@
From ce9a1d1e3fc747bc929f7560de3df369c1a45434 Mon Sep 17 00:00:00 2001
From: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Date: Mon, 8 Jun 2026 17:25:54 +0200
Subject: [PATCH] net: wwan: t7xx: Add delay between MD and SAP suspend
JIRA: https://issues.redhat.com/browse/RHEL-155042
commit ae733795e593272f67d607c09d2a00637ac13ed0
Author: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Date: Wed May 27 08:14:51 2026 +0200
net: wwan: t7xx: Add delay between MD and SAP suspend
SAP (Service Access Point) suspend occasionally times out with error
-110 (ETIMEDOUT), followed by modem port errors and complete modem
failure requiring a system reboot to recover.
Error symptoms:
mtk_t7xx 0000:72:00.0: [PM] SAP suspend error: -110
mtk_t7xx 0000:72:00.0: can't suspend (...returned -110)
mtk_t7xx 0000:07:00.0: Failed to send skb: -22
mtk_t7xx 0000:07:00.0: Write error on MBIM port, -22
The modem firmware needs time after receiving the MD (modem) suspend
request to complete internal operations before it is ready to accept
the SAP suspend request. Without this delay, if runtime PM attempts
to suspend while the firmware is busy, the SAP suspend command times
out, leaving the modem in an unrecoverable state.
Root cause and userspace interaction:
ModemManager 1.24+ includes changes that reduce the likelihood of this
issue by ensuring the modem is in a low-power state before the kernel
attempts runtime suspend. However, the kernel driver should not depend
on specific userspace behavior or ModemManager versions. Older versions
(1.20-1.22) are still widely deployed, and the kernel should be robust
regardless of userspace implementation details.
There appears to be no hardware status register or other mechanism
available to query whether the firmware is ready for SAP suspend.
A delay between the two suspend requests is the most reliable solution
found through testing.
Add a 50ms delay between MD suspend and SAP suspend. This gives the
firmware adequate time to complete internal operations without adding
significant latency to the suspend path. This makes the driver robust
across all ModemManager versions and system conditions.
Testing: 96+ hours of continuous operation with ModemManager 1.20.2
and Fibocom FM350-GL modem. Zero SAP suspend timeouts observed across
2000+ successful suspend/resume cycles. Previously failed within
24 hours with 100% reproducibility.
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Link: https://patch.msgid.link/20260527061451.12710-1-jtornosm@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c
index eb137e0..46613bb 100644
--- a/drivers/net/wwan/t7xx/t7xx_pci.c
+++ b/drivers/net/wwan/t7xx/t7xx_pci.c
@@ -447,6 +447,9 @@ static int __t7xx_pci_pm_suspend(struct pci_dev *pdev)
goto abort_suspend;
}
+ /* Delay to prevent SAP suspend timeout */
+ msleep(50);
+
ret = t7xx_send_pm_request(t7xx_dev, H2D_CH_SUSPEND_REQ_AP);
if (ret) {
t7xx_send_pm_request(t7xx_dev, H2D_CH_RESUME_REQ);

View File

@ -0,0 +1,94 @@
From 449e173e733a3f8bb9186785fc48265fbcfd8956 Mon Sep 17 00:00:00 2001
From: Waiman Long <longman@redhat.com>
Date: Mon, 9 Mar 2026 23:09:28 -0400
Subject: [PATCH] timers: Fix NULL function pointer race in
timer_shutdown_sync()
JIRA: https://issues.redhat.com/browse/RHEL-152433
CVE: CVE-2025-68214
commit 20739af07383e6eb1ec59dcd70b72ebfa9ac362c
Author: Yipeng Zou <zouyipeng@huawei.com>
Date: Sat, 22 Nov 2025 09:39:42 +0000
timers: Fix NULL function pointer race in timer_shutdown_sync()
There is a race condition between timer_shutdown_sync() and timer
expiration that can lead to hitting a WARN_ON in expire_timers().
The issue occurs when timer_shutdown_sync() clears the timer function
to NULL while the timer is still running on another CPU. The race
scenario looks like this:
CPU0 CPU1
<SOFTIRQ>
lock_timer_base()
expire_timers()
base->running_timer = timer;
unlock_timer_base()
[call_timer_fn enter]
mod_timer()
...
timer_shutdown_sync()
lock_timer_base()
// For now, will not detach the timer but only clear its function to NULL
if (base->running_timer != timer)
ret = detach_if_pending(timer, base, true);
if (shutdown)
timer->function = NULL;
unlock_timer_base()
[call_timer_fn exit]
lock_timer_base()
base->running_timer = NULL;
unlock_timer_base()
...
// Now timer is pending while its function set to NULL.
// next timer trigger
<SOFTIRQ>
expire_timers()
WARN_ON_ONCE(!fn) // hit
...
lock_timer_base()
// Now timer will detach
if (base->running_timer != timer)
ret = detach_if_pending(timer, base, true);
if (shutdown)
timer->function = NULL;
unlock_timer_base()
The problem is that timer_shutdown_sync() clears the timer function
regardless of whether the timer is currently running. This can leave a
pending timer with a NULL function pointer, which triggers the
WARN_ON_ONCE(!fn) check in expire_timers().
Fix this by only clearing the timer function when actually detaching the
timer. If the timer is running, leave the function pointer intact, which is
safe because the timer will be properly detached when it finishes running.
Fixes: 0cc04e80458a ("timers: Add shutdown mechanism to the internal functions")
Signed-off-by: Yipeng Zou <zouyipeng@huawei.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20251122093942.301559-1-zouyipeng@huawei.com
Signed-off-by: Waiman Long <longman@redhat.com>
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 1391ea8..9b61f99 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1458,10 +1458,11 @@ static int __try_to_del_timer_sync(struct timer_list *timer, bool shutdown)
base = lock_timer_base(timer, &flags);
- if (base->running_timer != timer)
+ if (base->running_timer != timer) {
ret = detach_if_pending(timer, base, true);
- if (shutdown)
- timer->function = NULL;
+ if (shutdown)
+ timer->function = NULL;
+ }
raw_spin_unlock_irqrestore(&base->lock, flags);

View File

@ -0,0 +1,274 @@
From aac205646b22c60a35eeb810537df406a0ce2c65 Mon Sep 17 00:00:00 2001
From: Rafael Aquini <raquini@redhat.com>
Date: Wed, 1 Jul 2026 16:38:58 -0400
Subject: [PATCH] procfs: avoid fetching build ID while holding VMA lock
JIRA: https://redhat.atlassian.net/browse/RHEL-189666
CVE: CVE-2026-23199
Conflicts:
* fs/proc/task_mmu.c: minor differences in the hunks due to RHEL-10 yet not
utilizing granular per-VMA lock for PROCMAP_QUERY and instead relying on
the full-fledged mmap_lock semaphore for sinchronization. The convertion
of PROCMAP_QUERY to per-VMA locks is v6.18 material and its imposed churn
is not required nor it is a necessary condition for the correction of this
backport.
commit b5cbacd7f86f4f62b8813688c8e73be94e8e1951
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Thu Jan 29 13:53:40 2026 -0800
procfs: avoid fetching build ID while holding VMA lock
Fix PROCMAP_QUERY to fetch optional build ID only after dropping mmap_lock
or per-VMA lock, whichever was used to lock VMA under question, to avoid
deadlock reported by syzbot:
-> #1 (&mm->mmap_lock){++++}-{4:4}:
__might_fault+0xed/0x170
_copy_to_iter+0x118/0x1720
copy_page_to_iter+0x12d/0x1e0
filemap_read+0x720/0x10a0
blkdev_read_iter+0x2b5/0x4e0
vfs_read+0x7f4/0xae0
ksys_read+0x12a/0x250
do_syscall_64+0xcb/0xf80
entry_SYSCALL_64_after_hwframe+0x77/0x7f
-> #0 (&sb->s_type->i_mutex_key#8){++++}-{4:4}:
__lock_acquire+0x1509/0x26d0
lock_acquire+0x185/0x340
down_read+0x98/0x490
blkdev_read_iter+0x2a7/0x4e0
__kernel_read+0x39a/0xa90
freader_fetch+0x1d5/0xa80
__build_id_parse.isra.0+0xea/0x6a0
do_procmap_query+0xd75/0x1050
procfs_procmap_ioctl+0x7a/0xb0
__x64_sys_ioctl+0x18e/0x210
do_syscall_64+0xcb/0xf80
entry_SYSCALL_64_after_hwframe+0x77/0x7f
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
rlock(&mm->mmap_lock);
lock(&sb->s_type->i_mutex_key#8);
lock(&mm->mmap_lock);
rlock(&sb->s_type->i_mutex_key#8);
*** DEADLOCK ***
This seems to be exacerbated (as we haven't seen these syzbot reports
before that) by the recent:
777a8560fd29 ("lib/buildid: use __kernel_read() for sleepable context")
To make this safe, we need to grab file refcount while VMA is still locked, but
other than that everything is pretty straightforward. Internal build_id_parse()
API assumes VMA is passed, but it only needs the underlying file reference, so
just add another variant build_id_parse_file() that expects file passed
directly.
[akpm@linux-foundation.org: fix up kerneldoc]
Link: https://lkml.kernel.org/r/20260129215340.3742283-1-andrii@kernel.org
Fixes: ed5d583a88a9 ("fs/procfs: implement efficient VMA querying API for /proc/<pid>/maps")
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reported-by: <syzbot+4e70c8e0a2017b432f7a@syzkaller.appspotmail.com>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Tested-by: Suren Baghdasaryan <surenb@google.com>
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Eduard Zingerman <eddyz87@gmail.com>
Cc: Hao Luo <haoluo@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: KP Singh <kpsingh@kernel.org>
Cc: Martin KaFai Lau <martin.lau@linux.dev>
Cc: Song Liu <song@kernel.org>
Cc: Stanislav Fomichev <sdf@fomichev.me>
Cc: Yonghong Song <yonghong.song@linux.dev>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Rafael Aquini <raquini@redhat.com>
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 4cb8583..27cc491 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -456,6 +456,7 @@ static int do_procmap_query(struct proc_maps_private *priv, void __user *uarg)
struct procmap_query karg;
struct vm_area_struct *vma;
struct mm_struct *mm;
+ struct file *vm_file = NULL;
const char *name = NULL;
char build_id_buf[BUILD_ID_SIZE_MAX], *name_buf = NULL;
__u64 usize;
@@ -528,21 +529,6 @@ static int do_procmap_query(struct proc_maps_private *priv, void __user *uarg)
karg.inode = 0;
}
- if (karg.build_id_size) {
- __u32 build_id_sz;
-
- err = build_id_parse(vma, build_id_buf, &build_id_sz);
- if (err) {
- karg.build_id_size = 0;
- } else {
- if (karg.build_id_size < build_id_sz) {
- err = -ENAMETOOLONG;
- goto out;
- }
- karg.build_id_size = build_id_sz;
- }
- }
-
if (karg.vma_name_size) {
size_t name_buf_sz = min_t(size_t, PATH_MAX, karg.vma_name_size);
const struct path *path;
@@ -576,10 +562,34 @@ static int do_procmap_query(struct proc_maps_private *priv, void __user *uarg)
karg.vma_name_size = name_sz;
}
+ if (karg.build_id_size && vma->vm_file)
+ vm_file = get_file(vma->vm_file);
+
/* unlock vma or mmap_lock, and put mm_struct before copying data to user */
query_vma_teardown(mm, vma);
mmput(mm);
+ if (karg.build_id_size) {
+ __u32 build_id_sz;
+
+ if (vm_file)
+ err = build_id_parse_file(vm_file, build_id_buf, &build_id_sz);
+ else
+ err = -ENOENT;
+ if (err) {
+ karg.build_id_size = 0;
+ } else {
+ if (karg.build_id_size < build_id_sz) {
+ err = -ENAMETOOLONG;
+ goto out;
+ }
+ karg.build_id_size = build_id_sz;
+ }
+ }
+
+ if (vm_file)
+ fput(vm_file);
+
if (karg.vma_name_size && copy_to_user(u64_to_user_ptr(karg.vma_name_addr),
name, karg.vma_name_size)) {
kfree(name_buf);
@@ -599,6 +609,8 @@ static int do_procmap_query(struct proc_maps_private *priv, void __user *uarg)
out:
query_vma_teardown(mm, vma);
mmput(mm);
+ if (vm_file)
+ fput(vm_file);
kfree(name_buf);
return err;
}
diff --git a/include/linux/buildid.h b/include/linux/buildid.h
index 831c1b4..7acc06b 100644
--- a/include/linux/buildid.h
+++ b/include/linux/buildid.h
@@ -7,7 +7,10 @@
#define BUILD_ID_SIZE_MAX 20
struct vm_area_struct;
+struct file;
+
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size);
+int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size);
int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size);
int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size);
diff --git a/lib/buildid.c b/lib/buildid.c
index 8183310..c4b7376 100644
--- a/lib/buildid.c
+++ b/lib/buildid.c
@@ -279,7 +279,7 @@ static int get_build_id_64(struct freader *r, unsigned char *build_id, __u32 *si
/* enough for Elf64_Ehdr, Elf64_Phdr, and all the smaller requests */
#define MAX_FREADER_BUF_SZ 64
-static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
+static int __build_id_parse(struct file *file, unsigned char *build_id,
__u32 *size, bool may_fault)
{
const Elf32_Ehdr *ehdr;
@@ -287,11 +287,7 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
char buf[MAX_FREADER_BUF_SZ];
int ret;
- /* only works for page backed storage */
- if (!vma->vm_file)
- return -EINVAL;
-
- freader_init_from_file(&r, buf, sizeof(buf), vma->vm_file, may_fault);
+ freader_init_from_file(&r, buf, sizeof(buf), file, may_fault);
/* fetch first 18 bytes of ELF header for checks */
ehdr = freader_fetch(&r, 0, offsetofend(Elf32_Ehdr, e_type));
@@ -319,8 +315,8 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
return ret;
}
-/*
- * Parse build ID of ELF file mapped to vma
+/**
+ * build_id_parse_nofault() - Parse build ID of ELF file mapped to vma
* @vma: vma object
* @build_id: buffer to store build id, at least BUILD_ID_SIZE long
* @size: returns actual build id size in case of success
@@ -332,11 +328,14 @@ static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
*/
int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
{
- return __build_id_parse(vma, build_id, size, false /* !may_fault */);
+ if (!vma->vm_file)
+ return -EINVAL;
+
+ return __build_id_parse(vma->vm_file, build_id, size, false /* !may_fault */);
}
-/*
- * Parse build ID of ELF file mapped to VMA
+/**
+ * build_id_parse() - Parse build ID of ELF file mapped to VMA
* @vma: vma object
* @build_id: buffer to store build id, at least BUILD_ID_SIZE long
* @size: returns actual build id size in case of success
@@ -348,7 +347,26 @@ int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id,
*/
int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
{
- return __build_id_parse(vma, build_id, size, true /* may_fault */);
+ if (!vma->vm_file)
+ return -EINVAL;
+
+ return __build_id_parse(vma->vm_file, build_id, size, true /* may_fault */);
+}
+
+/**
+ * build_id_parse_file() - Parse build ID of ELF file
+ * @file: file object
+ * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
+ * @size: returns actual build id size in case of success
+ *
+ * Assumes faultable context and can cause page faults to bring in file data
+ * into page cache.
+ *
+ * Return: 0 on success; negative error, otherwise
+ */
+int build_id_parse_file(struct file *file, unsigned char *build_id, __u32 *size)
+{
+ return __build_id_parse(file, build_id, size, true /* may_fault */);
}
/**

View File

@ -0,0 +1,57 @@
From a942817e22deae157ab3431184f3a760e616f696 Mon Sep 17 00:00:00 2001
From: Rafael Aquini <raquini@redhat.com>
Date: Wed, 1 Jul 2026 16:38:58 -0400
Subject: [PATCH] procfs: fix possible double mmput() in do_procmap_query()
JIRA: https://redhat.atlassian.net/browse/RHEL-189666
CVE: CVE-2026-23199
commit 61dc9f776705d6db6847c101b98fa4f0e9eb6fa3
Author: Andrii Nakryiko <andrii@kernel.org>
Date: Tue Feb 10 11:27:38 2026 -0800
procfs: fix possible double mmput() in do_procmap_query()
When user provides incorrectly sized buffer for build ID for PROCMAP_QUERY
we return with -ENAMETOOLONG error. After recent changes this condition
happens later, after we unlocked mmap_lock/per-VMA lock and did mmput(),
so original goto out is now wrong and will double-mmput() mm_struct. Fix
by jumping further to clean up only vm_file and name_buf.
Link: https://lkml.kernel.org/r/20260210192738.3041609-1-andrii@kernel.org
Fixes: b5cbacd7f86f ("procfs: avoid fetching build ID while holding VMA lock")
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reported-by: Ruikai Peng <ruikai@pwno.io>
Reported-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev>
Reported-by: syzbot+237b5b985b78c1da9600@syzkaller.appspotmail.com
Cc: Ruikai Peng <ruikai@pwno.io>
Closes: https://lkml.kernel.org/r/CAFD3drOJANTZPuyiqMdqpiRwOKnHwv5QgMNZghCDr-WxdiHvMg@mail.gmail.com
Closes: https://lore.kernel.org/all/698aaf3c.050a0220.3b3015.0088.GAE@google.com/T/#u
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Rafael Aquini <raquini@redhat.com>
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 27cc491..a574e8d 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -581,7 +581,7 @@ static int do_procmap_query(struct proc_maps_private *priv, void __user *uarg)
} else {
if (karg.build_id_size < build_id_sz) {
err = -ENAMETOOLONG;
- goto out;
+ goto out_file;
}
karg.build_id_size = build_id_sz;
}
@@ -609,6 +609,7 @@ static int do_procmap_query(struct proc_maps_private *priv, void __user *uarg)
out:
query_vma_teardown(mm, vma);
mmput(mm);
+out_file:
if (vm_file)
fput(vm_file);
kfree(name_buf);

View File

@ -0,0 +1,43 @@
From eb4a7139e97374f42b7242cc754e77f1623fbcd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
Date: Thu, 12 Feb 2026 08:27:31 +0200
Subject: [PATCH] drm/i915/alpm: ALPM disable fixes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
PORT_ALPM_CTL is supposed to be written only before link training. Remove
writing it from ALPM disable.
Also clearing ALPM_CTL_ALPM_AUX_LESS_ENABLE and is not about disabling ALPM
but switching to AUX-Wake ALPM. Stop touching this bit on ALPM disable.
Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/7153
Fixes: 1ccbf135862b ("drm/i915/psr: Enable ALPM on source side for eDP Panel replay")
Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: <stable@vger.kernel.org> # v6.10+
Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: Michał Grzelak <michal.grzelak@intel.com>
Link: https://patch.msgid.link/20260212062731.397801-1-jouni.hogander@intel.com
(cherry picked from commit 008304c9ae75c772d3460040de56e12112cdf5e6)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c
index ed7a7ed..2aed386 100644
--- a/drivers/gpu/drm/i915/display/intel_alpm.c
+++ b/drivers/gpu/drm/i915/display/intel_alpm.c
@@ -577,12 +577,7 @@ void intel_alpm_disable(struct intel_dp *intel_dp)
mutex_lock(&intel_dp->alpm_parameters.lock);
intel_de_rmw(display, ALPM_CTL(display, cpu_transcoder),
- ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE |
- ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
-
- intel_de_rmw(display,
- PORT_ALPM_CTL(cpu_transcoder),
- PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0);
+ ALPM_CTL_ALPM_ENABLE | ALPM_CTL_LOBF_ENABLE, 0);
drm_dbg_kms(display->drm, "Disabling ALPM\n");
mutex_unlock(&intel_dp->alpm_parameters.lock);

View File

@ -0,0 +1,47 @@
From 69f83f167463bad26104af7fbc114ce1f80366b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
Date: Thu, 15 Jan 2026 09:00:39 +0200
Subject: [PATCH] drm/i915/psr: Don't enable Panel Replay on sink if globally
disabled
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
With some panels informing support for Panel Replay we are observing
problems if having Panel Replay enable bit set on sink when forced to use
PSR instead of Panel Replay. Avoid these problems by not setting Panel
Replay enable bit in sink when Panel Replay is globally disabled during
link training. I.e. disabled by module parameter.
The enable bit is still set when disabling Panel Replay via debugfs
interface. Added note comment about this.
Fixes: 68f3a505b367 ("drm/i915/psr: Enable Panel Replay on sink always when it's supported")
Cc: Mika Kahola <mika.kahola@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: <stable@vger.kernel.org> # v6.15+
Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: Mika Kahola <mika.kahola@intel.com>
Link: https://patch.msgid.link/20260115070039.368965-1-jouni.hogander@intel.com
(cherry picked from commit c5a52cd04e24f0ae53fda26f74ab027b8c548e0e)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 5adbf7a..69cbaa5 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -856,7 +856,12 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp,
void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp)
{
- if (CAN_PANEL_REPLAY(intel_dp))
+ /*
+ * NOTE: We might want to trigger mode set when
+ * disabling/enabling Panel Replay via debugfs interface to
+ * ensure this bit is cleared/set accordingly.
+ */
+ if (CAN_PANEL_REPLAY(intel_dp) && panel_replay_global_enabled(intel_dp))
drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG,
DP_PANEL_REPLAY_ENABLE);
}

View File

@ -0,0 +1,72 @@
From 8bb9093df555f9e89fdbe1405118b11384c03e04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
Date: Wed, 20 May 2026 13:49:43 +0300
Subject: [PATCH] drm/i915/psr: Block DC states on vblank enable when Panel
Replay supported
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Currently we are blocking DC states only when Panel Replay is enabled on
vblank enable. It may happen that Panel Replay is getting enabled when
vblank is already enabled. Fix this by blocking DC states always if Panel
Replay is supported.
While at it take care of possible dual eDP case by looping all encoders
supporting PSR.
Fixes: 0c427ac78a1d ("drm/i915/psr: Add interface to notify PSR of vblank enable/disable")
Cc: <stable@vger.kernel.org> # v6.16+
Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: Michał Grzelak <michal.grzelak@intel.com>
Link: https://patch.msgid.link/20260520104944.239797-1-jouni.hogander@intel.com
(cherry picked from commit eb5911f990554f7ce947dd53df00c114362e4465)
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 69cbaa5..c805c69 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3984,32 +3984,33 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
bool enable)
{
struct intel_encoder *encoder;
+ bool block_dc_states = false;
for_each_intel_encoder_with_psr(display->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
mutex_lock(&intel_dp->psr.lock);
- if (intel_dp->psr.panel_replay_enabled) {
- mutex_unlock(&intel_dp->psr.lock);
- break;
- }
+ if (CAN_PANEL_REPLAY(intel_dp))
+ block_dc_states = true;
- if (intel_dp->psr.enabled && intel_dp->psr.pkg_c_latency_used)
+ if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled &&
+ intel_dp->psr.pkg_c_latency_used)
intel_psr_apply_underrun_on_idle_wa_locked(intel_dp);
mutex_unlock(&intel_dp->psr.lock);
- return;
}
/*
* NOTE: intel_display_power_set_target_dc_state is used
- * only by PSR * code for DC3CO handling. DC3CO target
+ * only by PSR code for DC3CO handling. DC3CO target
* state is currently disabled in * PSR code. If DC3CO
* is taken into use we need take that into account here
* as well.
*/
- intel_display_power_set_target_dc_state(display, enable ? DC_STATE_DISABLE :
- DC_STATE_EN_UPTO_DC6);
+ if (block_dc_states)
+ intel_display_power_set_target_dc_state(display, enable ?
+ DC_STATE_DISABLE :
+ DC_STATE_EN_UPTO_DC6);
}
static void

View File

@ -0,0 +1,139 @@
From 3549a9649dc7c5fc586ab12f675279283cdcb2a7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jouni=20H=C3=B6gander?= <jouni.hogander@intel.com>
Date: Wed, 20 May 2026 13:49:44 +0300
Subject: [PATCH] drm/i915/psr: Use DC_OFF wake reference to block DC6 on
vblank enable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
We are observing following warnings:
*ERROR* power well DC_off state mismatch (refcount 0/enabled 1)
gen9_dc_off_power_well_enabled is considering target state DC_STATE_DISABLE
as DC_OFF power well being enabled. Fix this by using wakeref for the
purpose.
To achieve this we need to modify notification code as well. Currently it
is possible that PSR gets notified vblank enable/disable twice on same
status. This is currently not a problem as it is just triggering call to
intel_display_power_set_target_dc_state with same target state as a
parameter. When using wakeref this becomes a problem due to reference
counting. Fix this storing vbank status on last notification and use that
to ensure there are no more than one notification with same vblank status.
v2: ensure there is no subsequent notifications with same status
Fixes: aa451abcffb5 ("drm/i915/display: Prevent DC6 while vblank is enabled for Panel Replay")
Cc: <stable@vger.kernel.org> # v6.13+
Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
Reviewed-by: Michał Grzelak <michal.grzelak@intel.com>
Link: https://patch.msgid.link/20260520104944.239797-2-jouni.hogander@intel.com
(cherry picked from commit 35485ac56d878192a3829a58cb26503125ec7104)
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 8c22640..800a30b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -472,6 +472,7 @@ struct intel_display {
u8 vblank_enabled;
int vblank_enable_count;
+ bool vblank_status_last_notified;
struct work_struct vblank_notify_work;
diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
index 123e054..21b2a19 100644
--- a/drivers/gpu/drm/i915/display/intel_display_irq.c
+++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
@@ -1707,8 +1707,12 @@ static void intel_display_vblank_notify_work(struct work_struct *work)
struct intel_display *display =
container_of(work, typeof(*display), irq.vblank_notify_work);
int vblank_enable_count = READ_ONCE(display->irq.vblank_enable_count);
+ bool vblank_status = !!vblank_enable_count;
- intel_psr_notify_vblank_enable_disable(display, vblank_enable_count);
+ if (display->irq.vblank_status_last_notified != vblank_status) {
+ intel_psr_notify_vblank_enable_disable(display, vblank_status);
+ display->irq.vblank_status_last_notified = vblank_status;
+ }
}
int bdw_enable_vblank(struct drm_crtc *_crtc)
@@ -1721,10 +1725,10 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
if (gen11_dsi_configure_te(crtc, true))
return 0;
+ spin_lock_irqsave(&display->irq.lock, irqflags);
if (crtc->vblank_psr_notify && display->irq.vblank_enable_count++ == 0)
schedule_work(&display->irq.vblank_notify_work);
- spin_lock_irqsave(&display->irq.lock, irqflags);
bdw_enable_pipe_irq(display, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&display->irq.lock, irqflags);
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 9995663..05da837 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1700,6 +1700,10 @@ struct intel_psr {
bool pkg_c_latency_used;
u8 active_non_psr_pipes;
+
+ const char *no_psr_reason;
+
+ struct ref_tracker *vblank_wakeref;
};
struct intel_dp {
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index c805c69..4747cff 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -3984,14 +3984,20 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
bool enable)
{
struct intel_encoder *encoder;
- bool block_dc_states = false;
for_each_intel_encoder_with_psr(display->drm, encoder) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
mutex_lock(&intel_dp->psr.lock);
- if (CAN_PANEL_REPLAY(intel_dp))
- block_dc_states = true;
+ if (CAN_PANEL_REPLAY(intel_dp)) {
+ if (enable)
+ intel_dp->psr.vblank_wakeref =
+ intel_display_power_get(display,
+ POWER_DOMAIN_DC_OFF);
+ else
+ intel_display_power_put(display, POWER_DOMAIN_DC_OFF,
+ intel_dp->psr.vblank_wakeref);
+ }
if (intel_dp->psr.enabled && !intel_dp->psr.panel_replay_enabled &&
intel_dp->psr.pkg_c_latency_used)
@@ -3999,18 +4005,6 @@ void intel_psr_notify_vblank_enable_disable(struct intel_display *display,
mutex_unlock(&intel_dp->psr.lock);
}
-
- /*
- * NOTE: intel_display_power_set_target_dc_state is used
- * only by PSR code for DC3CO handling. DC3CO target
- * state is currently disabled in * PSR code. If DC3CO
- * is taken into use we need take that into account here
- * as well.
- */
- if (block_dc_states)
- intel_display_power_set_target_dc_state(display, enable ?
- DC_STATE_DISABLE :
- DC_STATE_EN_UPTO_DC6);
}
static void

View File

@ -0,0 +1,79 @@
From 7c9c0da42abb4835933201861f979a5ef152f185 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Tue, 12 May 2026 13:04:40 +0200
Subject: [PATCH] dpll: export __dpll_pin_change_ntf() for use under dpll_lock
JIRA: https://redhat.atlassian.net/browse/RHEL-137412
commit 620055cb1036a6125fd912e7a14b47a6572b809b
Author: Ivan Vecera <ivecera@redhat.com>
Date: Mon Apr 27 22:22:21 2026 -0700
dpll: export __dpll_pin_change_ntf() for use under dpll_lock
Export __dpll_pin_change_ntf() so that drivers can send pin change
notifications from within pin callbacks, which are already called
under dpll_lock. Using dpll_pin_change_ntf() in that context would
deadlock.
Add lockdep_assert_held() to catch misuse without the lock held.
Acked-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Signed-off-by: Petr Oros <poros@redhat.com>
Tested-by: Alexander Nowlin <alexander.nowlin@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260427-jk-iwl-net-petr-oros-fixes-v1-9-cdcb48303fd8@intel.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 1d860eb..6c28b8f 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -938,11 +938,21 @@ int dpll_pin_delete_ntf(struct dpll_pin *pin)
return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
}
+/**
+ * __dpll_pin_change_ntf - notify that the pin has been changed
+ * @pin: registered pin pointer
+ *
+ * Context: caller must hold dpll_lock. Suitable for use inside pin
+ * callbacks which are already invoked under dpll_lock.
+ * Return: 0 if succeeds, error code otherwise.
+ */
int __dpll_pin_change_ntf(struct dpll_pin *pin)
{
+ lockdep_assert_held(&dpll_lock);
dpll_pin_notify(pin, DPLL_PIN_CHANGED);
return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
}
+EXPORT_SYMBOL_GPL(__dpll_pin_change_ntf);
/**
* dpll_pin_change_ntf - notify that the pin has been changed
diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
index dd28b56..a9cfd55 100644
--- a/drivers/dpll/dpll_netlink.h
+++ b/drivers/dpll/dpll_netlink.h
@@ -11,5 +11,3 @@ int dpll_device_delete_ntf(struct dpll_device *dpll);
int dpll_pin_create_ntf(struct dpll_pin *pin);
int dpll_pin_delete_ntf(struct dpll_pin *pin);
-
-int __dpll_pin_change_ntf(struct dpll_pin *pin);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index d988c09..4a8854a 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -338,6 +338,7 @@ int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin,
int dpll_device_change_ntf(struct dpll_device *dpll);
+int __dpll_pin_change_ntf(struct dpll_pin *pin);
int dpll_pin_change_ntf(struct dpll_pin *pin);
int register_dpll_notifier(struct notifier_block *nb);

View File

@ -0,0 +1,67 @@
From 67455700958bf8d6868d2ba366556948f36b17b1 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:13:47 +0200
Subject: [PATCH] dpll: Prevent duplicate registrations
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit f3ddbaaaaf4d0633b40482f471753f9c71294a4a
Author: Ivan Vecera <ivecera@redhat.com>
Date: Wed Jan 21 14:00:11 2026 +0100
dpll: Prevent duplicate registrations
Modify the internal registration helpers dpll_xa_ref_{dpll,pin}_add()
to reject duplicate registration attempts.
Previously, if a caller attempted to register the same pin multiple
times (with the same ops, priv, and cookie) on the same device, the core
silently increments the reference count and return success. This behavior
is incorrect because if the caller makes these duplicate registrations
then for the first one dpll_pin_registration is allocated and for others
the associated dpll_pin_ref.refcount is incremented. During the first
unregistration the associated dpll_pin_registration is freed and for
others WARN is fired.
Fix this by updating the logic to return `-EEXIST` if a matching
registration is found to enforce a strict "register once" policy.
Fixes: 9431063ad323 ("dpll: core: Add DPLL framework base functions")
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20260121130012.112606-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 8b260a3..f1b76fc 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -198,10 +198,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
if (ref->pin != pin)
continue;
reg = dpll_pin_registration_find(ref, ops, priv, cookie);
- if (reg) {
- refcount_inc(&ref->refcount);
- return 0;
- }
+ if (reg)
+ return -EEXIST;
ref_exists = true;
break;
}
@@ -281,10 +279,8 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
if (ref->dpll != dpll)
continue;
reg = dpll_pin_registration_find(ref, ops, priv, cookie);
- if (reg) {
- refcount_inc(&ref->refcount);
- return 0;
- }
+ if (reg)
+ return -EEXIST;
ref_exists = true;
break;
}

View File

@ -0,0 +1,54 @@
From c9a2d9869828d1f8e0c86f78358c0f36aa75a632 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:13:50 +0200
Subject: [PATCH] dpll: zl3073x: Use named initializers for struct
i2c_device_id
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit a09dfac0296dff2521bf53b8f53a7c0d83607782
Author: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
Date: Tue May 19 16:27:10 2026 +0200
dpll: zl3073x: Use named initializers for struct i2c_device_id
While being less compact, using named initializers allows to more easily
see which members of the structs are assigned which value without having
to lookup the declaration of the struct. And it's also more robust
against changes to the struct definition.
This patch doesn't modify the compiled arrays, only their representation
in source form benefits. The former was confirmed with x86 and arm64
builds.
Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
Reviewed-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260519142710.1587324-2-u.kleine-koenig@baylibre.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/zl3073x/i2c.c b/drivers/dpll/zl3073x/i2c.c
index 979df85..4a23340 100644
--- a/drivers/dpll/zl3073x/i2c.c
+++ b/drivers/dpll/zl3073x/i2c.c
@@ -26,11 +26,11 @@ static int zl3073x_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id zl3073x_i2c_id[] = {
- { "zl30731" },
- { "zl30732" },
- { "zl30733" },
- { "zl30734" },
- { "zl30735" },
+ { .name = "zl30731" },
+ { .name = "zl30732" },
+ { .name = "zl30733" },
+ { .name = "zl30734" },
+ { .name = "zl30735" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id);

View File

@ -0,0 +1,60 @@
From a0afb5efe1c574c74950558f3286dbbb78ada44f Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:13:51 +0200
Subject: [PATCH] dpll: zl3073x: fix memory leak on pin registration failure
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit fa997ddef508b1b37b2fe4d2dad7c4b70958335e
Author: Ivan Vecera <ivecera@redhat.com>
Date: Tue May 19 15:22:05 2026 +0200
dpll: zl3073x: fix memory leak on pin registration failure
If zl3073x_dpll_pin_register() fails, the allocated pin is not yet
added to zldpll->pins list. The error path calls
zl3073x_dpll_pins_unregister() which only iterates pins on the list,
so the current pin is leaked. Free the pin before jumping to the error
label.
Additionally move the pin->dpll_pin = NULL assignment in
zl3073x_dpll_pin_register() from err_register to the common
err_pin_get path. When dpll_pin_get() fails, pin->dpll_pin holds an
ERR_PTR value. Without this fix the subsequent zl3073x_dpll_pin_free()
would trigger a spurious WARN because it checks pin->dpll_pin for
non-NULL.
Fixes: 75a71ecc2412 ("dpll: zl3073x: Register DPLL devices and pins")
Reviewed-by: Petr Oros <poros@redhat.com>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260519132205.161847-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index 6b714ec..03ee4df 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -1434,8 +1434,8 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
err_register:
dpll_pin_put(pin->dpll_pin, &pin->tracker);
- pin->dpll_pin = NULL;
err_pin_get:
+ pin->dpll_pin = NULL;
fwnode_handle_put(pin->fwnode);
pin->fwnode = NULL;
zl3073x_pin_props_put(props);
@@ -1603,8 +1603,10 @@ zl3073x_dpll_pins_register(struct zl3073x_dpll *zldpll)
}
rc = zl3073x_dpll_pin_register(pin, index);
- if (rc)
+ if (rc) {
+ zl3073x_dpll_pin_free(pin);
goto error;
+ }
list_add(&pin->list, &zldpll->pins);
}

View File

@ -0,0 +1,110 @@
From 5106bbc6e840150a786f93951713a2d122be7cdc Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:13:53 +0200
Subject: [PATCH] dpll: change dpll_netdev_pin_handle_size() to assume
DPLL_A_PIN_ID will be used
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 7409fad779e271f252d844ae16e1a7429626b13e
Author: Eric Dumazet <edumazet@google.com>
Date: Thu May 21 17:14:39 2026 +0000
dpll: change dpll_netdev_pin_handle_size() to assume DPLL_A_PIN_ID will be used
We plan to no longer hold RTNL in "ip link show", and use RCU instead.
Assume rtnl_fill_dpll_pin() will have to fill DPLL_A_PIN_ID.
It is fine to over-estimate skb size (by 8 bytes) in if_nlmsg_size().
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20260521171440.114956-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 6c28b8f..2604fa9 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -89,17 +89,6 @@ static struct dpll_pin *dpll_netdev_pin(const struct net_device *dev)
return rcu_dereference_rtnl(dev->dpll_pin);
}
-/**
- * dpll_netdev_pin_handle_size - get size of pin handle attribute of a netdev
- * @dev: netdev from which to get the pin
- *
- * Return: byte size of pin handle attribute, or 0 if @dev has no pin.
- */
-size_t dpll_netdev_pin_handle_size(const struct net_device *dev)
-{
- return dpll_netdev_pin(dev) ? nla_total_size(4) : 0; /* DPLL_A_PIN_ID */
-}
-
int dpll_netdev_add_pin_handle(struct sk_buff *msg,
const struct net_device *dev)
{
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 4a8854a..ff7ff18 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -13,6 +13,7 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/rtnetlink.h>
+#include <net/netlink.h>
#include <linux/rh_kabi.h>
@@ -270,7 +271,11 @@ struct dpll_pin_notifier_info {
void dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin);
void dpll_netdev_pin_clear(struct net_device *dev);
-size_t dpll_netdev_pin_handle_size(const struct net_device *dev);
+static inline size_t dpll_netdev_pin_handle_size(void)
+{
+ return nla_total_size(4); /* DPLL_A_PIN_ID */
+}
+
int dpll_netdev_add_pin_handle(struct sk_buff *msg,
const struct net_device *dev);
@@ -281,7 +286,7 @@ static inline void
dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) { }
static inline void dpll_netdev_pin_clear(struct net_device *dev) { }
-static inline size_t dpll_netdev_pin_handle_size(const struct net_device *dev)
+static inline size_t dpll_netdev_pin_handle_size(void)
{
return 0;
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 10a6a25..a0b5d5a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1087,11 +1087,11 @@ static size_t rtnl_devlink_port_size(const struct net_device *dev)
return size;
}
-static size_t rtnl_dpll_pin_size(const struct net_device *dev)
+static size_t rtnl_dpll_pin_size(void)
{
size_t size = nla_total_size(0); /* nest IFLA_DPLL_PIN */
- size += dpll_netdev_pin_handle_size(dev);
+ size += dpll_netdev_pin_handle_size();
return size;
}
@@ -1152,7 +1152,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
+ rtnl_prop_list_size(dev)
+ nla_total_size(MAX_ADDR_LEN) /* IFLA_PERM_ADDRESS */
+ rtnl_devlink_port_size(dev)
- + rtnl_dpll_pin_size(dev)
+ + rtnl_dpll_pin_size()
+ nla_total_size(8) /* IFLA_MAX_PACING_OFFLOAD_HORIZON */
+ 0;
}

View File

@ -0,0 +1,68 @@
From 41e5e87efc968b8591fb46e1014469d697031e82 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:13:55 +0200
Subject: [PATCH] dpll: export __dpll_device_change_ntf() for use under
dpll_lock
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 20040b2a3cb992f84d3db4c086b909eb9b906b31
Author: Ivan Vecera <ivecera@redhat.com>
Date: Tue May 26 09:45:23 2026 +0200
dpll: export __dpll_device_change_ntf() for use under dpll_lock
Export __dpll_device_change_ntf() so that drivers can send device
change notifications from within device callbacks, which are already
called under dpll_lock. Using dpll_device_change_ntf() in that
context would deadlock.
Add lockdep_assert_held() to catch misuse without the lock held.
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20260526074525.1451008-2-ivecera@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 2604fa9..7a86b86 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -856,12 +856,21 @@ int dpll_device_delete_ntf(struct dpll_device *dpll)
return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
}
-static int
-__dpll_device_change_ntf(struct dpll_device *dpll)
+/**
+ * __dpll_device_change_ntf - notify that the dpll device has been changed
+ * @dpll: registered dpll pointer
+ *
+ * Context: caller must hold dpll_lock. Suitable for use inside device
+ * callbacks which are already invoked under dpll_lock.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int __dpll_device_change_ntf(struct dpll_device *dpll)
{
+ lockdep_assert_held(&dpll_lock);
dpll_device_notify(dpll, DPLL_DEVICE_CHANGED);
return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
}
+EXPORT_SYMBOL_GPL(__dpll_device_change_ntf);
/**
* dpll_device_change_ntf - notify that the dpll device has been changed
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index ff7ff18..5ee402f 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -341,6 +341,7 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin,
struct dpll_pin *ref_sync_pin);
+int __dpll_device_change_ntf(struct dpll_device *dpll);
int dpll_device_change_ntf(struct dpll_device *dpll);
int __dpll_pin_change_ntf(struct dpll_pin *pin);

View File

@ -0,0 +1,113 @@
From 4177e352ca1390d614e458e8a0929a63ba6a17e3 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:13:57 +0200
Subject: [PATCH] dpll: zl3073x: use __dpll_device_change_ntf() and remove
change_work
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit d733f519f6443540f8359461a34e3b0042099bbe
Author: Ivan Vecera <ivecera@redhat.com>
Date: Tue May 26 09:45:24 2026 +0200
dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work
The change_work was introduced to send device change notifications
from DPLL device callbacks without deadlocking on dpll_lock, since
the callbacks are already invoked under that lock. Now that
__dpll_device_change_ntf() is exported for callers that already
hold dpll_lock, use it directly and remove the change_work
infrastructure entirely.
This eliminates a race condition where change_work could be
re-scheduled after cancel_work_sync() during device teardown,
potentially causing the handler to dereference a freed or NULL
dpll_dev pointer.
Fixes: 9363b4837659 ("dpll: zl3073x: Allow to configure phase offset averaging factor")
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260526074525.1451008-3-ivecera@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index 03ee4df..98750f3 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -1117,15 +1117,6 @@ zl3073x_dpll_phase_offset_avg_factor_get(const struct dpll_device *dpll,
return 0;
}
-static void
-zl3073x_dpll_change_work(struct work_struct *work)
-{
- struct zl3073x_dpll *zldpll;
-
- zldpll = container_of(work, struct zl3073x_dpll, change_work);
- dpll_device_change_ntf(zldpll->dpll_dev);
-}
-
static int
zl3073x_dpll_phase_offset_avg_factor_set(const struct dpll_device *dpll,
void *dpll_priv, u32 factor,
@@ -1151,8 +1142,10 @@ zl3073x_dpll_phase_offset_avg_factor_set(const struct dpll_device *dpll,
* we have to send a notification for other DPLL devices.
*/
list_for_each_entry(item, &zldpll->dev->dplls, list) {
- if (item != zldpll)
- schedule_work(&item->change_work);
+ struct dpll_device *dpll_dev = READ_ONCE(item->dpll_dev);
+
+ if (item != zldpll && dpll_dev)
+ __dpll_device_change_ntf(dpll_dev);
}
return 0;
@@ -1667,13 +1660,13 @@ zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll)
static void
zl3073x_dpll_device_unregister(struct zl3073x_dpll *zldpll)
{
- WARN(!zldpll->dpll_dev, "DPLL device is not registered\n");
+ struct dpll_device *dpll_dev = READ_ONCE(zldpll->dpll_dev);
- cancel_work_sync(&zldpll->change_work);
+ WARN(!dpll_dev, "DPLL device is not registered\n");
- dpll_device_unregister(zldpll->dpll_dev, &zldpll->ops, zldpll);
- dpll_device_put(zldpll->dpll_dev, &zldpll->tracker);
- zldpll->dpll_dev = NULL;
+ WRITE_ONCE(zldpll->dpll_dev, NULL);
+ dpll_device_unregister(dpll_dev, &zldpll->ops, zldpll);
+ dpll_device_put(dpll_dev, &zldpll->tracker);
}
/**
@@ -1958,7 +1951,6 @@ zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch)
zldpll->dev = zldev;
zldpll->id = ch;
INIT_LIST_HEAD(&zldpll->pins);
- INIT_WORK(&zldpll->change_work, zl3073x_dpll_change_work);
return zldpll;
}
diff --git a/drivers/dpll/zl3073x/dpll.h b/drivers/dpll/zl3073x/dpll.h
index 434c32a..c8bc843 100644
--- a/drivers/dpll/zl3073x/dpll.h
+++ b/drivers/dpll/zl3073x/dpll.h
@@ -21,7 +21,6 @@
* @tracker: tracking object for the acquired reference
* @lock_status: last saved DPLL lock status
* @pins: list of pins
- * @change_work: device change notification work
*/
struct zl3073x_dpll {
struct list_head list;
@@ -35,7 +34,6 @@ struct zl3073x_dpll {
dpll_tracker tracker;
enum dpll_lock_status lock_status;
struct list_head pins;
- struct work_struct change_work;
};
struct zl3073x_dpll *zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch);

View File

@ -0,0 +1,195 @@
From 057880fb4e1f962b89823aa4ad489c36f8fad099 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:00 +0200
Subject: [PATCH] dpll: zl3073x: make frequency monitor a per-device attribute
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
Conflicts:
- One line context difference in zl3073x_dev_periodic_work()
due to already backported 54e65df8cf18a ("dpll: zl3073x:
report FFO as DPLL vs input reference offset").
- A fake conflict in zl3073x_dpll_freq_monitor_set() due to
the upstream and downstream diff being rendered differently,
but representing exactly the same code change.
commit c1224569cef038b040db0459510cd7948ecd467b
Author: Ivan Vecera <ivecera@redhat.com>
Date: Tue May 26 09:45:25 2026 +0200
dpll: zl3073x: make frequency monitor a per-device attribute
The frequency monitoring feature uses shared hardware registers
that measure input reference frequencies independently of
individual DPLL channels. However, the freq_monitor flag was
incorrectly placed in the per-DPLL structure, causing each
channel to track its own enable/disable state independently.
Since the DPLL core calls measured_freq_get() only for the first
pin registration, the measured_freq_check() in the periodic worker
was gated by the per-DPLL freq_monitor flag of whichever channel
happens to be checked. If the first DPLL channel had frequency
monitoring disabled while another had it enabled, measurements
were never reported.
Move freq_monitor from struct zl3073x_dpll to struct zl3073x_dev
so all DPLL channels share a single flag, matching the hardware
behavior. Update freq_monitor_set() to notify other DPLL devices
about the change (like phase_offset_avg_factor_set() already does)
and remove the mode-dependent guard in zl3073x_dpll_changes_check()
since all input pin monitoring (pin state, phase offset, FFO, and
measured frequency) works correctly in all DPLL modes.
Fixes: bfc923b642874 ("dpll: zl3073x: implement frequency monitoring")
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Link: https://patch.msgid.link/20260526074525.1451008-4-ivecera@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c
index b334506..8e6416a 100644
--- a/drivers/dpll/zl3073x/core.c
+++ b/drivers/dpll/zl3073x/core.c
@@ -724,18 +724,15 @@ zl3073x_dev_periodic_work(struct kthread_work *work)
dev_warn(zldev->dev, "Failed to update phase offsets: %pe\n",
ERR_PTR(rc));
- /* Update measured input reference frequencies if any DPLL has
- * frequency monitoring enabled.
+ /* Update measured input reference frequencies if frequency
+ * monitoring is enabled.
*/
- list_for_each_entry(zldpll, &zldev->dplls, list) {
- if (zldpll->freq_monitor) {
- rc = zl3073x_ref_freq_meas_update(zldev);
- if (rc)
- dev_warn(zldev->dev,
- "Failed to update measured frequencies: %pe\n",
- ERR_PTR(rc));
- break;
- }
+ if (zldev->freq_monitor) {
+ rc = zl3073x_ref_freq_meas_update(zldev);
+ if (rc)
+ dev_warn(zldev->dev,
+ "Failed to update measured frequencies: %pe\n",
+ ERR_PTR(rc));
}
list_for_each_entry(zldpll, &zldev->dplls, list)
diff --git a/drivers/dpll/zl3073x/core.h b/drivers/dpll/zl3073x/core.h
index 9944062..addba37 100644
--- a/drivers/dpll/zl3073x/core.h
+++ b/drivers/dpll/zl3073x/core.h
@@ -57,6 +57,7 @@ struct zl3073x_chip_info {
* @work: periodic work
* @clock_id: clock id of the device
* @phase_avg_factor: phase offset measurement averaging factor
+ * @freq_monitor: is frequency monitor enabled
*/
struct zl3073x_dev {
struct device *dev;
@@ -77,9 +78,10 @@ struct zl3073x_dev {
struct kthread_worker *kworker;
struct kthread_delayed_work work;
- /* Devlink parameters */
+ /* Per-chip parameters */
u64 clock_id;
u8 phase_avg_factor;
+ bool freq_monitor;
};
extern const struct regmap_config zl3073x_regmap_config;
diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
index 98750f3..9f66aac 100644
--- a/drivers/dpll/zl3073x/dpll.c
+++ b/drivers/dpll/zl3073x/dpll.c
@@ -1250,7 +1250,7 @@ zl3073x_dpll_freq_monitor_get(const struct dpll_device *dpll,
{
struct zl3073x_dpll *zldpll = dpll_priv;
- if (zldpll->freq_monitor)
+ if (zldpll->dev->freq_monitor)
*state = DPLL_FEATURE_STATE_ENABLE;
else
*state = DPLL_FEATURE_STATE_DISABLE;
@@ -1264,9 +1264,19 @@ zl3073x_dpll_freq_monitor_set(const struct dpll_device *dpll,
enum dpll_feature_state state,
struct netlink_ext_ack *extack)
{
- struct zl3073x_dpll *zldpll = dpll_priv;
+ struct zl3073x_dpll *item, *zldpll = dpll_priv;
+
+ zldpll->dev->freq_monitor = (state == DPLL_FEATURE_STATE_ENABLE);
+
+ /* The frequency monitoring is common for all DPLL channels so after
+ * change we have to send a notification for other DPLL devices.
+ */
+ list_for_each_entry(item, &zldpll->dev->dplls, list) {
+ struct dpll_device *dpll_dev = READ_ONCE(item->dpll_dev);
- zldpll->freq_monitor = (state == DPLL_FEATURE_STATE_ENABLE);
+ if (item != zldpll && dpll_dev)
+ __dpll_device_change_ntf(dpll_dev);
+ }
return 0;
}
@@ -1777,7 +1787,7 @@ zl3073x_dpll_pin_measured_freq_check(struct zl3073x_dpll_pin *pin)
u8 ref_id;
u32 freq;
- if (!zldpll->freq_monitor)
+ if (!zldpll->dev->freq_monitor)
return false;
ref_id = zl3073x_input_pin_ref_get(pin->id);
@@ -1810,10 +1820,8 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
struct zl3073x_dev *zldev = zldpll->dev;
enum dpll_lock_status lock_status;
struct device *dev = zldev->dev;
- const struct zl3073x_chan *chan;
struct zl3073x_dpll_pin *pin;
int rc;
- u8 mode;
zldpll->check_count++;
@@ -1832,15 +1840,6 @@ zl3073x_dpll_changes_check(struct zl3073x_dpll *zldpll)
dpll_device_change_ntf(zldpll->dpll_dev);
}
- /* Input pin monitoring does make sense only in automatic
- * or forced reference modes.
- */
- chan = zl3073x_chan_state_get(zldev, zldpll->id);
- mode = zl3073x_chan_mode_get(chan);
- if (mode != ZL_DPLL_MODE_REFSEL_MODE_AUTO &&
- mode != ZL_DPLL_MODE_REFSEL_MODE_REFLOCK)
- return;
-
/* Update phase offset latch registers for this DPLL if the phase
* offset monitor feature is enabled.
*/
diff --git a/drivers/dpll/zl3073x/dpll.h b/drivers/dpll/zl3073x/dpll.h
index c8bc843..21adcc1 100644
--- a/drivers/dpll/zl3073x/dpll.h
+++ b/drivers/dpll/zl3073x/dpll.h
@@ -15,7 +15,6 @@
* @id: DPLL index
* @check_count: periodic check counter
* @phase_monitor: is phase offset monitor enabled
- * @freq_monitor: is frequency monitor enabled
* @ops: DPLL device operations for this instance
* @dpll_dev: pointer to registered DPLL device
* @tracker: tracking object for the acquired reference
@@ -28,7 +27,6 @@ struct zl3073x_dpll {
u8 id;
u8 check_count;
bool phase_monitor;
- bool freq_monitor;
struct dpll_device_ops ops;
struct dpll_device *dpll_dev;
dpll_tracker tracker;

View File

@ -0,0 +1,84 @@
From 07f57ff127cd39789c0c0ad8f964e84de6b8065f Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:03 +0200
Subject: [PATCH] dpll: add generic DPLL type
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 9375487c0c78817b3651e2621d648c6198757c41
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:33 2026 +0200
dpll: add generic DPLL type
Add DPLL_TYPE_GENERIC to represent DPLL devices which do not fit the
existing PPS or EEC classes.
The UAPI type is intentionally generic. During netdev discussion,
maintainers pointed out that introducing identifiers tied to a specific
placement or single design does not scale across ASICs and vendors.
The role of a DPLL is already inferable from the spawning driver,
bus device, and pin topology, without encoding additional
purpose-specific taxonomy in the type name.
Using a generic type keeps the UAPI extensible and avoids premature
naming that may become incorrect as new hardware topologies are
exposed through the DPLL subsystem.
Expose the new type through UAPI and netlink specification as "generic".
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-2-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
index 4ba8adc..9c5f985 100644
--- a/Documentation/netlink/specs/dpll.yaml
+++ b/Documentation/netlink/specs/dpll.yaml
@@ -138,6 +138,9 @@ definitions:
-
name: eec
doc: dpll drives the Ethernet Equipment Clock
+ -
+ name: generic
+ doc: generic dpll type for devices outside PPS/EEC classes
render-max: true
-
type: enum
diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c
index 268999d..ad63db3 100644
--- a/drivers/dpll/dpll_nl.c
+++ b/drivers/dpll/dpll_nl.c
@@ -36,7 +36,7 @@ const struct nla_policy dpll_reference_sync_nl_policy[DPLL_A_PIN_STATE + 1] = {
static const struct nla_policy dpll_device_id_get_nl_policy[DPLL_A_TYPE + 1] = {
[DPLL_A_MODULE_NAME] = { .type = NLA_NUL_STRING, },
[DPLL_A_CLOCK_ID] = { .type = NLA_U64, },
- [DPLL_A_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+ [DPLL_A_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 3),
};
/* DPLL_CMD_DEVICE_GET - do */
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index aa45b79..7cc709c 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -108,11 +108,14 @@ enum dpll_clock_quality_level {
* enum dpll_type - type of dpll, valid values for DPLL_A_TYPE attribute
* @DPLL_TYPE_PPS: dpll produces Pulse-Per-Second signal
* @DPLL_TYPE_EEC: dpll drives the Ethernet Equipment Clock
+ * @DPLL_TYPE_GENERIC: generic dpll type for devices outside PPS/EEC classes
*/
enum dpll_type {
DPLL_TYPE_PPS = 1,
DPLL_TYPE_EEC,
-
+#ifndef __GENKSYMS__
+ DPLL_TYPE_GENERIC,
+#endif
/* private: */
__DPLL_TYPE_MAX,
DPLL_TYPE_MAX = (__DPLL_TYPE_MAX - 1)

View File

@ -0,0 +1,125 @@
From 0da69a253f03f7e520706958f17747f6c7599ce4 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:06 +0200
Subject: [PATCH] dpll: allow registering FW-identified pin with a different
DPLL
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit c191b319f20873cd62320cf738a53875827cd89d
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:34 2026 +0200
dpll: allow registering FW-identified pin with a different DPLL
Relax the (module, clock_id) equality requirement when registering a
pin identified by firmware (pin->fwnode). Some platforms associate a
FW-described pin with a DPLL instance that differs from the pin's
(module, clock_id) tuple. For such pins, permit registration without
requiring the strict match. Non-FW pins still require equality.
Keep netlink pin module reporting/filtering safe for this relaxed
registration model by caching the module name in the pin object at
allocation time and using the cached string in netlink paths.
This avoids dereferencing pin->module after provider module teardown.
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-3-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index f1b76fc..758363b 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -11,6 +11,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/idr.h>
+#include <linux/module.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -652,6 +653,7 @@ dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module,
pin->pin_idx = pin_idx;
pin->clock_id = clock_id;
pin->module = module;
+ strscpy(pin->module_name, module_name(module));
if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX ||
prop->type > DPLL_PIN_TYPE_MAX)) {
ret = -EINVAL;
@@ -884,11 +886,21 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
return -EINVAL;
mutex_lock(&dpll_lock);
- if (WARN_ON(!(dpll->module == pin->module &&
- dpll->clock_id == pin->clock_id)))
+
+ /*
+ * For pins identified via firmware (pin->fwnode), allow registration
+ * even if the pin's (module, clock_id) differs from the target DPLL.
+ * For non-fwnode pins, require a strict (module, clock_id) match.
+ */
+ if (!pin->fwnode &&
+ WARN_ON_ONCE(dpll->module != pin->module ||
+ dpll->clock_id != pin->clock_id)) {
ret = -EINVAL;
- else
- ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
+ goto out_unlock;
+ }
+
+ ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
+out_unlock:
mutex_unlock(&dpll_lock);
return ret;
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
index 0d861bd..fcc1564 100644
--- a/drivers/dpll/dpll_core.h
+++ b/drivers/dpll/dpll_core.h
@@ -50,6 +50,7 @@ struct dpll_device {
* @pin_idx: index of a pin given by dev driver
* @clock_id: clock_id of creator
* @module: module of creator
+ * @module_name: module name of creator
* @fwnode: optional reference to firmware node
* @dpll_refs: hold referencees to dplls pin was registered with
* @parent_refs: hold references to parent pins pin was registered with
@@ -77,6 +78,7 @@ struct dpll_pin {
refcount_t refcount;
struct ref_tracker_dir refcnt_tracker;
struct rcu_head rcu;
+ RH_KABI_EXTEND(char module_name[MODULE_NAME_LEN])
};
/**
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 7a86b86..bdd3637 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -712,7 +712,7 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
if (ret)
return ret;
if (nla_put_string(msg, DPLL_A_PIN_MODULE_NAME,
- module_name(pin->module)))
+ pin->module_name))
return -EMSGSIZE;
if (nla_put_64bit(msg, DPLL_A_PIN_CLOCK_ID, sizeof(pin->clock_id),
&pin->clock_id, DPLL_A_PIN_PAD))
@@ -1659,9 +1659,9 @@ dpll_pin_find(u64 clock_id, struct nlattr *mod_name_attr,
xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) {
prop = &pin->prop;
cid_match = clock_id ? pin->clock_id == clock_id : true;
- mod_match = mod_name_attr && module_name(pin->module) ?
+ mod_match = mod_name_attr && pin->module_name[0] ?
!nla_strcmp(mod_name_attr,
- module_name(pin->module)) : true;
+ pin->module_name) : true;
type_match = type ? prop->type == type : true;
board_match = board_label ? (prop->board_label ?
!nla_strcmp(board_label, prop->board_label) : false) :

View File

@ -0,0 +1,61 @@
From a376b1535cd2325c1c35d61d69036164bd1fa5a6 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:09 +0200
Subject: [PATCH] dpll: fix stale iteration in dpll_pin_on_pin_unregister()
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 32239d600236a986c8e6d16aa814d3d91066b244
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:35 2026 +0200
dpll: fix stale iteration in dpll_pin_on_pin_unregister()
Neither parent->dpll_refs nor pin->dpll_refs on its own is a correct
iteration target at unregister time:
- pin->dpll_refs includes DPLLs the child was registered against
via a different parent or directly; blind unregister WARNs on
the cookie miss in dpll_xa_ref_pin_del().
- parent->dpll_refs reflects the parent's current attachments, not
those at child-register time. Another driver may have (un)reg'd
the parent against additional DPLLs in the meantime, so we miss
registrations that exist and visit DPLLs that have none.
Walk pin->dpll_refs and use dpll_pin_registration_find() to filter
to entries whose cookie is this parent. Symmetric with
dpll_pin_on_pin_register(), correct under any subsequent change to
parent->dpll_refs.
Fixes: 9431063ad323 ("dpll: core: Add DPLL framework base functions")
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-4-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 758363b..3d23ad1 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -1031,14 +1031,19 @@ EXPORT_SYMBOL_GPL(dpll_pin_on_pin_register);
void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv)
{
+ struct dpll_pin_registration *reg;
struct dpll_pin_ref *ref;
unsigned long i;
mutex_lock(&dpll_lock);
dpll_pin_delete_ntf(pin);
dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
- xa_for_each(&pin->dpll_refs, i, ref)
+ xa_for_each(&pin->dpll_refs, i, ref) {
+ reg = dpll_pin_registration_find(ref, ops, priv, parent);
+ if (!reg)
+ continue;
__dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
+ }
mutex_unlock(&dpll_lock);
}
EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);

View File

@ -0,0 +1,47 @@
From a3f64b573a45ee715a3833a0034adc0b8f9d9813 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:13 +0200
Subject: [PATCH] dpll: send delete notification before unregister in on-pin
rollback
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit e83b403eb142be18d223fc599c0ac45519053671
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:36 2026 +0200
dpll: send delete notification before unregister in on-pin rollback
The rollback path in dpll_pin_on_pin_register() called
__dpll_pin_unregister() before dpll_pin_delete_ntf(). When the
unregister dropped the pin's last DPLL reference it cleared the
DPLL_REGISTERED mark in dpll_pin_xa, so the subsequent
dpll_pin_event_send() failed dpll_pin_available() and aborted with
-ENODEV. As a result userspace was never notified of the rollback
deletion and remained out of sync with the kernel.
Send the delete notification first, matching the order used by
dpll_pin_unregister() and dpll_pin_on_pin_unregister().
Fixes: 9d71b54b65b1 ("dpll: netlink: Add DPLL framework base functions")
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-5-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 3d23ad1..c85cc00 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -1007,9 +1007,9 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
dpll_unregister:
xa_for_each(&parent->dpll_refs, i, ref)
if (i < stop) {
+ dpll_pin_delete_ntf(pin);
__dpll_pin_unregister(ref->dpll, pin, ops, priv,
parent);
- dpll_pin_delete_ntf(pin);
}
dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
unlock:

View File

@ -0,0 +1,53 @@
From bed06b47d17a43e01769d54ed1f97ff04618ae3d Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:18 +0200
Subject: [PATCH] dpll: emit per-dpll delete notifications in
dpll_pin_on_pin_unregister()
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit df0ba51ccf873e533669578104981109217d8201
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:37 2026 +0200
dpll: emit per-dpll delete notifications in dpll_pin_on_pin_unregister()
dpll_pin_on_pin_register() emits a creation notification for every
parent->dpll_refs entry, but dpll_pin_on_pin_unregister() emitted only
one deletion notification outside the loop. When a pin is registered
against multiple parent dplls, userspace sees N creates but a single
delete and leaks per-dpll state.
Move dpll_pin_delete_ntf() into the loop and call it before
__dpll_pin_unregister() so the DPLL_REGISTERED mark is still set when
dpll_pin_available() is consulted.
Fixes: 9d71b54b65b1 ("dpll: netlink: Add DPLL framework base functions")
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-6-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index c85cc00..60171c9 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -1036,14 +1036,14 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
unsigned long i;
mutex_lock(&dpll_lock);
- dpll_pin_delete_ntf(pin);
- dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
xa_for_each(&pin->dpll_refs, i, ref) {
reg = dpll_pin_registration_find(ref, ops, priv, parent);
if (!reg)
continue;
+ dpll_pin_delete_ntf(pin);
__dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
}
+ dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
mutex_unlock(&dpll_lock);
}
EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);

View File

@ -0,0 +1,50 @@
From f9973a3184eda6eeb322dde368d07a2fc5860b81 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:21 +0200
Subject: [PATCH] dpll: guard sync-pair removal on full pin unregister
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 0a5c720a7d57d2287d5566c4ad93ee26b7c06845
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:38 2026 +0200
dpll: guard sync-pair removal on full pin unregister
__dpll_pin_unregister() wiped the global sync-pair state on every
(dpll, ops, priv, cookie) tuple removed from a pin. When a pin is
registered multiple times and only one registration is being torn
down, this dropped sync-pair pairings still in use by the surviving
registrations.
Move dpll_pin_ref_sync_pair_del() inside the xa_empty(&pin->dpll_refs)
branch so it only runs when the last registration is gone, alongside
clearing the DPLL_REGISTERED mark.
Fixes: 58256a26bfb3 ("dpll: add reference sync get/set")
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-7-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 60171c9..8f4ebf7 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -926,11 +926,12 @@ __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv, void *cookie)
{
ASSERT_DPLL_PIN_REGISTERED(pin);
- dpll_pin_ref_sync_pair_del(pin->id);
dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
- if (xa_empty(&pin->dpll_refs))
+ if (xa_empty(&pin->dpll_refs)) {
+ dpll_pin_ref_sync_pair_del(pin->id);
xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
+ }
}
/**

View File

@ -0,0 +1,50 @@
From cb38fe491e0afb090c3e20481b06b859ae3ae969 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:24 +0200
Subject: [PATCH] dpll: balance create/delete notifications in
__dpll_pin_(un)register
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 1a2292101c0dc422466c673031de03d2e871adbe
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:39 2026 +0200
dpll: balance create/delete notifications in __dpll_pin_(un)register
__dpll_pin_register() emits dpll_pin_create_ntf() internally, but
__dpll_pin_unregister() left the matching delete to its callers. The
counts then diverge on dpll_pin_on_pin_register() rollback and on
dpll_pin_on_pin_unregister(), leaking stale notifications.
Emit dpll_pin_delete_ntf() inside __dpll_pin_unregister() and drop the
now-redundant call in dpll_pin_unregister().
Fixes: 9431063ad323 ("dpll: core: Add DPLL framework base functions")
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-8-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 8f4ebf7..6020810 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -926,6 +926,7 @@ __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv, void *cookie)
{
ASSERT_DPLL_PIN_REGISTERED(pin);
+ dpll_pin_delete_ntf(pin);
dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
if (xa_empty(&pin->dpll_refs)) {
@@ -953,7 +954,6 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
return;
mutex_lock(&dpll_lock);
- dpll_pin_delete_ntf(pin);
__dpll_pin_unregister(dpll, pin, ops, priv, NULL);
mutex_unlock(&dpll_lock);
}

View File

@ -0,0 +1,186 @@
From 74b646def907e81b6d4ffdd13873c37ba3c88db9 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:27 +0200
Subject: [PATCH] dpll: extend pin notifier with notification source ID
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 0bf47f722fa9e4ecdab7497afc1af64330540bed
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:40 2026 +0200
dpll: extend pin notifier with notification source ID
Extend the DPLL pin notification API to include a source identifier
indicating where the notification originates. This allows notifier
consumers to distinguish between notifications coming from
an associated DPLL instance, a parent pin, or the pin itself.
A new field, src_clock_id, is added to struct dpll_pin_notifier_info
and is passed through all pin-related notification paths. Callers of
dpll_pin_notify() are updated to provide a meaningful source identifier
based on their context:
- pin registration/unregistration uses the DPLL's clock_id,
- pin-on-pin operations use the parent pin's clock_id,
- pin changes use the pin's own clock_id.
As introduced in the commit ("dpll: allow registering FW-identified pin
with a different DPLL"), it is possible to share the same physical pin
via firmware description (fwnode) with DPLL objects from different
kernel modules. This means that a given pin can be registered multiple
times.
Driver such as ICE (E825 devices) rely on this mechanism when listening
for the event where a shared-fwnode pin appears, while avoiding reacting
to events triggered by their own registration logic.
This change only extends the notification metadata and does not alter
existing semantics for drivers that do not use the new field.
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-9-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
index 6020810..2c57527 100644
--- a/drivers/dpll/dpll_core.c
+++ b/drivers/dpll/dpll_core.c
@@ -72,7 +72,8 @@ void dpll_device_notify(struct dpll_device *dpll, unsigned long action)
call_dpll_notifiers(action, &info);
}
-void dpll_pin_notify(struct dpll_pin *pin, unsigned long action)
+void dpll_pin_notify(struct dpll_pin *pin, u64 src_clock_id,
+ unsigned long action)
{
struct dpll_pin_notifier_info info = {
.pin = pin,
@@ -81,6 +82,7 @@ void dpll_pin_notify(struct dpll_pin *pin, unsigned long action)
.clock_id = pin->clock_id,
.fwnode = pin->fwnode,
.prop = &pin->prop,
+ .src_clock_id = src_clock_id,
};
call_dpll_notifiers(action, &info);
@@ -849,7 +851,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
if (ret)
goto ref_pin_del;
xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
- dpll_pin_create_ntf(pin);
+ dpll_pin_create_ntf(pin, dpll->clock_id);
return ret;
@@ -926,7 +928,7 @@ __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv, void *cookie)
{
ASSERT_DPLL_PIN_REGISTERED(pin);
- dpll_pin_delete_ntf(pin);
+ dpll_pin_delete_ntf(pin, dpll->clock_id);
dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
if (xa_empty(&pin->dpll_refs)) {
@@ -999,7 +1001,7 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
stop = i;
goto dpll_unregister;
}
- dpll_pin_create_ntf(pin);
+ dpll_pin_create_ntf(pin, parent->clock_id);
}
mutex_unlock(&dpll_lock);
@@ -1008,7 +1010,7 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
dpll_unregister:
xa_for_each(&parent->dpll_refs, i, ref)
if (i < stop) {
- dpll_pin_delete_ntf(pin);
+ dpll_pin_delete_ntf(pin, parent->clock_id);
__dpll_pin_unregister(ref->dpll, pin, ops, priv,
parent);
}
@@ -1041,7 +1043,7 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
reg = dpll_pin_registration_find(ref, ops, priv, parent);
if (!reg)
continue;
- dpll_pin_delete_ntf(pin);
+ dpll_pin_delete_ntf(pin, parent->clock_id);
__dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
}
dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h
index fcc1564..e4bb4b2 100644
--- a/drivers/dpll/dpll_core.h
+++ b/drivers/dpll/dpll_core.h
@@ -110,6 +110,7 @@ extern struct xarray dpll_pin_xa;
extern struct mutex dpll_lock;
void dpll_device_notify(struct dpll_device *dpll, unsigned long action);
-void dpll_pin_notify(struct dpll_pin *pin, unsigned long action);
+void dpll_pin_notify(struct dpll_pin *pin, u64 src_clock_id,
+ unsigned long action);
#endif
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index bdd3637..0428da3 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -924,15 +924,15 @@ dpll_pin_event_send(enum dpll_cmd event, struct dpll_pin *pin)
return ret;
}
-int dpll_pin_create_ntf(struct dpll_pin *pin)
+int dpll_pin_create_ntf(struct dpll_pin *pin, u64 src_clock_id)
{
- dpll_pin_notify(pin, DPLL_PIN_CREATED);
+ dpll_pin_notify(pin, src_clock_id, DPLL_PIN_CREATED);
return dpll_pin_event_send(DPLL_CMD_PIN_CREATE_NTF, pin);
}
-int dpll_pin_delete_ntf(struct dpll_pin *pin)
+int dpll_pin_delete_ntf(struct dpll_pin *pin, u64 src_clock_id)
{
- dpll_pin_notify(pin, DPLL_PIN_DELETED);
+ dpll_pin_notify(pin, src_clock_id, DPLL_PIN_DELETED);
return dpll_pin_event_send(DPLL_CMD_PIN_DELETE_NTF, pin);
}
@@ -947,7 +947,7 @@ int dpll_pin_delete_ntf(struct dpll_pin *pin)
int __dpll_pin_change_ntf(struct dpll_pin *pin)
{
lockdep_assert_held(&dpll_lock);
- dpll_pin_notify(pin, DPLL_PIN_CHANGED);
+ dpll_pin_notify(pin, pin->clock_id, DPLL_PIN_CHANGED);
return dpll_pin_event_send(DPLL_CMD_PIN_CHANGE_NTF, pin);
}
EXPORT_SYMBOL_GPL(__dpll_pin_change_ntf);
diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h
index a9cfd55..4f63aa5 100644
--- a/drivers/dpll/dpll_netlink.h
+++ b/drivers/dpll/dpll_netlink.h
@@ -8,6 +8,6 @@ int dpll_device_create_ntf(struct dpll_device *dpll);
int dpll_device_delete_ntf(struct dpll_device *dpll);
-int dpll_pin_create_ntf(struct dpll_pin *pin);
+int dpll_pin_create_ntf(struct dpll_pin *pin, u64 src_clock_id);
-int dpll_pin_delete_ntf(struct dpll_pin *pin);
+int dpll_pin_delete_ntf(struct dpll_pin *pin, u64 src_clock_id);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 5ee402f..6117120 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -265,6 +265,7 @@ struct dpll_pin_notifier_info {
u64 clock_id;
const struct fwnode_handle *fwnode;
const struct dpll_pin_properties *prop;
+ u64 src_clock_id;
};
#if IS_ENABLED(CONFIG_DPLL)

View File

@ -0,0 +1,66 @@
From 5bbe55502a03aeea3e38b0fe23ddae7cf0822f69 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Mon, 22 Jun 2026 17:14:31 +0200
Subject: [PATCH] dpll: allow fwnode pins to attempt state change without
capability bit
JIRA: https://redhat.atlassian.net/browse/RHEL-186631
commit 521b6d5de08d506f0e3e1bf0a9b14766140107fc
Author: Grzegorz Nitka <grzegorz.nitka@intel.com>
Date: Sun Jun 7 20:30:41 2026 +0200
dpll: allow fwnode pins to attempt state change without capability bit
Pins registered with an fwnode may have .state_on_dpll_set implemented
without advertising DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE upfront.
Requiring the bit for fwnode pins ties firmware description to driver
implementation details unnecessarily.
Relax the capability check in dpll_pin_state_set() and
dpll_pin_on_pin_state_set(): when a pin has an associated fwnode, bypass
the capability gate and let the ops layer decide, returning -EOPNOTSUPP
if .state_on_dpll_set is absent. Non-fwnode pins retain the original
strict behavior.
This is used later in the series by the SyncE_Ref output pin, which
relies on the fwnode path for state control.
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Link: https://patch.msgid.link/20260607183045.1213735-10-grzegorz.nitka@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index 0428da3..aa77d25 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -1334,8 +1334,11 @@ dpll_pin_on_pin_state_set(struct dpll_pin *pin, u32 parent_idx,
unsigned long i;
int ret;
+ /* fwnode pins may not set the capability bit upfront; let the ops
+ * layer return -EOPNOTSUPP if the operation is unsupported.
+ */
if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
- pin->prop.capabilities)) {
+ pin->prop.capabilities) && !pin->fwnode) {
NL_SET_ERR_MSG(extack, "state changing is not allowed");
return -EOPNOTSUPP;
}
@@ -1370,8 +1373,11 @@ dpll_pin_state_set(struct dpll_device *dpll, struct dpll_pin *pin,
struct dpll_pin_ref *ref;
int ret;
+ /* fwnode pins may not set the capability bit upfront; let the ops
+ * layer return -EOPNOTSUPP if the operation is unsupported.
+ */
if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE &
- pin->prop.capabilities)) {
+ pin->prop.capabilities) && !pin->fwnode) {
NL_SET_ERR_MSG(extack, "state changing is not allowed");
return -EOPNOTSUPP;
}

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 2
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 211.42.1
RHEL_RELEASE = 211.43.1
#
# RHEL_REBASE_NUM

View File

@ -1,3 +1,32 @@
* Mon Aug 03 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.43.1.el10_2]
- redhat/kernel.spec: make module and modules-core provides use variant (Jan Stancek) [RHEL-213965]
- dpll: allow fwnode pins to attempt state change without capability bit (Jakub Ramaseuski) [RHEL-211011]
- dpll: extend pin notifier with notification source ID (Jakub Ramaseuski) [RHEL-211011]
- dpll: balance create/delete notifications in __dpll_pin_(un)register (Jakub Ramaseuski) [RHEL-211011]
- dpll: guard sync-pair removal on full pin unregister (Jakub Ramaseuski) [RHEL-211011]
- dpll: emit per-dpll delete notifications in dpll_pin_on_pin_unregister() (Jakub Ramaseuski) [RHEL-211011]
- dpll: send delete notification before unregister in on-pin rollback (Jakub Ramaseuski) [RHEL-211011]
- dpll: fix stale iteration in dpll_pin_on_pin_unregister() (Jakub Ramaseuski) [RHEL-211011]
- dpll: allow registering FW-identified pin with a different DPLL (Jakub Ramaseuski) [RHEL-211011]
- dpll: add generic DPLL type (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: make frequency monitor a per-device attribute (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work (Jakub Ramaseuski) [RHEL-211011]
- dpll: export __dpll_device_change_ntf() for use under dpll_lock (Jakub Ramaseuski) [RHEL-211011]
- dpll: change dpll_netdev_pin_handle_size() to assume DPLL_A_PIN_ID will be used (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: fix memory leak on pin registration failure (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: Use named initializers for struct i2c_device_id (Jakub Ramaseuski) [RHEL-211011]
- dpll: Prevent duplicate registrations (Jakub Ramaseuski) [RHEL-211011]
- dpll: export __dpll_pin_change_ntf() for use under dpll_lock (Jakub Ramaseuski) [RHEL-211011]
- drm/i915/psr: Use DC_OFF wake reference to block DC6 on vblank enable (Anusha Srivatsa) [RHEL-172832]
- drm/i915/psr: Block DC states on vblank enable when Panel Replay supported (Anusha Srivatsa) [RHEL-172832]
- drm/i915/psr: Don't enable Panel Replay on sink if globally disabled (Anusha Srivatsa) [RHEL-172832]
- drm/i915/alpm: ALPM disable fixes (Anusha Srivatsa) [RHEL-172832]
- procfs: fix possible double mmput() in do_procmap_query() (Rafael Aquini) [RHEL-189665] {CVE-2026-23199}
- procfs: avoid fetching build ID while holding VMA lock (Rafael Aquini) [RHEL-189665] {CVE-2026-23199}
- timers: Fix NULL function pointer race in timer_shutdown_sync() (CKI Backport Bot) [RHEL-189563] {CVE-2025-68214}
- net: wwan: t7xx: Add delay between MD and SAP suspend (CKI Backport Bot) [RHEL-184266]
Resolves: RHEL-172832, RHEL-184266, RHEL-189563, RHEL-189665, RHEL-211011, RHEL-213965
* Wed Jul 29 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.42.1.el10_2]
- net/sched: cls_api: Handle TC_ACT_CONSUMED in tcf_qevent_handle (CKI Backport Bot) [RHEL-214082] {CVE-2026-64530}
- ksm: use range-walk function to jump over holes in scan_get_next_rmap_item (Rafael Aquini) [RHEL-189554] {CVE-2025-68211}

View File

@ -176,13 +176,13 @@ Summary: The Linux kernel
%define specrpmversion 6.12.0
%define specversion 6.12.0
%define patchversion 6.12
%define pkgrelease 211.42.1
%define pkgrelease 211.43.1
%define kversion 6
%define tarfile_release 6.12.0-211.42.1.el10_2
# This is needed to do merge window version magic
%define patchlevel 12
# This allows pkg_release to have configurable %%{?dist} tag
%define specrelease 211.42.1%{?buildid}%{?dist}
%define specrelease 211.43.1%{?buildid}%{?dist}
# This defines the kabi tarball version
%define kabiversion 6.12.0-211.42.1.el10_2
@ -1127,6 +1127,33 @@ Patch1: patch-%{patchversion}-redhat.patch
# empty final patch to facilitate testing of kernel patches
Patch999999: linux-kernel-test.patch
# Backports for 6.12.0-211.43.1.el10_2
Patch1100: 1100-net-wwan-t7xx-add-delay-between-md-and-sap-suspend.patch
Patch1101: 1101-timers-fix-null-function-pointer-race-in-timer-shutdown-sync.patch
Patch1102: 1102-procfs-avoid-fetching-build-id-while-holding-vma-lock.patch
Patch1103: 1103-procfs-fix-possible-double-mmput-in-do-procmap-query.patch
Patch1104: 1104-drm-i915-alpm-alpm-disable-fixes.patch
Patch1105: 1105-drm-i915-psr-don-t-enable-panel-replay-on-sink-if-globally-disabled.patch
Patch1106: 1106-drm-i915-psr-block-dc-states-on-vblank-enable-when-panel-replay-supported.patch
Patch1107: 1107-drm-i915-psr-use-dc-off-wake-reference-to-block-dc6-on-vblank-enable.patch
Patch1108: 1108-dpll-export-dpll-pin-change-ntf-for-use-under-dpll-lock.patch
Patch1109: 1109-dpll-prevent-duplicate-registrations.patch
Patch1110: 1110-dpll-zl3073x-use-named-initializers-for-struct-i2c-device-id.patch
Patch1111: 1111-dpll-zl3073x-fix-memory-leak-on-pin-registration-failure.patch
Patch1112: 1112-dpll-change-dpll-netdev-pin-handle-size-to-assume-dpll-a-pin-id-will-be-used.patch
Patch1113: 1113-dpll-export-dpll-device-change-ntf-for-use-under-dpll-lock.patch
Patch1114: 1114-dpll-zl3073x-use-dpll-device-change-ntf-and-remove-change-work.patch
Patch1115: 1115-dpll-zl3073x-make-frequency-monitor-a-per-device-attribute.patch
Patch1116: 1116-dpll-add-generic-dpll-type.patch
Patch1117: 1117-dpll-allow-registering-fw-identified-pin-with-a-different-dpll.patch
Patch1118: 1118-dpll-fix-stale-iteration-in-dpll-pin-on-pin-unregister.patch
Patch1119: 1119-dpll-send-delete-notification-before-unregister-in-on-pin-rollback.patch
Patch1120: 1120-dpll-emit-per-dpll-delete-notifications-in-dpll-pin-on-pin-unregister.patch
Patch1121: 1121-dpll-guard-sync-pair-removal-on-full-pin-unregister.patch
Patch1122: 1122-dpll-balance-create-delete-notifications-in-dpll-pin-un-register.patch
Patch1123: 1123-dpll-extend-pin-notifier-with-notification-source-id.patch
Patch1124: 1124-dpll-allow-fwnode-pins-to-attempt-state-change-without-capability-bit.patch
# END OF PATCH DEFINITIONS
%description
@ -1551,8 +1578,8 @@ This package provides less commonly used kernel modules for the %{?2:%{2} }kerne
%package %{?1:%{1}-}modules\
Summary: kernel modules to match the %{?2:%{2}-}core kernel\
Provides: %{name}%{?1:-%{1}}-modules-%{_target_cpu} = %{specrpmversion}-%{release}\
Provides: %{name}-modules-%{_target_cpu} = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: %{name}-modules = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: %{name}%{?1:-%{1}}-modules-%{_target_cpu} = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: %{name}%{?1:-%{1}}-modules = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: installonlypkg(kernel-module)\
Provides: %{name}%{?1:-%{1}}-modules-uname-r = %{KVERREL}%{uname_suffix %{?1}}\
Requires: %{name}-uname-r = %{KVERREL}%{uname_suffix %{?1}}\
@ -1574,8 +1601,8 @@ This package provides commonly used kernel modules for the %{?2:%{2}-}core kerne
%package %{?1:%{1}-}modules-core\
Summary: Core kernel modules to match the %{?2:%{2}-}core kernel\
Provides: %{name}%{?1:-%{1}}-modules-core-%{_target_cpu} = %{specrpmversion}-%{release}\
Provides: %{name}-modules-core-%{_target_cpu} = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: %{name}-modules-core = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: %{name}%{?1:-%{1}}-modules-core-%{_target_cpu} = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: %{name}%{?1:-%{1}}-modules-core = %{specrpmversion}-%{release}%{uname_suffix %{?1}}\
Provides: installonlypkg(kernel-module)\
Provides: %{name}%{?1:-%{1}}-modules-core-uname-r = %{KVERREL}%{uname_suffix %{?1}}\
Requires: %{name}-uname-r = %{KVERREL}%{uname_suffix %{?1}}\
@ -1974,6 +2001,33 @@ ApplyOptionalPatch patch-%{patchversion}-redhat.patch
ApplyOptionalPatch linux-kernel-test.patch
# Applying backports for 6.12.0-211.43.1.el10_2
ApplyPatch 1100-net-wwan-t7xx-add-delay-between-md-and-sap-suspend.patch
ApplyPatch 1101-timers-fix-null-function-pointer-race-in-timer-shutdown-sync.patch
ApplyPatch 1102-procfs-avoid-fetching-build-id-while-holding-vma-lock.patch
ApplyPatch 1103-procfs-fix-possible-double-mmput-in-do-procmap-query.patch
ApplyPatch 1104-drm-i915-alpm-alpm-disable-fixes.patch
ApplyPatch 1105-drm-i915-psr-don-t-enable-panel-replay-on-sink-if-globally-disabled.patch
ApplyPatch 1106-drm-i915-psr-block-dc-states-on-vblank-enable-when-panel-replay-supported.patch
ApplyPatch 1107-drm-i915-psr-use-dc-off-wake-reference-to-block-dc6-on-vblank-enable.patch
ApplyPatch 1108-dpll-export-dpll-pin-change-ntf-for-use-under-dpll-lock.patch
ApplyPatch 1109-dpll-prevent-duplicate-registrations.patch
ApplyPatch 1110-dpll-zl3073x-use-named-initializers-for-struct-i2c-device-id.patch
ApplyPatch 1111-dpll-zl3073x-fix-memory-leak-on-pin-registration-failure.patch
ApplyPatch 1112-dpll-change-dpll-netdev-pin-handle-size-to-assume-dpll-a-pin-id-will-be-used.patch
ApplyPatch 1113-dpll-export-dpll-device-change-ntf-for-use-under-dpll-lock.patch
ApplyPatch 1114-dpll-zl3073x-use-dpll-device-change-ntf-and-remove-change-work.patch
ApplyPatch 1115-dpll-zl3073x-make-frequency-monitor-a-per-device-attribute.patch
ApplyPatch 1116-dpll-add-generic-dpll-type.patch
ApplyPatch 1117-dpll-allow-registering-fw-identified-pin-with-a-different-dpll.patch
ApplyPatch 1118-dpll-fix-stale-iteration-in-dpll-pin-on-pin-unregister.patch
ApplyPatch 1119-dpll-send-delete-notification-before-unregister-in-on-pin-rollback.patch
ApplyPatch 1120-dpll-emit-per-dpll-delete-notifications-in-dpll-pin-on-pin-unregister.patch
ApplyPatch 1121-dpll-guard-sync-pair-removal-on-full-pin-unregister.patch
ApplyPatch 1122-dpll-balance-create-delete-notifications-in-dpll-pin-un-register.patch
ApplyPatch 1123-dpll-extend-pin-notifier-with-notification-source-id.patch
ApplyPatch 1124-dpll-allow-fwnode-pins-to-attempt-state-change-without-capability-bit.patch
%{log_msg "End of patch applications"}
# END OF PATCH APPLICATIONS
@ -4491,6 +4545,34 @@ fi\
#
#
%changelog
* Mon Aug 03 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.43.1.el10_2]
- redhat/kernel.spec: make module and modules-core provides use variant (Jan Stancek) [RHEL-213965]
- dpll: allow fwnode pins to attempt state change without capability bit (Jakub Ramaseuski) [RHEL-211011]
- dpll: extend pin notifier with notification source ID (Jakub Ramaseuski) [RHEL-211011]
- dpll: balance create/delete notifications in __dpll_pin_(un)register (Jakub Ramaseuski) [RHEL-211011]
- dpll: guard sync-pair removal on full pin unregister (Jakub Ramaseuski) [RHEL-211011]
- dpll: emit per-dpll delete notifications in dpll_pin_on_pin_unregister() (Jakub Ramaseuski) [RHEL-211011]
- dpll: send delete notification before unregister in on-pin rollback (Jakub Ramaseuski) [RHEL-211011]
- dpll: fix stale iteration in dpll_pin_on_pin_unregister() (Jakub Ramaseuski) [RHEL-211011]
- dpll: allow registering FW-identified pin with a different DPLL (Jakub Ramaseuski) [RHEL-211011]
- dpll: add generic DPLL type (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: make frequency monitor a per-device attribute (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work (Jakub Ramaseuski) [RHEL-211011]
- dpll: export __dpll_device_change_ntf() for use under dpll_lock (Jakub Ramaseuski) [RHEL-211011]
- dpll: change dpll_netdev_pin_handle_size() to assume DPLL_A_PIN_ID will be used (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: fix memory leak on pin registration failure (Jakub Ramaseuski) [RHEL-211011]
- dpll: zl3073x: Use named initializers for struct i2c_device_id (Jakub Ramaseuski) [RHEL-211011]
- dpll: Prevent duplicate registrations (Jakub Ramaseuski) [RHEL-211011]
- dpll: export __dpll_pin_change_ntf() for use under dpll_lock (Jakub Ramaseuski) [RHEL-211011]
- drm/i915/psr: Use DC_OFF wake reference to block DC6 on vblank enable (Anusha Srivatsa) [RHEL-172832]
- drm/i915/psr: Block DC states on vblank enable when Panel Replay supported (Anusha Srivatsa) [RHEL-172832]
- drm/i915/psr: Don't enable Panel Replay on sink if globally disabled (Anusha Srivatsa) [RHEL-172832]
- drm/i915/alpm: ALPM disable fixes (Anusha Srivatsa) [RHEL-172832]
- procfs: fix possible double mmput() in do_procmap_query() (Rafael Aquini) [RHEL-189665] {CVE-2026-23199}
- procfs: avoid fetching build ID while holding VMA lock (Rafael Aquini) [RHEL-189665] {CVE-2026-23199}
- timers: Fix NULL function pointer race in timer_shutdown_sync() (CKI Backport Bot) [RHEL-189563] {CVE-2025-68214}
- net: wwan: t7xx: Add delay between MD and SAP suspend (CKI Backport Bot) [RHEL-184266]
* Wed Jul 29 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [6.12.0-211.42.1.el10_2]
- net/sched: cls_api: Handle TC_ACT_CONSUMED in tcf_qevent_handle (CKI Backport Bot) [RHEL-214082] {CVE-2026-64530}
- ksm: use range-walk function to jump over holes in scan_get_next_rmap_item (Rafael Aquini) [RHEL-189554] {CVE-2025-68211}