diff --git a/drivers/regulator/irq_helpers.c b/drivers/regulator/irq_helpers.c index 5b3cfac28667..cdbd170d2b15 100644 --- a/drivers/regulator/irq_helpers.c +++ b/drivers/regulator/irq_helpers.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #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); -