[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20260127160512.577735-1-alexander.sverdlin@siemens.com>
Date: Tue, 27 Jan 2026 17:05:06 +0100
From: "A. Sverdlin" <alexander.sverdlin@...mens.com>
To: Vijai Kumar K <vijaikumar.kanagarajan@...il.com>,
linux-kernel@...r.kernel.org
Cc: Alexander Sverdlin <alexander.sverdlin@...mens.com>,
Krzysztof Kozlowski <krzk@...nel.org>,
MyungJoo Ham <myungjoo.ham@...sung.com>,
Chanwoo Choi <cw00.choi@...sung.com>,
stable@...r.kernel.org
Subject: [PATCH] extcon: ptn5150: Avoid IRQ vs probe race and drop mutex
From: Alexander Sverdlin <alexander.sverdlin@...mens.com>
The IRQ is being requested quite early in probe sequence, where neither
mutex has been taken, nor info->edev has been set yet. From this point on
one shall expect the handler to be called. The corresponding test for
!info->edev looks pointless being not protected by the mutex.
Moving the IRQ request to the end of probe sequence avoids the race against
ptn5150_check_state() and other init steps (devm_extcon_dev_allocate(),
devm_extcon_dev_register()).
Finally it becomes obvious that the worker function doesn't run
concurrently with anything else and we can drop the mutex completely.
The change has been motivated by the following crash:
Unable to handle kernel paging request at virtual address 006c727400353434
CPU: 1 UID: 0 PID: 74 Comm: kworker/1:2 6.18.0-next-20251212
Workqueue: events ptn5150_irq_work [extcon_ptn5150]
pc : 0x6c727400353434
lr : notifier_call_chain+0x80
Call trace:
0x6c727400353434 (P)
raw_notifier_call_chain+0x20
extcon_sync+0xd0
extcon_set_state_sync+0x3c
ptn5150_check_state+0xf8 [extcon_ptn5150]
ptn5150_irq_work [extcon_ptn5150]
process_one_work
worker_thread
kthread
ret_from_fork
Kernel panic - not syncing: Oops: Fatal exception
Cc: stable@...r.kernel.org
Fixes: 4ed754de2d66 ("extcon: Add support for ptn5150 extcon driver")
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@...mens.com>
---
drivers/extcon/extcon-ptn5150.c | 38 ++++++++++-----------------------
1 file changed, 11 insertions(+), 27 deletions(-)
diff --git a/drivers/extcon/extcon-ptn5150.c b/drivers/extcon/extcon-ptn5150.c
index eca1b140aeb0f..cb5646bf91c5e 100644
--- a/drivers/extcon/extcon-ptn5150.c
+++ b/drivers/extcon/extcon-ptn5150.c
@@ -57,7 +57,6 @@ struct ptn5150_info {
struct gpio_desc *vbus_gpiod;
int irq;
struct work_struct irq_work;
- struct mutex mutex;
struct typec_switch *orient_sw;
struct usb_role_switch *role_sw;
};
@@ -144,16 +143,10 @@ static void ptn5150_irq_work(struct work_struct *work)
int ret = 0;
unsigned int int_status;
- if (!info->edev)
- return;
-
- mutex_lock(&info->mutex);
-
/* Clear interrupt. Read would clear the register */
ret = regmap_read(info->regmap, PTN5150_REG_INT_STATUS, &int_status);
if (ret) {
dev_err(info->dev, "failed to read INT STATUS %d\n", ret);
- mutex_unlock(&info->mutex);
return;
}
@@ -188,14 +181,9 @@ static void ptn5150_irq_work(struct work_struct *work)
/* Clear interrupt. Read would clear the register */
ret = regmap_read(info->regmap, PTN5150_REG_INT_REG_STATUS,
&int_status);
- if (ret) {
+ if (ret)
dev_err(info->dev,
"failed to read INT REG STATUS %d\n", ret);
- mutex_unlock(&info->mutex);
- return;
- }
-
- mutex_unlock(&info->mutex);
}
@@ -281,8 +269,6 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
}
}
- mutex_init(&info->mutex);
-
INIT_WORK(&info->irq_work, ptn5150_irq_work);
info->regmap = devm_regmap_init_i2c(i2c, &ptn5150_regmap_config);
@@ -307,16 +293,6 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
}
}
- ret = devm_request_threaded_irq(dev, info->irq, NULL,
- ptn5150_irq_handler,
- IRQF_TRIGGER_FALLING |
- IRQF_ONESHOT,
- i2c->name, info);
- if (ret < 0) {
- dev_err(dev, "failed to request handler for INTB IRQ\n");
- return ret;
- }
-
/* Allocate extcon device */
info->edev = devm_extcon_dev_allocate(info->dev, ptn5150_extcon_cable);
if (IS_ERR(info->edev)) {
@@ -366,9 +342,17 @@ static int ptn5150_i2c_probe(struct i2c_client *i2c)
* Update current extcon state if for example OTG connection was there
* before the probe
*/
- mutex_lock(&info->mutex);
ptn5150_check_state(info);
- mutex_unlock(&info->mutex);
+
+ ret = devm_request_threaded_irq(dev, info->irq, NULL,
+ ptn5150_irq_handler,
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ i2c->name, info);
+ if (ret < 0) {
+ dev_err(dev, "failed to request handler for INTB IRQ\n");
+ return ret;
+ }
return 0;
}
--
2.52.0
Powered by blists - more mailing lists