Commit e3c82ec8 authored by Jason Davis's avatar Jason Davis Committed by Linus Torvalds

[PATCH] ES7000 subarch update

The patch below implements an algorithm to determine an unique GSI override
for mapping GSIs to IO-APIC pins correctly.  GSI overrides are required in
order for ES7000 machines to function properly since IRQ to pin mappings
are NOT all one-to-one.  This patch applies only to the Unisys specific
ES7000 machines and has been tested thoroughly on several models of the
ES7000 line.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6d7e9764
...@@ -104,6 +104,13 @@ struct mip_reg { ...@@ -104,6 +104,13 @@ struct mip_reg {
#define MIP_SW_APIC 0x1020b #define MIP_SW_APIC 0x1020b
#define MIP_FUNC(VALUE) (VALUE & 0xff) #define MIP_FUNC(VALUE) (VALUE & 0xff)
#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
#define IOAPIC_GSI_BOUND(ioapic) ((ioapic+1) * (nr_ioapic_registers[ioapic]-1))
#define MAX_GSI_MAPSIZE 32
#endif
extern unsigned long io_apic_irqs;
extern int parse_unisys_oem (char *oemptr, int oem_entries); extern int parse_unisys_oem (char *oemptr, int oem_entries);
extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length); extern int find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length);
extern int es7000_start_cpu(int cpu, unsigned long eip); extern int es7000_start_cpu(int cpu, unsigned long eip);
......
...@@ -51,27 +51,74 @@ struct mip_reg *host_reg; ...@@ -51,27 +51,74 @@ struct mip_reg *host_reg;
int mip_port; int mip_port;
unsigned long mip_addr, host_addr; unsigned long mip_addr, host_addr;
#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_ACPI_INTERPRETER) || defined(CONFIG_ACPI_BOOT))
static unsigned long cycle_irqs = 0;
static unsigned long free_irqs = 0;
static int gsi_map[MAX_GSI_MAPSIZE] = { [0 ... MAX_GSI_MAPSIZE-1] = -1 };
/*
* GSI override for ES7000 platforms.
*/
static int __init
es7000_gsi_override(int ioapic, int gsi)
{
static int newgsi = 0;
if (gsi_map[gsi] != -1)
gsi = gsi_map[gsi];
else if (cycle_irqs ^ free_irqs) {
newgsi = find_next_bit(&cycle_irqs, IOAPIC_GSI_BOUND(0), newgsi);
__set_bit(newgsi, &free_irqs);
gsi_map[gsi] = newgsi;
gsi = newgsi;
newgsi++;
Dprintk("es7000_gsi_override: free_irqs = 0x%lx\n", free_irqs);
}
return gsi;
}
static int __init static int __init
es7000_rename_gsi(int ioapic, int gsi) es7000_rename_gsi(int ioapic, int gsi)
{ {
static int initialized = 0;
int i;
/*
* These should NEVER be true at this point but we'd rather be
* safe than sorry.
*/
if (acpi_disabled || acpi_pci_disabled || acpi_noirq)
return gsi;
if (ioapic) if (ioapic)
return gsi; return gsi;
else {
if (gsi == 0) if (!initialized) {
return 13; unsigned long tmp_irqs = 0;
if (gsi == 1)
return 16; for (i = 0; i < nr_ioapic_registers[0]; i++)
if (gsi == 4) __set_bit(mp_irqs[i].mpc_srcbusirq, &tmp_irqs);
return 17;
if (gsi == 6) cycle_irqs = (~tmp_irqs & io_apic_irqs & ((1 << IOAPIC_GSI_BOUND(0)) - 1));
return 18;
if (gsi == 7) initialized = 1;
return 19; Dprintk("es7000_rename_gsi: cycle_irqs = 0x%lx\n", cycle_irqs);
if (gsi == 8) }
return 20;
for (i = 0; i < nr_ioapic_registers[0]; i++) {
if (mp_irqs[i].mpc_srcbusirq == gsi) {
if (mp_irqs[i].mpc_dstirq == gsi)
return gsi; return gsi;
else
return es7000_gsi_override(0, gsi);
} }
}
return gsi;
} }
#endif // (CONFIG_X86_IO_APIC) && (CONFIG_ACPI_INTERPRETER || CONFIG_ACPI_BOOT)
/* /*
* Parse the OEM Table * Parse the OEM Table
...@@ -193,7 +240,7 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length) ...@@ -193,7 +240,7 @@ find_unisys_acpi_oem_table(unsigned long *oem_addr, int *length)
} }
} }
} }
printk("ES7000: did not find Unisys ACPI OEM table!\n"); Dprintk("ES7000: did not find Unisys ACPI OEM table!\n");
return -1; return -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment