Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'irq/for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

* 'irq/for-arm' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
genirq: Introduce generic irq migration for cpu hotunplug

+89
+2
include/linux/irq.h
··· 452 452 const struct cpumask *cpumask, bool force); 453 453 extern int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info); 454 454 455 + extern void irq_migrate_all_off_this_cpu(void); 456 + 455 457 #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ) 456 458 void irq_move_irq(struct irq_data *data); 457 459 void irq_move_masked_irq(struct irq_data *data);
+4
kernel/irq/Kconfig
··· 30 30 config GENERIC_PENDING_IRQ 31 31 bool 32 32 33 + # Support for generic irq migrating off cpu before the cpu is offline. 34 + config GENERIC_IRQ_MIGRATION 35 + bool 36 + 33 37 # Alpha specific irq affinity mechanism 34 38 config AUTO_IRQ_AFFINITY 35 39 bool
+1
kernel/irq/Makefile
··· 5 5 obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o 6 6 obj-$(CONFIG_PROC_FS) += proc.o 7 7 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o 8 + obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o 8 9 obj-$(CONFIG_PM_SLEEP) += pm.o 9 10 obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o
+82
kernel/irq/cpuhotplug.c
··· 1 + /* 2 + * Generic cpu hotunplug interrupt migration code copied from the 3 + * arch/arm implementation 4 + * 5 + * Copyright (C) Russell King 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + #include <linux/interrupt.h> 12 + #include <linux/ratelimit.h> 13 + #include <linux/irq.h> 14 + 15 + #include "internals.h" 16 + 17 + static bool migrate_one_irq(struct irq_desc *desc) 18 + { 19 + struct irq_data *d = irq_desc_get_irq_data(desc); 20 + const struct cpumask *affinity = d->common->affinity; 21 + struct irq_chip *c; 22 + bool ret = false; 23 + 24 + /* 25 + * If this is a per-CPU interrupt, or the affinity does not 26 + * include this CPU, then we have nothing to do. 27 + */ 28 + if (irqd_is_per_cpu(d) || 29 + !cpumask_test_cpu(smp_processor_id(), affinity)) 30 + return false; 31 + 32 + if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { 33 + affinity = cpu_online_mask; 34 + ret = true; 35 + } 36 + 37 + c = irq_data_get_irq_chip(d); 38 + if (!c->irq_set_affinity) { 39 + pr_warn_ratelimited("IRQ%u: unable to set affinity\n", d->irq); 40 + } else { 41 + int r = irq_do_set_affinity(d, affinity, false); 42 + if (r) 43 + pr_warn_ratelimited("IRQ%u: set affinity failed(%d).\n", 44 + d->irq, r); 45 + } 46 + 47 + return ret; 48 + } 49 + 50 + /** 51 + * irq_migrate_all_off_this_cpu - Migrate irqs away from offline cpu 52 + * 53 + * The current CPU has been marked offline. Migrate IRQs off this CPU. 54 + * If the affinity settings do not allow other CPUs, force them onto any 55 + * available CPU. 56 + * 57 + * Note: we must iterate over all IRQs, whether they have an attached 58 + * action structure or not, as we need to get chained interrupts too. 59 + */ 60 + void irq_migrate_all_off_this_cpu(void) 61 + { 62 + unsigned int irq; 63 + struct irq_desc *desc; 64 + unsigned long flags; 65 + 66 + local_irq_save(flags); 67 + 68 + for_each_active_irq(irq) { 69 + bool affinity_broken; 70 + 71 + desc = irq_to_desc(irq); 72 + raw_spin_lock(&desc->lock); 73 + affinity_broken = migrate_one_irq(desc); 74 + raw_spin_unlock(&desc->lock); 75 + 76 + if (affinity_broken) 77 + pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n", 78 + irq, smp_processor_id()); 79 + } 80 + 81 + local_irq_restore(flags); 82 + }