mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
regulator: Fix for v7.4
One fix here, we had an issue with deferred hardware disables where if we were deferring while suspend was happening we would let the workqueue run which could result in us trying to access hardware after it or the buses used to access it were suspended. We fix this by completing any work as we suspend the individual regulators. -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQReagvpf3TrrA7BoYYv73Ows9A4iQUCauTPJwAKCRAv73Ows9A4 ickkAP0StfBcdw1DyeDqAc3rK9y1qNE/X93ugNE+isHg3+kDEwEA0rB+UzRRODrs oR08dslt9aAOZpzj5c2alEIfnR4I7wY= =XIiE -----END PGP SIGNATURE----- Merge tag 'regulator-fix-v7.4-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator fix from Mark Brown: "One fix here, we had an issue with deferred hardware disables where if we were deferring while suspend was happening we would let the workqueue run which could result in us trying to access hardware after it or the buses used to access it were suspended. We fix this by completing any work as we suspend the individual regulators" * tag 'regulator-fix-v7.4-merge-window' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: regulator: irq: freeze deferred hardware access during suspend
This commit is contained in:
commit
2228d64da8
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
|
@ -27,6 +28,7 @@ struct regulator_irq {
|
|||
int irq;
|
||||
int retry_cnt;
|
||||
struct delayed_work isr_work;
|
||||
struct workqueue_struct *wq;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -145,12 +147,7 @@ static void regulator_notifier_isr_work(struct work_struct *work)
|
|||
return;
|
||||
|
||||
reschedule:
|
||||
if (!d->high_prio)
|
||||
mod_delayed_work(system_dfl_wq, &h->isr_work,
|
||||
msecs_to_jiffies(tmo));
|
||||
else
|
||||
mod_delayed_work(system_highpri_wq, &h->isr_work,
|
||||
msecs_to_jiffies(tmo));
|
||||
mod_delayed_work(h->wq, &h->isr_work, msecs_to_jiffies(tmo));
|
||||
}
|
||||
|
||||
static irqreturn_t regulator_notifier_isr(int irq, void *data)
|
||||
|
|
@ -248,13 +245,8 @@ static irqreturn_t regulator_notifier_isr(int irq, void *data)
|
|||
}
|
||||
|
||||
if (d->irq_off_ms) {
|
||||
if (!d->high_prio)
|
||||
schedule_delayed_work(&h->isr_work,
|
||||
msecs_to_jiffies(d->irq_off_ms));
|
||||
else
|
||||
mod_delayed_work(system_highpri_wq,
|
||||
&h->isr_work,
|
||||
msecs_to_jiffies(d->irq_off_ms));
|
||||
mod_delayed_work(h->wq, &h->isr_work,
|
||||
msecs_to_jiffies(d->irq_off_ms));
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
@ -363,13 +355,25 @@ void *regulator_irq_helper(struct device *dev,
|
|||
|
||||
init_rdev_errors(h);
|
||||
|
||||
if (h->desc.irq_off_ms)
|
||||
if (h->desc.irq_off_ms) {
|
||||
if (h->desc.high_prio) {
|
||||
h->wq = alloc_workqueue("regulator_irq_highpri",
|
||||
WQ_FREEZABLE | WQ_HIGHPRI, 0);
|
||||
if (!h->wq)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
} else {
|
||||
h->wq = system_freezable_wq;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&h->isr_work, regulator_notifier_isr_work);
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(h->irq, NULL, regulator_notifier_isr,
|
||||
IRQF_ONESHOT | irq_flags, h->desc.name, h);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to request IRQ %d\n", irq);
|
||||
if (h->desc.irq_off_ms && h->desc.high_prio)
|
||||
destroy_workqueue(h->wq);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
@ -393,8 +397,11 @@ void regulator_irq_helper_cancel(void **handle)
|
|||
struct regulator_irq *h = *handle;
|
||||
|
||||
free_irq(h->irq, h);
|
||||
if (h->desc.irq_off_ms)
|
||||
if (h->desc.irq_off_ms) {
|
||||
cancel_delayed_work_sync(&h->isr_work);
|
||||
if (h->desc.high_prio)
|
||||
destroy_workqueue(h->wq);
|
||||
}
|
||||
|
||||
h = NULL;
|
||||
}
|
||||
|
|
@ -441,4 +448,3 @@ int regulator_irq_map_event_simple(int irq, struct regulator_irq_data *rid,
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_irq_map_event_simple);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user