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

powerpc/irqdomain: Fix broken NR_IRQ references

The switch from using irq_map to irq_alloc_desc*() for managing irq
number allocations introduced new bugs in some of the powerpc
interrupt code. Several functions rely on the value of NR_IRQS to
determine the maximum irq number that could get allocated. However,
with sparse_irq and using irq_alloc_desc*() the maximum possible irq
number is now specified with 'nr_irqs' which may be a number larger
than NR_IRQS. This has caused breakage on powermac when
CONFIG_NR_IRQS is set to 32.

This patch removes most of the direct references to NR_IRQS in the
powerpc code and replaces them with either a nr_irqs reference or by
using the common for_each_irq_desc() macro. The powerpc-specific
for_each_irq() macro is removed at the same time.

Also, the Cell axon_msi driver is refactored to remove the global
build assumption on the size of NR_IRQS and instead add a limit to the
maximum irq number when calling irq_domain_add_nomap().

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Grant Likely and committed by
Benjamin Herrenschmidt
4013369f 8751ed14

+14 -29
-4
arch/powerpc/include/asm/irq.h
··· 18 18 #include <linux/atomic.h> 19 19 20 20 21 - /* Define a way to iterate across irqs. */ 22 - #define for_each_irq(i) \ 23 - for ((i) = 0; (i) < NR_IRQS; ++(i)) 24 - 25 21 extern atomic_t ppc_n_lost_interrupts; 26 22 27 23 /* This number is used when no interrupt has been assigned */
+1 -5
arch/powerpc/kernel/irq.c
··· 330 330 331 331 alloc_cpumask_var(&mask, GFP_KERNEL); 332 332 333 - for_each_irq(irq) { 333 + for_each_irq_desc(irq, desc) { 334 334 struct irq_data *data; 335 335 struct irq_chip *chip; 336 - 337 - desc = irq_to_desc(irq); 338 - if (!desc) 339 - continue; 340 336 341 337 data = irq_desc_get_irq_data(desc); 342 338 if (irqd_is_per_cpu(data))
+2 -5
arch/powerpc/kernel/machine_kexec.c
··· 23 23 24 24 void machine_kexec_mask_interrupts(void) { 25 25 unsigned int i; 26 + struct irq_desc *desc; 26 27 27 - for_each_irq(i) { 28 - struct irq_desc *desc = irq_to_desc(i); 28 + for_each_irq_desc(i, desc) { 29 29 struct irq_chip *chip; 30 - 31 - if (!desc) 32 - continue; 33 30 34 31 chip = irq_desc_get_chip(desc); 35 32 if (!chip)
+3 -5
arch/powerpc/platforms/cell/axon_msi.c
··· 114 114 pr_devel("axon_msi: woff %x roff %x msi %x\n", 115 115 write_offset, msic->read_offset, msi); 116 116 117 - if (msi < NR_IRQS && irq_get_chip_data(msi) == msic) { 117 + if (msi < nr_irqs && irq_get_chip_data(msi) == msic) { 118 118 generic_handle_irq(msi); 119 119 msic->fifo_virt[idx] = cpu_to_le32(0xffffffff); 120 120 } else { ··· 276 276 if (rc) 277 277 return rc; 278 278 279 - /* We rely on being able to stash a virq in a u16 */ 280 - BUILD_BUG_ON(NR_IRQS > 65536); 281 - 282 279 list_for_each_entry(entry, &dev->msi_list, list) { 283 280 virq = irq_create_direct_mapping(msic->irq_domain); 284 281 if (virq == NO_IRQ) { ··· 389 392 } 390 393 memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES); 391 394 392 - msic->irq_domain = irq_domain_add_nomap(dn, 0, &msic_host_ops, msic); 395 + /* We rely on being able to stash a virq in a u16, so limit irqs to < 65536 */ 396 + msic->irq_domain = irq_domain_add_nomap(dn, 65536, &msic_host_ops, msic); 393 397 if (!msic->irq_domain) { 394 398 printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n", 395 399 dn->full_name);
+1 -1
arch/powerpc/platforms/cell/beat_interrupt.c
··· 248 248 { 249 249 int i; 250 250 251 - for (i = 1; i < NR_IRQS; i++) 251 + for (i = 1; i < nr_irqs; i++) 252 252 beat_destruct_irq_plug(i); 253 253 }
+3 -3
arch/powerpc/platforms/powermac/pic.c
··· 57 57 58 58 static DEFINE_RAW_SPINLOCK(pmac_pic_lock); 59 59 60 - #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 61 - static unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; 62 - static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; 60 + /* The max irq number this driver deals with is 128; see max_irqs */ 61 + static DECLARE_BITMAP(ppc_lost_interrupts, 128); 62 + static DECLARE_BITMAP(ppc_cached_irq_mask, 128); 63 63 static int pmac_irq_cascade = -1; 64 64 static struct irq_domain *pmac_pic_host; 65 65
+1 -2
arch/powerpc/sysdev/cpm2_pic.c
··· 51 51 static intctl_cpm2_t __iomem *cpm2_intctl; 52 52 53 53 static struct irq_domain *cpm2_pic_host; 54 - #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) 55 - static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; 54 + static unsigned long ppc_cached_irq_mask[2]; /* 2 32-bit registers */ 56 55 57 56 static const u_char irq_to_siureg[] = { 58 57 1, 1, 1, 1, 1, 1, 1, 1,
+3 -4
arch/powerpc/sysdev/xics/xics-common.c
··· 188 188 { 189 189 int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id(); 190 190 unsigned int irq, virq; 191 + struct irq_desc *desc; 191 192 192 193 /* If we used to be the default server, move to the new "boot_cpuid" */ 193 194 if (hw_cpu == xics_default_server) ··· 203 202 /* Allow IPIs again... */ 204 203 icp_ops->set_priority(DEFAULT_PRIORITY); 205 204 206 - for_each_irq(virq) { 207 - struct irq_desc *desc; 205 + for_each_irq_desc(virq, desc) { 208 206 struct irq_chip *chip; 209 207 long server; 210 208 unsigned long flags; ··· 212 212 /* We can't set affinity on ISA interrupts */ 213 213 if (virq < NUM_ISA_INTERRUPTS) 214 214 continue; 215 - desc = irq_to_desc(virq); 216 215 /* We only need to migrate enabled IRQS */ 217 - if (!desc || !desc->action) 216 + if (!desc->action) 218 217 continue; 219 218 if (desc->irq_data.domain != xics_host) 220 219 continue;