Skip to content

Commit

Permalink
powerpc: iSeries has only 256 IRQs
Browse files Browse the repository at this point in the history
The iSeries Hypervisor only allows us to specify IRQ numbers up to 255 (it
has a u8 field to pass it in).  This patch allows platforms to specify a
maximum to the virtual IRQ numbers we will use and has iSeries set that
to 255.  If not set, the maximum is NR_IRQS - 1 (as before).

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
  • Loading branch information
Stephen Rothwell committed Apr 4, 2006
1 parent 6246b61 commit 7d01c88
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 14 deletions.
36 changes: 22 additions & 14 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,18 +272,26 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
* Don't use virtual irqs 0, 1, 2 for devices.
* The pcnet32 driver considers interrupt numbers < 2 to be invalid,
* and 2 is the XICS IPI interrupt.
* We limit virtual irqs to 17 less than NR_IRQS so that when we
* offset them by 16 (to reserve the first 16 for ISA interrupts)
* we don't end up with an interrupt number >= NR_IRQS.
* We limit virtual irqs to __irq_offet_value less than virt_irq_max so
* that when we offset them we don't end up with an interrupt
* number >= virt_irq_max.
*/
#define MIN_VIRT_IRQ 3
#define MAX_VIRT_IRQ (NR_IRQS - NUM_ISA_INTERRUPTS - 1)
#define NR_VIRT_IRQS (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)

unsigned int virt_irq_max;
static unsigned int max_virt_irq;
static unsigned int nr_virt_irqs;

void
virt_irq_init(void)
{
int i;

if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1)))
virt_irq_max = NR_IRQS - 1;
max_virt_irq = virt_irq_max - __irq_offset_value;
nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1;

for (i = 0; i < NR_IRQS; i++)
virt_irq_to_real_map[i] = UNDEFINED_IRQ;
}
Expand All @@ -308,17 +316,17 @@ int virt_irq_create_mapping(unsigned int real_irq)
return real_irq;
}

/* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */
/* map to a number between MIN_VIRT_IRQ and max_virt_irq */
virq = real_irq;
if (virq > MAX_VIRT_IRQ)
virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
if (virq > max_virt_irq)
virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;

/* search for this number or a free slot */
first_virq = virq;
while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
if (virt_irq_to_real_map[virq] == real_irq)
return virq;
if (++virq > MAX_VIRT_IRQ)
if (++virq > max_virt_irq)
virq = MIN_VIRT_IRQ;
if (virq == first_virq)
goto nospace; /* oops, no free slots */
Expand All @@ -330,8 +338,8 @@ int virt_irq_create_mapping(unsigned int real_irq)
nospace:
if (!warned) {
printk(KERN_CRIT "Interrupt table is full\n");
printk(KERN_CRIT "Increase NR_IRQS (currently %d) "
"in your kernel sources and rebuild.\n", NR_IRQS);
printk(KERN_CRIT "Increase virt_irq_max (currently %d) "
"in your kernel sources and rebuild.\n", virt_irq_max);
warned = 1;
}
return NO_IRQ;
Expand All @@ -349,8 +357,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)

virq = real_irq;

if (virq > MAX_VIRT_IRQ)
virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
if (virq > max_virt_irq)
virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;

first_virq = virq;

Expand All @@ -360,7 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)

virq++;

if (virq >= MAX_VIRT_IRQ)
if (virq >= max_virt_irq)
virq = 0;

} while (first_virq != virq);
Expand Down
7 changes: 7 additions & 0 deletions arch/powerpc/platforms/iseries/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <asm/iseries/hv_lp_event.h>
#include <asm/iseries/lpar_map.h>
#include <asm/udbg.h>
#include <asm/irq.h>

#include "naca.h"
#include "setup.h"
Expand Down Expand Up @@ -684,6 +685,12 @@ static int __init iseries_probe(void)
powerpc_firmware_features |= FW_FEATURE_ISERIES;
powerpc_firmware_features |= FW_FEATURE_LPAR;

/*
* The Hypervisor only allows us up to 256 interrupt
* sources (the irq number is passed in a u8).
*/
virt_irq_max = 255;

return 1;
}

Expand Down
7 changes: 7 additions & 0 deletions include/asm-powerpc/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
*/
extern unsigned int virt_irq_to_real_map[NR_IRQS];

/* The maximum virtual IRQ number that we support. This
* can be set by the platform and will be reduced by the
* value of __irq_offset_value. It defaults to and is
* capped by (NR_IRQS - 1).
*/
extern unsigned int virt_irq_max;

/* Create a mapping for a real_irq if it doesn't already exist.
* Return the virtual irq as a convenience.
*/
Expand Down

0 comments on commit 7d01c88

Please sign in to comment.