hwmon: chipcap2: synchronize ready IRQ state

The ready IRQ handler can race with reinit_completion() in the enable
path. In particular, a handler from an earlier operation can complete
the completion after it is reset for a new operation.

Use irq_lock to serialize access to the completion and process_irqs.
Disable IRQ processing and synchronize any running handler before resetting
the completion for a new operation.

Fixes: 3af350929e ("hwmon: Add support for Amphenol ChipCap 2")
Cc: stable@vger.kernel.org
Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
Link: https://patch.msgid.link/20261014-chipcap2_locks-v3-11-27ebfc2c5b9e@gmail.com
[groeck: Dropped obsolete 'Assisted-by: tag]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Javier Carrasco 2026-10-14 19:34:10 +02:00 committed by Guenter Roeck
parent bed5f0c075
commit 8c02722be2

View File

@ -123,6 +123,16 @@ static int cc2_enable(struct cc2_data *data)
{
int ret;
if (data->irq_ready > 0) {
scoped_guard(mutex, &data->irq_lock)
data->process_irqs = false;
synchronize_irq(data->irq_ready);
scoped_guard(mutex, &data->irq_lock)
reinit_completion(&data->complete);
}
/* exclusive regulator, check in case a disable failed */
if (data->regulator_enabled) {
scoped_guard(mutex, &data->irq_lock)
@ -130,9 +140,6 @@ static int cc2_enable(struct cc2_data *data)
return 0;
}
/* clear any pending completion */
try_wait_for_completion(&data->complete);
ret = regulator_enable(data->regulator);
if (ret < 0)
return ret;
@ -162,6 +169,9 @@ static void cc2_disable(struct cc2_data *data)
scoped_guard(mutex, &data->irq_lock)
data->process_irqs = false;
if (data->irq_ready > 0)
synchronize_irq(data->irq_ready);
/* exclusive regulator, check in case an enable failed */
if (!data->regulator_enabled)
return;
@ -510,8 +520,10 @@ static irqreturn_t cc2_ready_interrupt(int irq, void *data)
{
struct cc2_data *cc2 = data;
if (cc2->process_irqs)
complete(&cc2->complete);
scoped_guard(mutex, &cc2->irq_lock) {
if (cc2->process_irqs)
complete(&cc2->complete);
}
return IRQ_HANDLED;
}