From: hyunjungg <hj351016@gmail.com>
To: Danish Anwar <danishanwar@ti.com>, Roger Quadros <rogerq@kernel.org>
Cc: Andrew Lunn <andrew+netdev@lunn.ch>,
"David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
Hyunjung Ko <hj351016@gmail.com>
Subject: [PATCH net v2] net: ti: icss-iep: fix deadlock when disabling PPS
Date: Sun, 8 Nov 2026 16:47:33 +0900 [thread overview]
Message-ID: <20261108074733.248784-1-hj351016@gmail.com> (raw)
In-Reply-To: <20261107063726.3388730-1-hj351016@gmail.com>
From: Hyunjung Ko <hj351016@gmail.com>
icss_iep_pps_enable() holds iep->ptp_clk_mutex across the whole function.
When PPS is being disabled it calls cancel_work_sync(&iep->work) while that
mutex is still held.
The work handler, icss_iep_cap_cmp_work(), acquires iep->ptp_clk_mutex at
its start. The capture-compare IRQ (icss_iep_cap_cmp_irq) schedules this
work on every CMP1 event while PPS is enabled, so a handler instance can be
running when userspace disables PPS. In that case cancel_work_sync() blocks
waiting for the handler to finish while holding ptp_clk_mutex, and the
handler blocks trying to acquire the same ptp_clk_mutex -> deadlock.
lockdep would report this as a possible circular locking dependency
between the work and ptp_clk_mutex.
Unlike a teardown path, the capture-compare IRQ is not disabled here, so
the race is reachable at runtime simply by toggling PPS off while the
hardware is generating CMP events.
Drain the work only after dropping ptp_clk_mutex, so the disable path no
longer waits for the handler while holding the lock the handler needs.
Dropping the mutex before the drain means a work item that was already
queued (or an IRQ latched just before the compare was disabled) can still
run icss_iep_cap_cmp_work() after PPS/perout has been turned off. Guard the
handler so it returns early, under the mutex, when neither pps_enabled nor
perout_enabled is set, instead of re-arming CMP1 and emitting a stale PPS
event once the event source is gone.
This was found by a static analysis tool -- an in-house shape/pattern
checker that flags cancel_work_sync() calls made while holding a lock the
cancelled work's handler also acquires -- and confirmed by manual review
of the PPS enable/disable path. It was not tested on real hardware: I do
not have a TI ICSSG/PRU (AM65x-family) device, so the deadlock and the
late-work window are established by code inspection rather than an observed
lockdep or KASAN trace.
Fixes: f18ad402cd8b ("net: ti: icss-iep: Enable compare events")
Cc: stable@vger.kernel.org
Signed-off-by: Hyunjung Ko <hj351016@gmail.com>
---
v2:
- Guard icss_iep_cap_cmp_work() to return early, under ptp_clk_mutex, when
PPS/perout is disabled, so a work item that runs after the mutex is
dropped no longer re-arms the compare or emits a stale PPS event
(addresses the late-work windows raised in review of v1).
- Soften "lockdep reports" -> "lockdep would report" (not an observed
trace).
- Record discovery (static analysis + manual inspection) and that the
change was not tested on real hardware in the commit message, as
requested by the netdev commit-message bot.
v1: https://lore.kernel.org/netdev/20261107063726.3388730-1-hj351016@gmail.com/
drivers/net/ethernet/ti/icssg/icss_iep.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index ec08589..3b2a88c 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -534,6 +534,17 @@ static void icss_iep_cap_cmp_work(struct work_struct *work)
mutex_lock(&iep->ptp_clk_mutex);
+ /*
+ * PPS/perout may have been disabled (and the compare hardware
+ * cleared) while this work was queued or waiting for the mutex.
+ * Bail out rather than re-arm CMP1 and emit a stale PPS event once
+ * the event source is gone.
+ */
+ if (!iep->pps_enabled && !iep->perout_enabled) {
+ mutex_unlock(&iep->ptp_clk_mutex);
+ return;
+ }
+
ns = readl(iep->base + reg_offs[ICSS_IEP_CMP1_REG0]);
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) {
val = readl(iep->base + reg_offs[ICSS_IEP_CMP1_REG1]);
@@ -579,6 +590,7 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
{
struct ptp_clock_request rq;
struct timespec64 ts;
+ bool drain_work = false;
int ret = 0;
u64 ns;
@@ -607,7 +619,7 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
} else {
ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
if (iep->cap_cmp_irq)
- cancel_work_sync(&iep->work);
+ drain_work = true;
}
if (!ret)
@@ -616,6 +628,15 @@ static int icss_iep_pps_enable(struct icss_iep *iep, int on)
exit:
mutex_unlock(&iep->ptp_clk_mutex);
+ /*
+ * Drain the capture-compare work only after dropping ptp_clk_mutex.
+ * icss_iep_cap_cmp_work() takes ptp_clk_mutex itself, so cancelling it
+ * under the mutex deadlocks against a handler instance already running
+ * and waiting for that same mutex.
+ */
+ if (drain_work)
+ cancel_work_sync(&iep->work);
+
return ret;
}
--
2.43.0
prev parent reply other threads:[~2026-11-08 7:48 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 6:37 [PATCH net] " hyunjungg
2026-11-07 6:40 ` netdev-bot+sinfo
2026-11-08 6:59 ` netdev-bot+sashiko
2026-11-08 7:47 ` khj
2026-11-08 7:47 ` hyunjungg [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261108074733.248784-1-hj351016@gmail.com \
--to=hj351016@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=danishanwar@ti.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rogerq@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®