Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8df2e02c authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Rafael J. Wysocki
Browse files

genirq: Move suspend/resume logic into irq/pm code



No functional change. Preparatory patch for cleaning up the suspend
abort functionality. Update the comments while at it.

Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 068765ba
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -63,8 +63,8 @@ enum {

extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
		unsigned long flags);
extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
extern void __disable_irq(struct irq_desc *desc, unsigned int irq);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq);

extern int irq_startup(struct irq_desc *desc, bool resend);
extern void irq_shutdown(struct irq_desc *desc);
+5 −23
Original line number Diff line number Diff line
@@ -382,14 +382,8 @@ setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
}
#endif

void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
void __disable_irq(struct irq_desc *desc, unsigned int irq)
{
	if (suspend) {
		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
			return;
		desc->istate |= IRQS_SUSPENDED;
	}

	if (!desc->depth++)
		irq_disable(desc);
}
@@ -401,7 +395,7 @@ static int __disable_irq_nosync(unsigned int irq)

	if (!desc)
		return -EINVAL;
	__disable_irq(desc, irq, false);
	__disable_irq(desc, irq);
	irq_put_desc_busunlock(desc, flags);
	return 0;
}
@@ -442,20 +436,8 @@ void disable_irq(unsigned int irq)
}
EXPORT_SYMBOL(disable_irq);

void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
void __enable_irq(struct irq_desc *desc, unsigned int irq)
{
	if (resume) {
		if (!(desc->istate & IRQS_SUSPENDED)) {
			if (!desc->action)
				return;
			if (!(desc->action->flags & IRQF_FORCE_RESUME))
				return;
			/* Pretend that it got disabled ! */
			desc->depth++;
		}
		desc->istate &= ~IRQS_SUSPENDED;
	}

	switch (desc->depth) {
	case 0:
 err_out:
@@ -497,7 +479,7 @@ void enable_irq(unsigned int irq)
		 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
		goto out;

	__enable_irq(desc, irq, false);
	__enable_irq(desc, irq);
out:
	irq_put_desc_busunlock(desc, flags);
}
@@ -1228,7 +1210,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
	 */
	if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
		desc->istate &= ~IRQS_SPURIOUS_DISABLED;
		__enable_irq(desc, irq, false);
		__enable_irq(desc, irq);
	}

	raw_spin_unlock_irqrestore(&desc->lock, flags);
+38 −6
Original line number Diff line number Diff line
@@ -13,13 +13,26 @@

#include "internals.h"

static void suspend_device_irq(struct irq_desc *desc, int irq)
{
	if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
		return;

	desc->istate |= IRQS_SUSPENDED;
	__disable_irq(desc, irq);
}

/**
 * suspend_device_irqs - disable all currently enabled interrupt lines
 *
 * During system-wide suspend or hibernation device drivers need to be prevented
 * from receiving interrupts and this function is provided for this purpose.
 * It marks all interrupt lines in use, except for the timer ones, as disabled
 * and sets the IRQS_SUSPENDED flag for each of them.
 * During system-wide suspend or hibernation device drivers need to be
 * prevented from receiving interrupts and this function is provided
 * for this purpose.
 *
 * So we disable all interrupts and mark them IRQS_SUSPENDED except
 * for those which are unused and those which are marked as not
 * suspendable via an interrupt request with the flag IRQF_NO_SUSPEND
 * set.
 */
void suspend_device_irqs(void)
{
@@ -30,7 +43,7 @@ void suspend_device_irqs(void)
		unsigned long flags;

		raw_spin_lock_irqsave(&desc->lock, flags);
		__disable_irq(desc, irq, true);
		suspend_device_irq(desc, irq);
		raw_spin_unlock_irqrestore(&desc->lock, flags);
	}

@@ -40,6 +53,25 @@ void suspend_device_irqs(void)
}
EXPORT_SYMBOL_GPL(suspend_device_irqs);

static void resume_irq(struct irq_desc *desc, int irq)
{
	if (desc->istate & IRQS_SUSPENDED)
		goto resume;

	if (!desc->action)
		return;

	/* Interrupts marked with that flag are force reenabled */
	if (!(desc->action->flags & IRQF_FORCE_RESUME))
		return;

	/* Pretend that it got disabled ! */
	desc->depth++;
resume:
	desc->istate &= ~IRQS_SUSPENDED;
	__enable_irq(desc, irq);
}

static void resume_irqs(bool want_early)
{
	struct irq_desc *desc;
@@ -54,7 +86,7 @@ static void resume_irqs(bool want_early)
			continue;

		raw_spin_lock_irqsave(&desc->lock, flags);
		__enable_irq(desc, irq, true);
		resume_irq(desc, irq);
		raw_spin_unlock_irqrestore(&desc->lock, flags);
	}
}