From: Anand Moon <linux.amoon@gmail.com>
To: Heiko Stuebner <heiko@sntech.de>,
Andi Shyti <andi.shyti@kernel.org>,
linux-arm-kernel@lists.infradead.org (moderated
list:ARM/Rockchip SoC support),
linux-rockchip@lists.infradead.org (open list:ARM/Rockchip SoC
support),
linux-i2c@vger.kernel.org (open list:I2C SUBSYSTEM HOST DRIVERS),
linux-kernel@vger.kernel.org (open list)
Cc: Anand Moon <linux.amoon@gmail.com>
Subject: [PATCH v3 2/2] i2c: rk3x: Fix deadlock by splitting rk3x_i2c_adapt_div into locked/unlocked variants
Date: Thu, 2 Apr 2026 19:49:23 +0530 [thread overview]
Message-ID: <20260402141927.7216-2-linux.amoon@gmail.com> (raw)
In-Reply-To: <20260402141927.7216-1-linux.amoon@gmail.com>
Introduce __rk3x_i2c_adapt_div() function as a locked-only helper to
handle core timing calculations and register updates. This restructuring
allows these operations to be safely called from contexts where i2c->lock
is already held—such as during error recovery in rk3x_i2c_xfer_common
avoiding recursive locking or deadlocks.
Signed-off-by: Anand Moon <linux.amoon@gmail.com>
---
v3: new patch to avoid deadlock.
---
drivers/i2c/busses/i2c-rk3x.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 06a77780cf82..2556a3d8b2a1 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -880,22 +880,18 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
return ret;
}
-static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
+static void __rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
{
struct i2c_timings *t = &i2c->t;
struct rk3x_i2c_calced_timings calc;
unsigned long period, time_hold = (WAIT_TIMEOUT / 2) * 1000000;
u64 t_low_ns, t_high_ns;
- unsigned long flags;
u32 val;
int ret;
ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
- clk_enable(i2c->pclk);
-
- spin_lock_irqsave(&i2c->lock, flags);
val = i2c_readl(i2c, REG_CON);
val &= ~REG_CON_TUNING_MASK;
val |= calc.tuning;
@@ -909,10 +905,6 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
i2c_writel(i2c, val, REG_SCL_OE_DB);
}
- spin_unlock_irqrestore(&i2c->lock, flags);
-
- clk_disable(i2c->pclk);
-
t_low_ns = div_u64(8ULL * HZ_PER_GHZ * (calc.div_low + 1), clk_rate);
t_high_ns = div_u64(8ULL * HZ_PER_GHZ * (calc.div_high + 1), clk_rate);
dev_dbg(i2c->dev,
@@ -922,6 +914,19 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
t_low_ns, t_high_ns);
}
+static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
+{
+ unsigned long flags;
+
+ clk_enable(i2c->pclk);
+
+ spin_lock_irqsave(&i2c->lock, flags);
+ __rk3x_i2c_adapt_div(i2c, clk_rate);
+ spin_unlock_irqrestore(&i2c->lock, flags);
+
+ clk_disable(i2c->pclk);
+}
+
/**
* rk3x_i2c_clk_notifier_cb - Clock rate change callback
* @nb: Pointer to notifier block
@@ -1152,7 +1157,7 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
if (ret == -ETIMEDOUT && i2c->soc_data->has_scl_oe_debounce) {
if (ipd & REG_INT_SLV_HDSCL) {
dev_err(i2c->dev, "SCL hold by slave detected, resetting timings.\n");
- rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
+ __rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
}
}
--
2.50.1
WARNING: multiple messages have this Message-ID (diff)
From: Anand Moon <linux.amoon@gmail.com>
To: Heiko Stuebner <heiko@sntech.de>,
Andi Shyti <andi.shyti@kernel.org>,
linux-arm-kernel@lists.infradead.org (moderated
list:ARM/Rockchip SoC support),
linux-rockchip@lists.infradead.org (open list:ARM/Rockchip SoC
support),
linux-i2c@vger.kernel.org (open list:I2C SUBSYSTEM HOST DRIVERS),
linux-kernel@vger.kernel.org (open list)
Cc: Anand Moon <linux.amoon@gmail.com>
Subject: [PATCH v3 2/2] i2c: rk3x: Fix deadlock by splitting rk3x_i2c_adapt_div into locked/unlocked variants
Date: Thu, 2 Apr 2026 19:49:23 +0530 [thread overview]
Message-ID: <20260402141927.7216-2-linux.amoon@gmail.com> (raw)
In-Reply-To: <20260402141927.7216-1-linux.amoon@gmail.com>
Introduce __rk3x_i2c_adapt_div() function as a locked-only helper to
handle core timing calculations and register updates. This restructuring
allows these operations to be safely called from contexts where i2c->lock
is already held—such as during error recovery in rk3x_i2c_xfer_common
avoiding recursive locking or deadlocks.
Signed-off-by: Anand Moon <linux.amoon@gmail.com>
---
v3: new patch to avoid deadlock.
---
drivers/i2c/busses/i2c-rk3x.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 06a77780cf82..2556a3d8b2a1 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -880,22 +880,18 @@ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate,
return ret;
}
-static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
+static void __rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
{
struct i2c_timings *t = &i2c->t;
struct rk3x_i2c_calced_timings calc;
unsigned long period, time_hold = (WAIT_TIMEOUT / 2) * 1000000;
u64 t_low_ns, t_high_ns;
- unsigned long flags;
u32 val;
int ret;
ret = i2c->soc_data->calc_timings(clk_rate, t, &calc);
WARN_ONCE(ret != 0, "Could not reach SCL freq %u", t->bus_freq_hz);
- clk_enable(i2c->pclk);
-
- spin_lock_irqsave(&i2c->lock, flags);
val = i2c_readl(i2c, REG_CON);
val &= ~REG_CON_TUNING_MASK;
val |= calc.tuning;
@@ -909,10 +905,6 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
i2c_writel(i2c, val, REG_SCL_OE_DB);
}
- spin_unlock_irqrestore(&i2c->lock, flags);
-
- clk_disable(i2c->pclk);
-
t_low_ns = div_u64(8ULL * HZ_PER_GHZ * (calc.div_low + 1), clk_rate);
t_high_ns = div_u64(8ULL * HZ_PER_GHZ * (calc.div_high + 1), clk_rate);
dev_dbg(i2c->dev,
@@ -922,6 +914,19 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
t_low_ns, t_high_ns);
}
+static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
+{
+ unsigned long flags;
+
+ clk_enable(i2c->pclk);
+
+ spin_lock_irqsave(&i2c->lock, flags);
+ __rk3x_i2c_adapt_div(i2c, clk_rate);
+ spin_unlock_irqrestore(&i2c->lock, flags);
+
+ clk_disable(i2c->pclk);
+}
+
/**
* rk3x_i2c_clk_notifier_cb - Clock rate change callback
* @nb: Pointer to notifier block
@@ -1152,7 +1157,7 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
if (ret == -ETIMEDOUT && i2c->soc_data->has_scl_oe_debounce) {
if (ipd & REG_INT_SLV_HDSCL) {
dev_err(i2c->dev, "SCL hold by slave detected, resetting timings.\n");
- rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
+ __rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
}
}
--
2.50.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
next prev parent reply other threads:[~2026-04-02 14:19 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 14:19 [PATCH v3 1/2] i2c: rk3x: add support for SCL OE debounce and slave hold recovery Anand Moon
2026-04-02 14:19 ` Anand Moon
2026-04-02 14:19 ` Anand Moon [this message]
2026-04-02 14:19 ` [PATCH v3 2/2] i2c: rk3x: Fix deadlock by splitting rk3x_i2c_adapt_div into locked/unlocked variants Anand Moon
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=20260402141927.7216-2-linux.amoon@gmail.com \
--to=linux.amoon@gmail.com \
--cc=andi.shyti@kernel.org \
--cc=heiko@sntech.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.