* [PATCH v2] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler
@ 2026-11-13 11:53 Jishnu Prakash
2026-11-13 15:14 ` Andy Shevchenko
0 siblings, 1 reply; 2+ messages in thread
From: Jishnu Prakash @ 2026-11-13 11:53 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}
Call trace:
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.
Note that both handlers used a local variable to hold the index of the
SDAM whose IRQ was triggered ('sdam_num' in the primary handler and
'sdam_index' in the thread function). These are the same value under
different names and 'sdam_index' is kept now, since that is the name
used for it at other places in the file.
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>
---
Changes in v2:
- Trimmed call stack and error lines and added clarification about sdam_index
in commit message, as suggested by Andy.
- Link to v1: https://patch.msgid.link/20261111-adctm5_gen3_hardirq_removal-v1-1-536ed503396c@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 related [flat|nested] 2+ messages in thread* Re: [PATCH v2] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler
2026-11-13 11:53 [PATCH v2] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler Jishnu Prakash
@ 2026-11-13 15:14 ` Andy Shevchenko
0 siblings, 0 replies; 2+ messages in thread
From: Andy Shevchenko @ 2026-11-13 15:14 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 Fri, Nov 13, 2026 at 05:23:03PM +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}
>
> Call trace:
> 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.
>
> Note that both handlers used a local variable to hold the index of the
> SDAM whose IRQ was triggered ('sdam_num' in the primary handler and
> 'sdam_index' in the thread function). These are the same value under
> different names and 'sdam_index' is kept now, since that is the name
> used for it at other places in the file.
But this is not the point. The point should be semantics of the variable
and not frequency of use.
...
> -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;
I probably missed to point that at the same time we can split semantically
different variables.
struct adc_tm5_gen3_chip *adc_tm5 = dev_id;
u8 tm_status[2];
u8 status, val;
int sdam_index;
int ret;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-13 15:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-13 11:53 [PATCH v2] thermal: qcom-spmi-adc-tm5-gen3: move hardirq actions into threaded handler Jishnu Prakash
2026-11-13 15:14 ` Andy Shevchenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox