From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Johan Hovold <johan@kernel.org>,
Phil Reid <preid@electromag.com.au>,
Wolfram Sang <wsa+renesas@sang-engineering.com>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 5.10.y 2/5] i2c: core: fix hang on adapter registration failure
Date: Sun, 5 Jul 2026 15:06:09 -0400 [thread overview]
Message-ID: <20260705190612.1987801-2-sashal@kernel.org> (raw)
In-Reply-To: <20260705190612.1987801-1-sashal@kernel.org>
From: Johan Hovold <johan@kernel.org>
[ Upstream commit 3c7e164344e5bcf6f274bbf59a3274f5caad9bc1 ]
Clients may be registered from bus notifier callbacks when the adapter
is registered. On a subsequent error during registration, the adapter
references taken by such clients prevent the wait for the references to
be released from ever completing.
Fix this by refactoring client deregistration and deregistering also on
late adapter registration failures.
Fixes: f8756c67b3de ("i2c: core: call of_i2c_setup_smbus_alert in i2c_register_adapter")
Cc: stable@vger.kernel.org # 4.15
Cc: Phil Reid <preid@electromag.com.au>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Stable-dep-of: ba14d7cf2fe7 ("i2c: core: fix adapter registration race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/i2c/i2c-core-base.c | 49 ++++++++++++++++++++++---------------
1 file changed, 29 insertions(+), 20 deletions(-)
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index bbb4c8a3d4a6fa..8abd576d357b67 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -61,6 +61,7 @@
static DEFINE_MUTEX(core_lock);
static DEFINE_IDR(i2c_adapter_idr);
+static void i2c_deregister_clients(struct i2c_adapter *adap);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
@@ -1502,6 +1503,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
return 0;
out_reg:
+ i2c_deregister_clients(adap);
init_completion(&adap->dev_released);
device_unregister(&adap->dev);
wait_for_completion(&adap->dev_released);
@@ -1644,29 +1646,10 @@ static int __process_removed_adapter(struct device_driver *d, void *data)
return 0;
}
-/**
- * i2c_del_adapter - unregister I2C adapter
- * @adap: the adapter being unregistered
- * Context: can sleep
- *
- * This unregisters an I2C adapter which was previously registered
- * by @i2c_add_adapter or @i2c_add_numbered_adapter.
- */
-void i2c_del_adapter(struct i2c_adapter *adap)
+static void i2c_deregister_clients(struct i2c_adapter *adap)
{
- struct i2c_adapter *found;
struct i2c_client *client, *next;
- /* First make sure that this adapter was ever added */
- mutex_lock(&core_lock);
- found = idr_find(&i2c_adapter_idr, adap->nr);
- mutex_unlock(&core_lock);
- if (found != adap) {
- pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
- return;
- }
-
- i2c_acpi_remove_space_handler(adap);
/* Tell drivers about this removal */
mutex_lock(&core_lock);
bus_for_each_drv(&i2c_bus_type, NULL, adap,
@@ -1692,6 +1675,32 @@ void i2c_del_adapter(struct i2c_adapter *adap)
* them up properly, so we give them a chance to do that first. */
device_for_each_child(&adap->dev, NULL, __unregister_client);
device_for_each_child(&adap->dev, NULL, __unregister_dummy);
+}
+
+/**
+ * i2c_del_adapter - unregister I2C adapter
+ * @adap: the adapter being unregistered
+ * Context: can sleep
+ *
+ * This unregisters an I2C adapter which was previously registered
+ * by @i2c_add_adapter or @i2c_add_numbered_adapter.
+ */
+void i2c_del_adapter(struct i2c_adapter *adap)
+{
+ struct i2c_adapter *found;
+
+ /* First make sure that this adapter was ever added */
+ mutex_lock(&core_lock);
+ found = idr_find(&i2c_adapter_idr, adap->nr);
+ mutex_unlock(&core_lock);
+ if (found != adap) {
+ pr_debug("attempting to delete unregistered adapter [%s]\n", adap->name);
+ return;
+ }
+
+ i2c_acpi_remove_space_handler(adap);
+
+ i2c_deregister_clients(adap);
#ifdef CONFIG_I2C_COMPAT
class_compat_remove_link(i2c_adapter_compat_class, &adap->dev,
--
2.53.0
next prev parent reply other threads:[~2026-07-05 19:06 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 13:53 FAILED: patch "[PATCH] i2c: core: fix adapter registration race" failed to apply to 5.10-stable tree gregkh
2026-07-05 19:06 ` [PATCH 5.10.y 1/5] i2c: core: fix irq domain leak on adapter registration failure Sasha Levin
2026-07-05 19:06 ` Sasha Levin [this message]
2026-07-05 19:06 ` [PATCH 5.10.y 3/5] i2c: core: fix NULL-deref " Sasha Levin
2026-07-05 19:06 ` [PATCH 5.10.y 4/5] i2c: core: fix adapter debugfs creation Sasha Levin
2026-07-05 19:06 ` [PATCH 5.10.y 5/5] i2c: core: fix adapter registration race Sasha Levin
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=20260705190612.1987801-2-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=johan@kernel.org \
--cc=preid@electromag.com.au \
--cc=stable@vger.kernel.org \
--cc=wsa+renesas@sang-engineering.com \
/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