* [PATCH] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler
@ 2026-11-11 8:42 Jishnu Prakash
2026-11-11 14:23 ` Andy Shevchenko
0 siblings, 1 reply; 2+ messages in thread
From: Jishnu Prakash @ 2026-11-11 8:42 UTC (permalink / raw)
To: Amit Kucheria, Thara Gopinath, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, Andy Shevchenko
Cc: linux-arm-msm, linux-pm, linux-kernel, kamal.wadhwa,
Pankaj Patil, Jishnu Prakash
adc_tm5_probe() registers the ADC_TM interrupt with both a primary
handler and thread function (adctm5_gen3_isr/adctm5_gen3_isr_thread)
with IRQF_ONESHOT. The primary handler calls adc5_gen3_read(), which
takes the SPMI regmap's lock (a regular, non-raw spinlock) from hardirq
context. With CONFIG_PROVE_LOCKING enabled, this leads to a warning
about an attempt to take a lock in an invalid wait context:
swapper/0/0 is trying to lock:
ffff000b67201018
(qcom_spmi_pmic:259:(&spmi_regmap_config)->lock){....}-{3:3}, at:
regmap_lock_spinlock+0x20/0x40
other info that might help us debug this:
context-{2:2}
locks held by swapper/0/0: 0, last CPU#0
stack backtrace:
CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.4.0-rc1 #1 PREEMPT(full)
Call trace:
check_wait_context.isra.0+0x2d8/0x380
__lock_acquire+0x2ec/0x840
lock_acquire.part.0+0xe0/0x250
lock_acquire+0x8c/0x1e0
_raw_spin_lock_irqsave+0x6c/0xd8
regmap_lock_spinlock+0x20/0x40
regmap_raw_read+0x88/0x328
regmap_bulk_read+0x10c/0x340
adc5_gen3_read+0x38/0x50 [qcom_spmi_adc5_gen3]
adctm5_gen3_isr+0x90/0x130 [qcom_spmi_adc_tm5_gen3]
There is no requirement for any of the work done in the primary handler
to run in hardirq context. Drop the primary handler and move all the
actions in it to the threaded handler, which removes the invalid wait
context warning.
Reported-by: Pankaj Patil <pankaj.patil@oss.qualcomm.com>
Closes: https://lore.kernel.org/all/1cb6d902-73f3-4d65-96f4-4b3c5217253c@oss.qualcomm.com/
Fixes: 948ee3a74f35 ("thermal/drivers/qcom: add support for PMIC5 Gen3 ADC thermal monitoring")
Signed-off-by: Jishnu Prakash <jishnu.prakash@oss.qualcomm.com>
---
drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c | 41 +++++++--------------------
1 file changed, 10 insertions(+), 31 deletions(-)
diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c
index 910b241fa94d..996bfcfcac35 100644
--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c
+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5-gen3.c
@@ -73,58 +73,38 @@ static int get_sdam_from_irq(struct adc_tm5_gen3_chip *adc_tm5, int irq)
return -ENOENT;
}
-static irqreturn_t adctm5_gen3_isr(int irq, void *dev_id)
+static irqreturn_t adctm5_gen3_isr_thread(int irq, void *dev_id)
{
struct adc_tm5_gen3_chip *adc_tm5 = dev_id;
- int ret, sdam_num;
+ int sdam_index, ret;
u8 tm_status[2];
u8 status, val;
- sdam_num = get_sdam_from_irq(adc_tm5, irq);
- if (sdam_num < 0)
+ sdam_index = get_sdam_from_irq(adc_tm5, irq);
+ if (sdam_index < 0)
return IRQ_NONE;
- ret = adc5_gen3_read(adc_tm5->dev_data, sdam_num, ADC5_GEN3_STATUS1,
+ ret = adc5_gen3_read(adc_tm5->dev_data, sdam_index, ADC5_GEN3_STATUS1,
&status, sizeof(status));
if (ret)
return IRQ_NONE;
if (status & ADC5_GEN3_STATUS1_CONV_FAULT) {
val = ADC5_GEN3_CONV_ERR_CLR_REQ;
- adc5_gen3_status_clear(adc_tm5->dev_data, sdam_num,
+ adc5_gen3_status_clear(adc_tm5->dev_data, sdam_index,
ADC5_GEN3_CONV_ERR_CLR, &val, 1);
return IRQ_HANDLED;
}
- ret = adc5_gen3_read(adc_tm5->dev_data, sdam_num, ADC5_GEN3_TM_HIGH_STS,
- tm_status, sizeof(tm_status));
- if (ret)
- return IRQ_NONE;
-
- if (tm_status[0] || tm_status[1])
- return IRQ_WAKE_THREAD;
-
- return IRQ_NONE;
-}
-
-static irqreturn_t adctm5_gen3_isr_thread(int irq, void *dev_id)
-{
- struct adc_tm5_gen3_chip *adc_tm5 = dev_id;
- u8 tm_status[2];
- int sdam_index;
-
- sdam_index = get_sdam_from_irq(adc_tm5, irq);
- if (sdam_index < 0)
- return IRQ_NONE;
-
scoped_guard(adc5_gen3, adc_tm5) {
- int ret;
-
ret = adc5_gen3_read(adc_tm5->dev_data, sdam_index, ADC5_GEN3_TM_HIGH_STS,
tm_status, sizeof(tm_status));
if (ret)
return IRQ_NONE;
+ if (!(tm_status[0] || tm_status[1]))
+ return IRQ_NONE;
+
ret = adc5_gen3_status_clear(adc_tm5->dev_data, sdam_index,
ADC5_GEN3_TM_HIGH_STS_CLR, tm_status,
sizeof(tm_status));
@@ -405,8 +385,7 @@ static int adc_tm5_probe(struct auxiliary_device *aux_dev,
ret = devm_request_threaded_irq(dev,
adc_tm5->dev_data->base[i].irq,
- adctm5_gen3_isr,
- adctm5_gen3_isr_thread,
+ NULL, adctm5_gen3_isr_thread,
irq_flags,
adc_tm5->dev_data->base[i].irq_name,
adc_tm5);
---
base-commit: 7475ea8b58616b33c04afb976cf0fbaad9dd63fb
change-id: 20261111-adctm5_gen3_hardirq_removal-467a437a78e1
Best regards,
--
Jishnu Prakash <jishnu.prakash@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler
2026-11-11 8:42 [PATCH] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler Jishnu Prakash
@ 2026-11-11 14:23 ` Andy Shevchenko
0 siblings, 0 replies; 2+ messages in thread
From: Andy Shevchenko @ 2026-11-11 14:23 UTC (permalink / raw)
To: Jishnu Prakash
Cc: Amit Kucheria, Thara Gopinath, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-arm-msm, linux-pm, linux-kernel,
kamal.wadhwa, Pankaj Patil
On Wed, Nov 11, 2026 at 02:12:01PM +0530, Jishnu Prakash wrote:
> adc_tm5_probe() registers the ADC_TM interrupt with both a primary
> handler and thread function (adctm5_gen3_isr/adctm5_gen3_isr_thread)
> with IRQF_ONESHOT. The primary handler calls adc5_gen3_read(), which
> takes the SPMI regmap's lock (a regular, non-raw spinlock) from hardirq
> context. With CONFIG_PROVE_LOCKING enabled, this leads to a warning
> about an attempt to take a lock in an invalid wait context:
>
> swapper/0/0 is trying to lock:
> ffff000b67201018
> (qcom_spmi_pmic:259:(&spmi_regmap_config)->lock){....}-{3:3}, at:
> regmap_lock_spinlock+0x20/0x40
> other info that might help us debug this:
> context-{2:2}
> locks held by swapper/0/0: 0, last CPU#0
> stack backtrace:
>
> CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.4.0-rc1 #1 PREEMPT(full)
>
> Call trace:
> check_wait_context.isra.0+0x2d8/0x380
> __lock_acquire+0x2ec/0x840
> lock_acquire.part.0+0xe0/0x250
> lock_acquire+0x8c/0x1e0
Please, drop unneeded churn, since regmap_lock_spinlock() the rest is not needed.
It's all documented in Submitting Patches, take your time to read and study that
document.
> _raw_spin_lock_irqsave+0x6c/0xd8
> regmap_lock_spinlock+0x20/0x40
> regmap_raw_read+0x88/0x328
> regmap_bulk_read+0x10c/0x340
> adc5_gen3_read+0x38/0x50 [qcom_spmi_adc5_gen3]
> adctm5_gen3_isr+0x90/0x130 [qcom_spmi_adc_tm5_gen3]
>
> There is no requirement for any of the work done in the primary handler
> to run in hardirq context. Drop the primary handler and move all the
> actions in it to the threaded handler, which removes the invalid wait
> context warning.
...
> -static irqreturn_t adctm5_gen3_isr(int irq, void *dev_id)
> +static irqreturn_t adctm5_gen3_isr_thread(int irq, void *dev_id)
> {
> struct adc_tm5_gen3_chip *adc_tm5 = dev_id;
> - int ret, sdam_num;
> + int sdam_index, ret;
Was the variable rename so important for the fix? Can we defer it to the later
cleanups, if ever needed?
> u8 tm_status[2];
> u8 status, val;
...
> - struct adc_tm5_gen3_chip *adc_tm5 = dev_id;
> - u8 tm_status[2];
> - int sdam_index;
Okay, I see the reason now why it's done, but I noticed no mention of this in
the commit message. Also it's unclear which variable is used more often and
what is the real semantics of its value. Is it number or index? With all this
in mind, please at bare minimum elaborate in the commit message and, if it's
actually a number, replace the other part instead.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-11 14:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-11 8:42 [PATCH] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler Jishnu Prakash
2026-11-11 14:23 ` Andy Shevchenko
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®