Commit 60c1d948 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'irq-core-2025-05-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq core updates from Thomas Gleixner:
 "Updates for the generic interrupt subsystem core code:

   - Address a long standing subtle problem in the CPU hotplug code for
     affinity-managed interrupts.

     Affinity-managed interrupts are shut down by the core code when the
     last CPU in the affinity set goes offline and started up again when
     the first CPU in the affinity set becomes online again.

     This unfortunately does not take into account whether an interrupt
     has been disabled before the last CPU goes offline and starts up
     the interrupt unconditionally when the first CPU becomes online
     again.

     That's obviously not what drivers expect.

     Address this by preserving the disabled state for affinity-managed
     interrupts accross these CPU hotplug operations. All non-managed
     interrupts are not affected by this because startup/shutdown is
     coupled to request/free_irq() which obviously has to reset state.

   - Support three-cell scheme interrupts to allow GPIO drivers to
     specify interrupts from an already existing scheme

   - Switch the interrupt subsystem core to lock guards. This gets rid
     of quite some copy & pasta boilerplate code all over the place.

   - The usual small cleanups and improvements all over the place"

* tag 'irq-core-2025-05-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (59 commits)
  genirq/irqdesc: Remove double locking in hwirq_show()
  genirq: Retain disable depth for managed interrupts across CPU hotplug
  genirq: Bump the size of the local variable for sprintf()
  genirq/manage: Use the correct lock guard in irq_set_irq_wake()
  genirq: Consistently use '%u' format specifier for unsigned int variables
  genirq: Ensure flags in lock guard is consistently initialized
  genirq: Fix inverted condition in handle_nested_irq()
  genirq/cpuhotplug: Fix up lock guards conversion brainf..t
  genirq: Use scoped_guard() to shut clang up
  genirq: Remove unused remove_percpu_irq()
  genirq: Remove irq_[get|put]_desc*()
  genirq/manage: Rework irq_set_irqchip_state()
  genirq/manage: Rework irq_get_irqchip_state()
  genirq/manage: Rework teardown_percpu_nmi()
  genirq/manage: Rework prepare_percpu_nmi()
  genirq/manage: Rework disable_percpu_irq()
  genirq/manage: Rework irq_percpu_is_enabled()
  genirq/manage: Rework enable_percpu_irq()
  genirq/manage: Rework irq_set_parent()
  genirq/manage: Rework can_request_irq()
  ...
parents 0c149401 a510bb87
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -140,7 +140,7 @@ extern irqreturn_t no_action(int cpl, void *dev_id);
/*
 * If a (PCI) device interrupt is not connected we set dev->irq to
 * IRQ_NOTCONNECTED. This causes request_irq() to fail with -ENOTCONN, so we
 * can distingiush that case from other error returns.
 * can distinguish that case from other error returns.
 *
 * 0x80000000 is guaranteed to be outside the available range of interrupts
 * and easy to distinguish from other possible incorrect values.
+1 −2
Original line number Diff line number Diff line
@@ -597,7 +597,6 @@ enum {

struct irqaction;
extern int setup_percpu_irq(unsigned int irq, struct irqaction *new);
extern void remove_percpu_irq(unsigned int irq, struct irqaction *act);

#ifdef CONFIG_DEPRECATED_IRQ_CPU_ONOFFLINE
extern void irq_cpu_online(void);
@@ -700,7 +699,7 @@ extern void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret);
extern int noirqdebug_setup(char *str);

/* Checks whether the interrupt can be requested by request_irq(): */
extern int can_request_irq(unsigned int irq, unsigned long irqflags);
extern bool can_request_irq(unsigned int irq, unsigned long irqflags);

/* Dummy irq-chip implementations: */
extern struct irq_chip no_irq_chip;
+10 −10
Original line number Diff line number Diff line
@@ -571,16 +571,16 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
			const u32 *intspec, unsigned int intsize,
			irq_hw_number_t *out_hwirq, unsigned int *out_type);
int irq_domain_xlate_twothreecell(struct irq_domain *d, struct device_node *ctrlr,
				  const u32 *intspec, unsigned int intsize,
				  irq_hw_number_t *out_hwirq, unsigned int *out_type);

int irq_domain_translate_twocell(struct irq_domain *d,
				 struct irq_fwspec *fwspec,
				 unsigned long *out_hwirq,
				 unsigned int *out_type);

int irq_domain_translate_onecell(struct irq_domain *d,
				 struct irq_fwspec *fwspec,
				 unsigned long *out_hwirq,
				 unsigned int *out_type);
