[PATCH RFC 03/12] genirq: Implement dynamic migration for Managed IRQs

Qiliang Yuan posted 12 patches 2 days, 21 hours ago
[PATCH RFC 03/12] genirq: Implement dynamic migration for Managed IRQs
Posted by Qiliang Yuan 2 days, 21 hours ago
Support dynamic reconfiguration of CPU isolation by making the managed
interrupts responsive to housekeeping mask changes at runtime.

1. Register a housekeeping notifier in the genirq subsystem to listen
   for HK_TYPE_MANAGED_IRQ updates.
2. Iterate through all active interrupts when a mask update occurs.
3. Re-apply affinity for managed interrupts to ensure they honor the
   newly configured housekeeping mask.
4. Use irq_set_affinity_locked() to trigger migration away from newly
   isolated CPUs or towards newly designated housekeeping CPUs.

Signed-off-by: Qiliang Yuan <realwujing@gmail.com>
Signed-off-by: Qiliang Yuan <yuanql9@chinatelecom.cn>
---
 kernel/irq/manage.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 349ae7979da0..9523f0655b12 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -21,6 +21,7 @@
 #include <linux/sched/isolation.h>
 #include <uapi/linux/sched/types.h>
 #include <linux/task_work.h>
+#include <linux/cpuhotplug.h>
 
 #include "internals.h"
 
@@ -2811,3 +2812,54 @@ bool irq_check_status_bit(unsigned int irq, unsigned int bitmask)
 	return res;
 }
 EXPORT_SYMBOL_GPL(irq_check_status_bit);
+
+#ifdef CONFIG_SMP
+static int irq_housekeeping_reconfigure(struct notifier_block *nb,
+					unsigned long action, void *data)
+{
+	struct housekeeping_update *upd = data;
+	struct irq_desc *desc;
+	unsigned int irq;
+
+	if (action != HK_UPDATE_MASK || upd->type != HK_TYPE_MANAGED_IRQ)
+		return NOTIFY_OK;
+
+	irq_lock_sparse();
+	for_each_active_irq(irq) {
+		struct irq_data *id;
+
+		desc = irq_to_desc(irq);
+		if (!desc)
+			continue;
+
+		scoped_guard(raw_spinlock_irqsave, &desc->lock) {
+			id = irq_desc_get_irq_data(desc);
+			if (!irqd_affinity_is_managed(id) || !desc->action ||
+			    !irq_data_get_irq_chip(id))
+				continue;
+
+			/*
+			 * Re-apply existing affinity to honor the new
+			 * housekeeping mask via __irq_set_affinity() logic.
+			 */
+			irq_set_affinity_locked(id, irq_data_get_affinity_mask(id), false);
+		}
+	}
+	irq_unlock_sparse();
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block irq_housekeeping_nb = {
+	.notifier_call = irq_housekeeping_reconfigure,
+};
+
+static int __init irq_init_housekeeping_notifier(void)
+{
+	housekeeping_register_notifier(&irq_housekeeping_nb);
+	return 0;
+}
+core_initcall(irq_init_housekeeping_notifier);
+#endif
+
+

-- 
2.51.0
Re: [PATCH RFC 03/12] genirq: Implement dynamic migration for Managed IRQs
Posted by Thomas Gleixner 2 days, 15 hours ago
On Fri, Feb 06 2026 at 02:04, Qiliang Yuan wrote:

s/Managed IRQs/managed interrupts/ in $subject

> Support dynamic reconfiguration of CPU isolation by making the managed
> interrupts responsive to housekeeping mask changes at runtime.
>
> 1. Register a housekeeping notifier in the genirq subsystem to listen
>    for HK_TYPE_MANAGED_IRQ updates.
> 2. Iterate through all active interrupts when a mask update occurs.
> 3. Re-apply affinity for managed interrupts to ensure they honor the
>    newly configured housekeeping mask.
> 4. Use irq_set_affinity_locked() to trigger migration away from newly
>    isolated CPUs or towards newly designated housekeeping CPUs.

Please don't explain implementation details in the change log. They can
be seen from the patch. Explain the why and the concept of the change

https://www.kernel.org/doc/html/latest/process/maintainer-tip.html#changelog

> Signed-off-by: Qiliang Yuan <realwujing@gmail.com>
> Signed-off-by: Qiliang Yuan <yuanql9@chinatelecom.cn>

So you developed that together with your alter ego? Pick one please.

> +#ifdef CONFIG_SMP
> +static int irq_housekeeping_reconfigure(struct notifier_block *nb,
> +					unsigned long action, void *data)
> +{
> +	struct housekeeping_update *upd = data;
> +	struct irq_desc *desc;

Move desc into the loop

> +	unsigned int irq;
> +
> +	if (action != HK_UPDATE_MASK || upd->type != HK_TYPE_MANAGED_IRQ)
> +		return NOTIFY_OK;
> +
> +	irq_lock_sparse();
> +	for_each_active_irq(irq) {
> +		struct irq_data *id;

id is really not a intuitive name. Most code here uses 'irqd'.

> +		desc = irq_to_desc(irq);
> +		if (!desc)
> +			continue;
> +
> +		scoped_guard(raw_spinlock_irqsave, &desc->lock) {

raw_spinlock_irq. There is nothing to save here as this is preemptible
thread context, no?

You can simplify all of the above by using:

	scoped_irqdesc_get_and_lock(irq, 0) {
        	struct irq_data *irqd = irq_desc_get_irq_data(scoped_irqdesc);

                ....

> +			id = irq_desc_get_irq_data(desc);
> +			if (!irqd_affinity_is_managed(id) || !desc->action ||
> +			    !irq_data_get_irq_chip(id))

No line break required. You have 100 characters.

> +				continue;

Thanks,

        tglx