diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index ef7e1289ad7e..f3d833be0e1a 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -1290,28 +1291,15 @@ irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id) } EXPORT_SYMBOL_GPL(mei_me_irq_quick_handler); -/** - * mei_me_irq_thread_handler - function called after ISR to handle the interrupt - * processing. - * - * @irq: The irq number - * @dev_id: pointer to the device structure - * - * Return: irqreturn_t - * - */ -irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) +static irqreturn_t __mei_me_irq_thread_handler(struct mei_device *dev) { - struct mei_device *dev = (struct mei_device *) dev_id; struct list_head cmpl_list; bool pg_blocked; s32 slots; u32 hcsr; int rets = 0; - dev_dbg(&dev->dev, "function called after ISR to handle the interrupt processing.\n"); /* initialize our complete list */ - mutex_lock(&dev->device_lock); hcsr = mei_hcsr_read(dev); me_intr_clear(dev, hcsr); @@ -1406,13 +1394,33 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) end: dev_dbg(&dev->dev, "interrupt thread end ret = %d\n", rets); mei_me_intr_enable(dev); - mutex_unlock(&dev->device_lock); return IRQ_HANDLED; } + +/** + * mei_me_irq_thread_handler - function called after ISR to handle the interrupt + * processing. + * + * @irq: The irq number + * @dev_id: pointer to the device structure + * + * Return: irqreturn_t + * + */ +irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) +{ + struct mei_device *dev = (struct mei_device *) dev_id; + + dev_dbg(&dev->dev, "function called after ISR to handle the interrupt processing.\n"); + + guard(mutex)(&dev->device_lock); + + return __mei_me_irq_thread_handler(dev); +} EXPORT_SYMBOL_GPL(mei_me_irq_thread_handler); -#define MEI_POLLING_TIMEOUT_ACTIVE 100 -#define MEI_POLLING_TIMEOUT_IDLE 500 +#define MEI_POLL_ACTIVE_MS 100 +#define MEI_POLL_IDLE_MS 500 /** * mei_me_polling_thread - interrupt register polling thread @@ -1420,48 +1428,59 @@ EXPORT_SYMBOL_GPL(mei_me_irq_thread_handler); * @_dev: mei device * * The thread monitors the interrupt source register and calls - * mei_me_irq_thread_handler() to handle the firmware + * __mei_me_irq_thread_handler() to handle the firmware * input. * - * The function polls in MEI_POLLING_TIMEOUT_ACTIVE timeout + * The function polls in MEI_POLL_ACTIVE_MS timeout * in case there was an event, in idle case the polling - * time increases yet again by MEI_POLLING_TIMEOUT_ACTIVE - * up to MEI_POLLING_TIMEOUT_IDLE. + * time increases yet again by MEI_POLL_ACTIVE_MS + * up to MEI_POLL_IDLE_MS. * * Return: always 0 */ int mei_me_polling_thread(void *_dev) { struct mei_device *dev = _dev; - irqreturn_t irq_ret; - long polling_timeout = MEI_POLLING_TIMEOUT_ACTIVE; + long polling_timeout = MEI_POLL_ACTIVE_MS; + bool have_interrupt; dev_dbg(&dev->dev, "kernel thread is running\n"); while (!kthread_should_stop()) { struct mei_me_hw *hw = to_me_hw(dev); u32 hcsr; - wait_event_interruptible_timeout(hw->wait_active, - hw->is_active || kthread_should_stop(), - msecs_to_jiffies(MEI_POLLING_TIMEOUT_IDLE)); + if (!hw->is_active) + wait_event_interruptible(hw->wait_active, + hw->is_active || kthread_should_stop()); + else + wait_event_interruptible_timeout(hw->wait_active, + hw->is_active || kthread_should_stop(), + msecs_to_jiffies(MEI_POLL_IDLE_MS)); if (kthread_should_stop()) break; - hcsr = mei_hcsr_read(dev); - if (me_intr_src(hcsr)) { - polling_timeout = MEI_POLLING_TIMEOUT_ACTIVE; - irq_ret = mei_me_irq_thread_handler(1, dev); - if (irq_ret != IRQ_HANDLED) - dev_err(&dev->dev, "irq_ret %d\n", irq_ret); - } else { - /* - * Increase timeout by MEI_POLLING_TIMEOUT_ACTIVE - * up to MEI_POLLING_TIMEOUT_IDLE - */ - polling_timeout = clamp_val(polling_timeout + MEI_POLLING_TIMEOUT_ACTIVE, - MEI_POLLING_TIMEOUT_ACTIVE, - MEI_POLLING_TIMEOUT_IDLE); + scoped_guard(mutex, &dev->device_lock) { + if (!hw->is_active) { + have_interrupt = false; + } else { + hcsr = mei_hcsr_read(dev); + have_interrupt = !!me_intr_src(hcsr); + } + + if (have_interrupt) { + polling_timeout = MEI_POLL_ACTIVE_MS; + dev_dbg(&dev->dev, "polling interrupt processing\n"); + __mei_me_irq_thread_handler(dev); + } else { + /* + * Increase timeout by MEI_POLL_ACTIVE_MS + * up to MEI_POLL_IDLE_MS + */ + polling_timeout = clamp_val(polling_timeout + MEI_POLL_ACTIVE_MS, + MEI_POLL_ACTIVE_MS, + MEI_POLL_IDLE_MS); + } } schedule_timeout_interruptible(msecs_to_jiffies(polling_timeout));