int irq_domain_translate_onecell(struct irq_domain *d, struct irq_fwspec *fwspec,
				 unsigned long *out_hwirq, unsigned int *out_type);
int irq_domain_translate_twocell(struct irq_domain *d, struct irq_fwspec *fwspec,
				 unsigned long *out_hwirq, unsigned int *out_type);
int irq_domain_translate_twothreecell(struct irq_domain *d, struct irq_fwspec *fwspec,
				      unsigned long *out_hwirq, unsigned int *out_type);

/* IPI functions */
int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest);
+9 −17
Original line number Diff line number Diff line
@@ -43,18 +43,16 @@ unsigned long probe_irq_on(void)
	 * flush such a longstanding irq before considering it as spurious.
	 */
	for_each_irq_desc_reverse(i, desc) {
		raw_spin_lock_irq(&desc->lock);
		guard(raw_spinlock_irq)(&desc->lock);
		if (!desc->action && irq_settings_can_probe(desc)) {
			/*
			 * Some chips need to know about probing in
			 * progress:
			 */
			if (desc->irq_data.chip->irq_set_type)
				desc->irq_data.chip->irq_set_type(&desc->irq_data,
							 IRQ_TYPE_PROBE);
				desc->irq_data.chip->irq_set_type(&desc->irq_data, IRQ_TYPE_PROBE);
			irq_activate_and_startup(desc, IRQ_NORESEND);
		}
		raw_spin_unlock_irq(&desc->lock);
	}

	/* Wait for longstanding interrupts to trigger. */
@@ -66,13 +64,12 @@ unsigned long probe_irq_on(void)
	 * happened in the previous stage, it may have masked itself)
	 */
	for_each_irq_desc_reverse(i, desc) {
		raw_spin_lock_irq(&desc->lock);
		guard(raw_spinlock_irq)(&desc->lock);
		if (!desc->action && irq_settings_can_probe(desc)) {
			desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
			if (irq_activate_and_startup(desc, IRQ_NORESEND))
				desc->istate |= IRQS_PENDING;
		}
		raw_spin_unlock_irq(&desc->lock);
	}

	/*
@@ -84,18 +81,16 @@ unsigned long probe_irq_on(void)
	 * Now filter out any obviously spurious interrupts
	 */
	for_each_irq_desc(i, desc) {
		raw_spin_lock_irq(&desc->lock);

		guard(raw_spinlock_irq)(&desc->lock);
		if (desc->istate & IRQS_AUTODETECT) {
			/* It triggered already - consider it spurious. */
			if (!(desc->istate & IRQS_WAITING)) {
				desc->istate &= ~IRQS_AUTODETECT;
				irq_shutdown_and_deactivate(desc);
			} else
				if (i < 32)
			} else if (i < 32) {
				mask |= 1 << i;
			}
		raw_spin_unlock_irq(&desc->lock);
		}
	}

	return mask;
@@ -121,7 +116,7 @@ unsigned int probe_irq_mask(unsigned long val)
	int i;

	for_each_irq_desc(i, desc) {
		raw_spin_lock_irq(&desc->lock);
		guard(raw_spinlock_irq)(&desc->lock);
		if (desc->istate & IRQS_AUTODETECT) {
			if (i < 16 && !(desc->istate & IRQS_WAITING))
				mask |= 1 << i;
@@ -129,7 +124,6 @@ unsigned int probe_irq_mask(unsigned long val)
			desc->istate &= ~IRQS_AUTODETECT;
			irq_shutdown_and_deactivate(desc);
		}
		raw_spin_unlock_irq(&desc->lock);
	}
	mutex_unlock(&probing_active);

@@ -160,8 +154,7 @@ int probe_irq_off(unsigned long val)
	struct irq_desc *desc;

	for_each_irq_desc(i, desc) {
		raw_spin_lock_irq(&desc->lock);

		guard(raw_spinlock_irq)(&desc->lock);
		if (desc->istate & IRQS_AUTODETECT) {
			if (!(desc->istate & IRQS_WAITING)) {
				if (!nr_of_irqs)
@@ -171,7 +164,6 @@ int probe_irq_off(unsigned long val)
			desc->istate &= ~IRQS_AUTODETECT;
			irq_shutdown_and_deactivate(desc);
		}
		raw_spin_unlock_irq(&desc->lock);
	}
	mutex_unlock(&probing_active);

+264 −367

File changed.

Preview size limit exceeded, changes collapsed.

Loading