mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
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:
parent
bed5f0c075
commit
8c02722be2
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user