diff options
Diffstat (limited to 'arch/powerpc/kernel/irq.c')
| -rw-r--r-- | arch/powerpc/kernel/irq.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index bb5c9501234c..57d560c68897 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -272,18 +272,26 @@ unsigned int virt_irq_to_real_map[NR_IRQS]; | |||
| 272 | * Don't use virtual irqs 0, 1, 2 for devices. | 272 | * Don't use virtual irqs 0, 1, 2 for devices. |
| 273 | * The pcnet32 driver considers interrupt numbers < 2 to be invalid, | 273 | * The pcnet32 driver considers interrupt numbers < 2 to be invalid, |
| 274 | * and 2 is the XICS IPI interrupt. | 274 | * and 2 is the XICS IPI interrupt. |
| 275 | * We limit virtual irqs to 17 less than NR_IRQS so that when we | 275 | * We limit virtual irqs to __irq_offet_value less than virt_irq_max so |
| 276 | * offset them by 16 (to reserve the first 16 for ISA interrupts) | 276 | * that when we offset them we don't end up with an interrupt |
| 277 | * we don't end up with an interrupt number >= NR_IRQS. | 277 | * number >= virt_irq_max. |
| 278 | */ | 278 | */ |
| 279 | #define MIN_VIRT_IRQ 3 | 279 | #define MIN_VIRT_IRQ 3 |
| 280 | #define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1) | 280 | |
| 281 | #define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1) | 281 | unsigned int virt_irq_max; |
| 282 | static unsigned int max_virt_irq; | ||
| 283 | static unsigned int nr_virt_irqs; | ||
| 282 | 284 | ||
| 283 | void | 285 | void |
| 284 | virt_irq_init(void) | 286 | virt_irq_init(void) |
| 285 | { | 287 | { |
| 286 | int i; | 288 | int i; |
| 289 | |||
| 290 | if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1))) | ||
| 291 | virt_irq_max = NR_IRQS - 1; | ||
| 292 | max_virt_irq = virt_irq_max - __irq_offset_value; | ||
| 293 | nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1; | ||
| 294 | |||
| 287 | for (i = 0; i < NR_IRQS; i++) | 295 | for (i = 0; i < NR_IRQS; i++) |
| 288 | virt_irq_to_real_map[i] = UNDEFINED_IRQ; | 296 | virt_irq_to_real_map[i] = UNDEFINED_IRQ; |
| 289 | } | 297 | } |
| @@ -308,17 +316,17 @@ int virt_irq_create_mapping(unsigned int real_irq) | |||
| 308 | return real_irq; | 316 | return real_irq; |
| 309 | } | 317 | } |
| 310 | 318 | ||
| 311 | /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */ | 319 | /* map to a number between MIN_VIRT_IRQ and max_virt_irq */ |
| 312 | virq = real_irq; | 320 | virq = real_irq; |
| 313 | if (virq > MAX_VIRT_IRQ) | 321 | if (virq > max_virt_irq) |
| 314 | virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; | 322 | virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ; |
| 315 | 323 | ||
| 316 | /* search for this number or a free slot */ | 324 | /* search for this number or a free slot */ |
| 317 | first_virq = virq; | 325 | first_virq = virq; |
| 318 | while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { | 326 | while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { |
| 319 | if (virt_irq_to_real_map[virq] == real_irq) | 327 | if (virt_irq_to_real_map[virq] == real_irq) |
| 320 | return virq; | 328 | return virq; |
| 321 | if (++virq > MAX_VIRT_IRQ) | 329 | if (++virq > max_virt_irq) |
| 322 | virq = MIN_VIRT_IRQ; | 330 | virq = MIN_VIRT_IRQ; |
| 323 | if (virq == first_virq) | 331 | if (virq == first_virq) |
| 324 | goto nospace; /* oops, no free slots */ | 332 | goto nospace; /* oops, no free slots */ |
| @@ -330,8 +338,8 @@ int virt_irq_create_mapping(unsigned int real_irq) | |||
| 330 | nospace: | 338 | nospace: |
| 331 | if (!warned) { | 339 | if (!warned) { |
| 332 | printk(KERN_CRIT "Interrupt table is full\n"); | 340 | printk(KERN_CRIT "Interrupt table is full\n"); |
| 333 | printk(KERN_CRIT "Increase NR_IRQS (currently %d) " | 341 | printk(KERN_CRIT "Increase virt_irq_max (currently %d) " |
| 334 | "in your kernel sources and rebuild.\n", NR_IRQS); | 342 | "in your kernel sources and rebuild.\n", virt_irq_max); |
| 335 | warned = 1; | 343 | warned = 1; |
| 336 | } | 344 | } |
| 337 | return NO_IRQ; | 345 | return NO_IRQ; |
| @@ -349,8 +357,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
| 349 | 357 | ||
| 350 | virq = real_irq; | 358 | virq = real_irq; |
| 351 | 359 | ||
| 352 | if (virq > MAX_VIRT_IRQ) | 360 | if (virq > max_virt_irq) |
| 353 | virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ; | 361 | virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ; |
| 354 | 362 | ||
| 355 | first_virq = virq; | 363 | first_virq = virq; |
| 356 | 364 | ||
| @@ -360,7 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
| 360 | 368 | ||
| 361 | virq++; | 369 | virq++; |
| 362 | 370 | ||
| 363 | if (virq >= MAX_VIRT_IRQ) | 371 | if (virq >= max_virt_irq) |
| 364 | virq = 0; | 372 | virq = 0; |
| 365 | 373 | ||
| 366 | } while (first_virq != virq); | 374 | } while (first_virq != virq); |
