Commit 9caf366e authored by Linus Torvalds's avatar Linus Torvalds

Merge http://lia64.bkbits.net/to-linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 7c0700ff 7d3b6870
...@@ -96,7 +96,8 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot ...@@ -96,7 +96,8 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
vmlinux: arch/$(ARCH)/vmlinux.lds.s vmlinux: arch/$(ARCH)/vmlinux.lds.s
CPPFLAGS_arch/ia64/vmlinux.lds.s := -traditional arch/$(ARCH)/vmlinux.lds.s: arch/$(ARCH)/vmlinux.lds.S
$(CPP) $(CPPFLAGS) $(CPPFLAGS_$@) -D__ASSEMBLY__ -P -C -U$(ARCH) $< -o $@
compressed: vmlinux compressed: vmlinux
$(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux-tmp $(OBJCOPY) $(OBJCOPYFLAGS) vmlinux vmlinux-tmp
......
...@@ -30,11 +30,11 @@ ...@@ -30,11 +30,11 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/efi.h>
#include <asm/delay.h> /* ia64_get_itc() */ #include <asm/delay.h> /* ia64_get_itc() */
#include <asm/io.h> #include <asm/io.h>
#include <asm/page.h> /* PAGE_OFFSET */ #include <asm/page.h> /* PAGE_OFFSET */
#include <asm/efi.h>
#define DRIVER_NAME "SBA" #define DRIVER_NAME "SBA"
......
...@@ -213,7 +213,7 @@ simeth_probe1(void) ...@@ -213,7 +213,7 @@ simeth_probe1(void)
memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr)); memcpy(dev->dev_addr, mac_addr, sizeof(mac_addr));
dev->irq = ia64_alloc_irq(); dev->irq = ia64_alloc_vector();
/* /*
* attach the interrupt in the simulator, this does enable interrupts * attach the interrupt in the simulator, this does enable interrupts
......
...@@ -1076,7 +1076,7 @@ simrs_init (void) ...@@ -1076,7 +1076,7 @@ simrs_init (void)
if (state->type == PORT_UNKNOWN) continue; if (state->type == PORT_UNKNOWN) continue;
if (!state->irq) { if (!state->irq) {
state->irq = ia64_alloc_irq(); state->irq = ia64_alloc_vector();
ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq); ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
} }
......
...@@ -12,9 +12,9 @@ ...@@ -12,9 +12,9 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/efi.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/efi.h>
#include <asm/iosapic.h> #include <asm/iosapic.h>
extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *, extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, acpi_object_list *,
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <linux/nfsd/syscall.h> #include <linux/nfsd/syscall.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/ipc.h> #include <linux/ipc.h>
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <asm/efi.h> #include <linux/efi.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/iosapic.h> #include <asm/iosapic.h>
#include <asm/machvec.h> #include <asm/machvec.h>
...@@ -47,9 +47,9 @@ ...@@ -47,9 +47,9 @@
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
asm (".weak iosapic_register_irq"); asm (".weak iosapic_register_intr");
asm (".weak iosapic_register_legacy_irq"); asm (".weak iosapic_override_isa_irq");
asm (".weak iosapic_register_platform_irq"); asm (".weak iosapic_register_platform_intr");
asm (".weak iosapic_init"); asm (".weak iosapic_init");
asm (".weak iosapic_version"); asm (".weak iosapic_version");
...@@ -173,10 +173,10 @@ acpi_dispose_crs (acpi_buffer *buf) ...@@ -173,10 +173,10 @@ acpi_dispose_crs (acpi_buffer *buf)
#ifdef CONFIG_ACPI_BOOT #ifdef CONFIG_ACPI_BOOT
#define ACPI_MAX_PLATFORM_IRQS 256 #define ACPI_MAX_PLATFORM_INTERRUPTS 256
/* Array to record platform interrupt vectors for generic interrupt routing. */ /* Array to record platform interrupt vectors for generic interrupt routing. */
int platform_irq_list[ACPI_MAX_PLATFORM_IRQS] = { [0 ... ACPI_MAX_PLATFORM_IRQS - 1] = -1 }; int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC; enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
...@@ -189,9 +189,9 @@ acpi_request_vector (u32 int_type) ...@@ -189,9 +189,9 @@ acpi_request_vector (u32 int_type)
{ {
int vector = -1; int vector = -1;
if (int_type < ACPI_MAX_PLATFORM_IRQS) { if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) {
/* correctable platform error interrupt */ /* correctable platform error interrupt */
vector = platform_irq_list[int_type]; vector = platform_intr_list[int_type];
} else } else
printk("acpi_request_vector(): invalid interrupt type\n"); printk("acpi_request_vector(): invalid interrupt type\n");
return vector; return vector;
...@@ -210,6 +210,7 @@ __acpi_map_table (unsigned long phys_addr, unsigned long size) ...@@ -210,6 +210,7 @@ __acpi_map_table (unsigned long phys_addr, unsigned long size)
static int total_cpus __initdata; static int total_cpus __initdata;
static int available_cpus __initdata; static int available_cpus __initdata;
struct acpi_table_madt * acpi_madt __initdata; struct acpi_table_madt * acpi_madt __initdata;
static u8 has_8259;
static int __init static int __init
...@@ -284,7 +285,7 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header) ...@@ -284,7 +285,7 @@ acpi_parse_lapic_nmi (acpi_table_entry_header *header)
static int __init static int __init
acpi_find_iosapic (int global_vector, u32 *irq_base, char **iosapic_address) acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address)
{ {
struct acpi_table_iosapic *iosapic; struct acpi_table_iosapic *iosapic;
int ver; int ver;
...@@ -292,7 +293,7 @@ acpi_find_iosapic (int global_vector, u32 *irq_base, char **iosapic_address) ...@@ -292,7 +293,7 @@ acpi_find_iosapic (int global_vector, u32 *irq_base, char **iosapic_address)
char *p; char *p;
char *end; char *end;
if (!irq_base || !iosapic_address) if (!gsi_base || !iosapic_address)
return -ENODEV; return -ENODEV;
p = (char *) (acpi_madt + 1); p = (char *) (acpi_madt + 1);
...@@ -302,13 +303,13 @@ acpi_find_iosapic (int global_vector, u32 *irq_base, char **iosapic_address) ...@@ -302,13 +303,13 @@ acpi_find_iosapic (int global_vector, u32 *irq_base, char **iosapic_address)
if (*p == ACPI_MADT_IOSAPIC) { if (*p == ACPI_MADT_IOSAPIC) {
iosapic = (struct acpi_table_iosapic *) p; iosapic = (struct acpi_table_iosapic *) p;
*irq_base = iosapic->global_irq_base; *gsi_base = iosapic->global_irq_base;
*iosapic_address = ioremap(iosapic->address, 0); *iosapic_address = ioremap(iosapic->address, 0);
ver = iosapic_version(*iosapic_address); ver = iosapic_version(*iosapic_address);
max_pin = (ver >> 16) & 0xff; max_pin = (ver >> 16) & 0xff;
if ((global_vector - *irq_base) <= max_pin) if ((gsi - *gsi_base) <= max_pin)
return 0; /* Found it! */ return 0; /* Found it! */
} }
p += p[1]; p += p[1];
...@@ -347,7 +348,7 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header) ...@@ -347,7 +348,7 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
{ {
struct acpi_table_plat_int_src *plintsrc; struct acpi_table_plat_int_src *plintsrc;
int vector; int vector;
u32 irq_base; u32 gsi_base;
char *iosapic_address; char *iosapic_address;
plintsrc = (struct acpi_table_plat_int_src *) header; plintsrc = (struct acpi_table_plat_int_src *) header;
...@@ -356,31 +357,31 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header) ...@@ -356,31 +357,31 @@ acpi_parse_plat_int_src (acpi_table_entry_header *header)
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
if (!iosapic_register_platform_irq) { if (!iosapic_register_platform_intr) {
printk(KERN_WARNING PREFIX "No ACPI platform IRQ support\n"); printk(KERN_WARNING PREFIX "No ACPI platform interrupt support\n");
return -ENODEV; return -ENODEV;
} }
if (acpi_find_iosapic(plintsrc->global_irq, &irq_base, &iosapic_address)) { if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) {
printk(KERN_WARNING PREFIX "IOSAPIC not found\n"); printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
return -ENODEV; return -ENODEV;
} }
/* /*
* Get vector assignment for this IRQ, set attributes, and program the * Get vector assignment for this interrupt, set attributes,
* IOSAPIC routing table. * and program the IOSAPIC routing table.
*/ */
vector = iosapic_register_platform_irq(plintsrc->type, vector = iosapic_register_platform_intr(plintsrc->type,
plintsrc->global_irq, plintsrc->global_irq,
plintsrc->iosapic_vector, plintsrc->iosapic_vector,
plintsrc->eid, plintsrc->eid,
plintsrc->id, plintsrc->id,
(plintsrc->flags.polarity == 1) ? 1 : 0, (plintsrc->flags.polarity == 1) ? 1 : 0,
(plintsrc->flags.trigger == 1) ? 1 : 0, (plintsrc->flags.trigger == 1) ? 1 : 0,
irq_base, gsi_base,
iosapic_address); iosapic_address);
platform_irq_list[plintsrc->type] = vector; platform_intr_list[plintsrc->type] = vector;
return 0; return 0;
} }
...@@ -397,12 +398,12 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header) ...@@ -397,12 +398,12 @@ acpi_parse_int_src_ovr (acpi_table_entry_header *header)
acpi_table_print_madt_entry(header); acpi_table_print_madt_entry(header);
/* Ignore if the platform doesn't support overrides */ /* Ignore if the platform doesn't support overrides */
if (!iosapic_register_legacy_irq) if (!iosapic_override_isa_irq)
return 0; return 0;
iosapic_register_legacy_irq(p->bus_irq, p->global_irq, iosapic_override_isa_irq(p->bus_irq, p->global_irq,
(p->flags.polarity == 1) ? 1 : 0, (p->flags.polarity == 1) ? 1 : 0,
(p->flags.trigger == 1) ? 1 : 0); (p->flags.trigger == 1) ? 1 : 0);
return 0; return 0;
} }
...@@ -431,6 +432,9 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size) ...@@ -431,6 +432,9 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
acpi_madt = (struct acpi_table_madt *) __va(phys_addr); acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
/* remember the value for reference after free_initmem() */
has_8259 = acpi_madt->flags.pcat_compat;
/* Get base address of IPI Message Block */ /* Get base address of IPI Message Block */
if (acpi_madt->lapic_address) if (acpi_madt->lapic_address)
...@@ -440,11 +444,14 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size) ...@@ -440,11 +444,14 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
return 0; return 0;
} }
static int __init static int __init
acpi_parse_fadt (unsigned long phys_addr, unsigned long size) acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
{ {
struct acpi_table_header *fadt_header; struct acpi_table_header *fadt_header;
fadt_descriptor_rev2 *fadt; fadt_descriptor_rev2 *fadt;
u32 sci_irq, gsi_base;
char *iosapic_address;
if (!phys_addr || !size) if (!phys_addr || !size)
return -EINVAL; return -EINVAL;
...@@ -458,9 +465,20 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size) ...@@ -458,9 +465,20 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER)) if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
acpi_kbd_controller_present = 0; acpi_kbd_controller_present = 0;
if (!iosapic_register_intr)
return 0; /* just ignore the rest */
sci_irq = fadt->sci_int;
if (has_8259 && sci_irq < 16)
return 0; /* legacy, no setup required */
if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address))
iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address);
return 0; return 0;
} }
unsigned long __init unsigned long __init
acpi_find_rsdp (void) acpi_find_rsdp (void)
{ {
...@@ -482,12 +500,12 @@ static int __init ...@@ -482,12 +500,12 @@ static int __init
acpi_parse_spcr (unsigned long phys_addr, unsigned long size) acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
{ {
acpi_ser_t *spcr; acpi_ser_t *spcr;
unsigned long global_int; unsigned int gsi;
if (!phys_addr || !size) if (!phys_addr || !size)
return -EINVAL; return -EINVAL;
if (!iosapic_register_irq) if (!iosapic_register_intr)
return -ENODEV; return -ENODEV;
/* /*
...@@ -500,6 +518,7 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size) ...@@ -500,6 +518,7 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
*/ */
spcr = (acpi_ser_t *) __va(phys_addr); spcr = (acpi_ser_t *) __va(phys_addr);
setup_serial_acpi(spcr); setup_serial_acpi(spcr);
if (spcr->length < sizeof(acpi_ser_t)) if (spcr->length < sizeof(acpi_ser_t))
...@@ -509,22 +528,22 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size) ...@@ -509,22 +528,22 @@ acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) && if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
(spcr->int_type == ACPI_SERIAL_INT_SAPIC)) (spcr->int_type == ACPI_SERIAL_INT_SAPIC))
{ {
u32 irq_base; u32 gsi_base;
char *iosapic_address; char *iosapic_address;
int vector; int vector;
/* We have a UART in memory space with an SAPIC interrupt */ /* We have a UART in memory space with an SAPIC interrupt */
global_int = ((spcr->global_int[3] << 24) | gsi = ( (spcr->global_int[3] << 24) |
(spcr->global_int[2] << 16) | (spcr->global_int[2] << 16) |
(spcr->global_int[1] << 8) | (spcr->global_int[1] << 8) |
(spcr->global_int[0]) ); (spcr->global_int[0]) );
/* Which iosapic does this IRQ belong to? */ /* Which iosapic does this interrupt belong to? */
if (!acpi_find_iosapic(global_int, &irq_base, &iosapic_address)) if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
vector = iosapic_register_irq(global_int, 1, 1, vector = iosapic_register_intr(gsi, 1, 1,
irq_base, iosapic_address); gsi_base, iosapic_address);
} }
return 0; return 0;
} }
...@@ -583,7 +602,12 @@ acpi_boot_init (char *cmdline) ...@@ -583,7 +602,12 @@ acpi_boot_init (char *cmdline)
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
skip_madt: skip_madt:
/* FADT says whether a legacy keyboard controller is present. */ /*
* FADT says whether a legacy keyboard controller is present.
* The FADT also contains an SCI_INT line, by which the system
* gets interrupts such as power and sleep buttons. If it's not
* on a Legacy interrupt, it needs to be setup.
*/
if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1) if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1)
printk(KERN_ERR PREFIX "Can't find FADT\n"); printk(KERN_ERR PREFIX "Can't find FADT\n");
...@@ -631,7 +655,7 @@ acpi_get_prt (struct pci_vector_struct **vectors, int *count) ...@@ -631,7 +655,7 @@ acpi_get_prt (struct pci_vector_struct **vectors, int *count)
*count = 0; *count = 0;
if (acpi_prt.count < 0) { if (acpi_prt.count < 0) {
printk(KERN_ERR PREFIX "No PCI IRQ routing entries\n"); printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n");
return -ENODEV; return -ENODEV;
} }
...@@ -669,4 +693,13 @@ acpi_get_interrupt_model (int *type) ...@@ -669,4 +693,13 @@ acpi_get_interrupt_model (int *type)
return 0; return 0;
} }
int
acpi_irq_to_vector (u32 irq)
{
if (has_8259 && irq < 16)
return isa_irq_to_vector(irq);
return gsi_to_vector(irq);
}
#endif /* CONFIG_ACPI_BOOT */ #endif /* CONFIG_ACPI_BOOT */
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/efi.h>
#include <asm/efi.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/kregs.h> #include <asm/kregs.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
......
...@@ -65,8 +65,8 @@ ...@@ -65,8 +65,8 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/efi.h>
#include <asm/efi.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>");
......
...@@ -1229,11 +1229,11 @@ sys_call_table: ...@@ -1229,11 +1229,11 @@ sys_call_table:
data8 ia64_ni_syscall // 1235 data8 ia64_ni_syscall // 1235
data8 ia64_ni_syscall data8 ia64_ni_syscall
data8 ia64_ni_syscall data8 ia64_ni_syscall
data8 ia64_ni_syscall data8 sys_io_setup
data8 ia64_ni_syscall data8 sys_io_destroy
data8 ia64_ni_syscall // 1240 data8 sys_io_getevents // 1240
data8 ia64_ni_syscall data8 sys_io_submit
data8 ia64_ni_syscall data8 sys_io_cancel
data8 ia64_ni_syscall data8 ia64_ni_syscall
data8 ia64_ni_syscall data8 ia64_ni_syscall
data8 ia64_ni_syscall // 1245 data8 ia64_ni_syscall // 1245
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
# include <linux/pci.h> # include <linux/pci.h>
#endif #endif
#include <asm/efi.h> #include <linux/efi.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/pal.h> #include <asm/pal.h>
#include <asm/sal.h> #include <asm/sal.h>
......
...@@ -58,7 +58,7 @@ EXPORT_SYMBOL(clear_page); ...@@ -58,7 +58,7 @@ EXPORT_SYMBOL(clear_page);
#include <asm/processor.h> #include <asm/processor.h>
# ifndef CONFIG_NUMA # ifndef CONFIG_NUMA
EXPORT_SYMBOL(cpu_info); EXPORT_SYMBOL(cpu_info__per_cpu);
# endif # endif
EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(kernel_thread);
......
...@@ -26,9 +26,12 @@ ...@@ -26,9 +26,12 @@
* 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq * 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq
* 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping
* error * error
* 02/07/29 T. Kochi Allocate interrupt vectors dynamically
* 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector,
* etc.)
*/ */
/* /*
* Here is what the interrupt logic between a PCI device and the CPU looks like: * Here is what the interrupt logic between a PCI device and the kernel looks like:
* *
* (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The
* device is uniquely identified by its bus--, and slot-number (the function * device is uniquely identified by its bus--, and slot-number (the function
...@@ -37,19 +40,28 @@ ...@@ -37,19 +40,28 @@
* *
* (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller. * (2) The motherboard routes the interrupt line to a pin on a IOSAPIC controller.
* Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level * Multiple interrupt lines may have to share the same IOSAPIC pin (if they're level
* triggered and use the same polarity). Each interrupt line has a unique IOSAPIC * triggered and use the same polarity). Each interrupt line has a unique Global
* irq number which can be calculated as the sum of the controller's base irq number * System Interrupt (GSI) number which can be calculated as the sum of the controller's
* and the IOSAPIC pin number to which the line connects. * base GSI number and the IOSAPIC pin number to which the line connects.
* *
* (3) The IOSAPIC uses an internal table to map the IOSAPIC pin into the IA-64 interrupt * (3) The IOSAPIC uses an internal routing table entries (RTEs) to map the IOSAPIC pin
* vector. This interrupt vector is then sent to the CPU. * into the IA-64 interrupt vector. This interrupt vector is then sent to the CPU.
* *
* In other words, there are two levels of indirections involved: * (4) The kernel recognizes an interrupt as an IRQ. The IRQ interface is used as
* architecture-independent interrupt handling mechanism in Linux. As an
* IRQ is a number, we have to have IA-64 interrupt vector number <-> IRQ number
* mapping. On smaller systems, we use one-to-one mapping between IA-64 vector and
* IRQ. A platform can implemnent platform_irq_to_vector(irq) and
* platform_local_vector_to_irq(vector) APIs to differentiate the mapping.
* Please see also include/asm-ia64/hw_irq.h for those APIs.
* *
* pci pin -> iosapic irq -> IA-64 vector * To sum up, there are three levels of mappings involved:
* *
* Note: outside this module, IA-64 vectors are called "irqs". This is because that's * PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
* the traditional name Linux uses for interrupt vectors. *
* Note: The term "IRQ" is loosely used everywhere in Linux kernel to describe interrupts.
* Now we use "IRQ" only for Linux IRQ's. ISA IRQ (isa_irq) is the only exception in this
* source code.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -72,49 +84,55 @@ ...@@ -72,49 +84,55 @@
#include <asm/system.h> #include <asm/system.h>
#undef DEBUG_IRQ_ROUTING #undef DEBUG_INTERRUPT_ROUTING
#undef OVERRIDE_DEBUG #undef OVERRIDE_DEBUG
#ifdef DEBUG_INTERRUPT_ROUTING
#define DBG(fmt...) printk(fmt)
#else
#define DBG(fmt...)
#endif
static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
/* PCI pin to IOSAPIC irq routing information. This info typically comes from ACPI. */ /* PCI pin to GSI routing information. This info typically comes from ACPI. */
static struct { static struct {
int num_routes; int num_routes;
struct pci_vector_struct *route; struct pci_vector_struct *route;
} pci_irq; } pci_irq;
/* This tables maps IA-64 vectors to the IOSAPIC pin that generates this vector. */ /* These tables map IA-64 vectors to the IOSAPIC pin that generates this vector. */
static struct iosapic_irq { static struct iosapic_intr_info {
char *addr; /* base address of IOSAPIC */ char *addr; /* base address of IOSAPIC */
unsigned int base_irq; /* first irq assigned to this IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
char pin; /* IOSAPIC pin (-1 => not an IOSAPIC irq) */ char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
unsigned char polarity : 1; /* interrupt polarity (see iosapic.h) */ unsigned char polarity: 1; /* interrupt polarity (see iosapic.h) */
unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
} iosapic_irq[IA64_NUM_VECTORS]; } iosapic_intr_info[IA64_NUM_VECTORS];
static struct iosapic { static struct iosapic {
char *addr; /* base address of IOSAPIC */ char *addr; /* base address of IOSAPIC */
unsigned int base_irq; /* first irq assigned to this IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
unsigned short max_pin; /* max input pin supported in this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */
unsigned char pcat_compat; /* 8259 compatibility flag */ unsigned char pcat_compat; /* 8259 compatibility flag */
} iosapic_lists[256] __initdata; } iosapic_lists[256] __devinitdata;
static int num_iosapic = 0; static int num_iosapic = 0;
/* /*
* Find an IOSAPIC associated with an IRQ * Find an IOSAPIC associated with a GSI
*/ */
static inline int __init static inline int __devinit
find_iosapic (unsigned int irq) find_iosapic (unsigned int gsi)
{ {
int i; int i;
for (i = 0; i < num_iosapic; i++) { for (i = 0; i < num_iosapic; i++) {
if ((unsigned) (irq - iosapic_lists[i].base_irq) <= iosapic_lists[i].max_pin) if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
return i; return i;
} }
...@@ -122,60 +140,51 @@ find_iosapic (unsigned int irq) ...@@ -122,60 +140,51 @@ find_iosapic (unsigned int irq)
} }
/* /*
* Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector. If no * Translate GSI number to the corresponding IA-64 interrupt vector. If no
* entry exists, return -1. * entry exists, return -1.
*/ */
static int int
iosapic_irq_to_vector (int irq) gsi_to_vector (unsigned int gsi)
{ {
int vector; int vector;
for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
if (iosapic_irq[vector].base_irq + iosapic_irq[vector].pin == irq) if (iosapic_intr_info[vector].gsi_base + iosapic_intr_info[vector].rte_index == gsi)
return vector; return vector;
return -1; return -1;
} }
/*
* Map PCI pin to the corresponding IA-64 interrupt vector. If no such mapping exists,
* return -1.
*/
int
pci_pin_to_vector (int bus, int slot, int pci_pin)
{
struct pci_vector_struct *r;
for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r)
if (r->bus == bus && (r->pci_id >> 16) == slot && r->pin == pci_pin)
return iosapic_irq_to_vector(r->irq);
return -1;
}
static void static void
set_rte (unsigned int vector, unsigned long dest) set_rte (unsigned int vector, unsigned int dest)
{ {
unsigned long pol, trigger, dmode; unsigned long pol, trigger, dmode;
u32 low32, high32; u32 low32, high32;
char *addr; char *addr;
int pin; int rte_index;
char redir; char redir;
#ifdef DEBUG_IRQ_ROUTING DBG(KERN_DEBUG "%s: routing vector %d to %x\n", __FUNCTION__, vector, dest);
printk(KERN_DEBUG "set_rte: routing vector 0x%02x to 0x%lx\n", vector, dest);
#endif
pin = iosapic_irq[vector].pin; rte_index = iosapic_intr_info[vector].rte_index;
if (pin < 0) if (rte_index < 0)
return; /* not an IOSAPIC interrupt */ return; /* not an IOSAPIC interrupt */
addr = iosapic_irq[vector].addr; addr = iosapic_intr_info[vector].addr;
pol = iosapic_irq[vector].polarity; pol = iosapic_intr_info[vector].polarity;
trigger = iosapic_irq[vector].trigger; trigger = iosapic_intr_info[vector].trigger;
dmode = iosapic_irq[vector].dmode; dmode = iosapic_intr_info[vector].dmode;
redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0; redir = (dmode == IOSAPIC_LOWEST_PRIORITY) ? 1 : 0;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
set_irq_affinity_info(vector, (int)(dest & 0xffff), redir); {
unsigned int irq;
for (irq = 0; irq < NR_IRQS; ++irq)
if (irq_to_vector(irq) == vector) {
set_irq_affinity_info(irq, (int)(dest & 0xffff), redir);
break;
}
}
#endif #endif
low32 = ((pol << IOSAPIC_POLARITY_SHIFT) | low32 = ((pol << IOSAPIC_POLARITY_SHIFT) |
...@@ -186,9 +195,9 @@ set_rte (unsigned int vector, unsigned long dest) ...@@ -186,9 +195,9 @@ set_rte (unsigned int vector, unsigned long dest)
/* dest contains both id and eid */ /* dest contains both id and eid */
high32 = (dest << IOSAPIC_DEST_SHIFT); high32 = (dest << IOSAPIC_DEST_SHIFT);
writel(IOSAPIC_RTE_HIGH(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
writel(high32, addr + IOSAPIC_WINDOW); writel(high32, addr + IOSAPIC_WINDOW);
writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
writel(low32, addr + IOSAPIC_WINDOW); writel(low32, addr + IOSAPIC_WINDOW);
} }
...@@ -204,18 +213,18 @@ mask_irq (unsigned int irq) ...@@ -204,18 +213,18 @@ mask_irq (unsigned int irq)
unsigned long flags; unsigned long flags;
char *addr; char *addr;
u32 low32; u32 low32;
int pin; int rte_index;
ia64_vector vec = irq_to_vector(irq); ia64_vector vec = irq_to_vector(irq);
addr = iosapic_irq[vec].addr; addr = iosapic_intr_info[vec].addr;
pin = iosapic_irq[vec].pin; rte_index = iosapic_intr_info[vec].rte_index;
if (pin < 0) if (rte_index < 0)
return; /* not an IOSAPIC interrupt! */ return; /* not an IOSAPIC interrupt! */
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
{ {
writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
low32 = readl(addr + IOSAPIC_WINDOW); low32 = readl(addr + IOSAPIC_WINDOW);
low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */ low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */
...@@ -230,17 +239,17 @@ unmask_irq (unsigned int irq) ...@@ -230,17 +239,17 @@ unmask_irq (unsigned int irq)
unsigned long flags; unsigned long flags;
char *addr; char *addr;
u32 low32; u32 low32;
int pin; int rte_index;
ia64_vector vec = irq_to_vector(irq); ia64_vector vec = irq_to_vector(irq);
addr = iosapic_irq[vec].addr; addr = iosapic_intr_info[vec].addr;
pin = iosapic_irq[vec].pin; rte_index = iosapic_intr_info[vec].rte_index;
if (pin < 0) if (rte_index < 0)
return; /* not an IOSAPIC interrupt! */ return; /* not an IOSAPIC interrupt! */
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
{ {
writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
low32 = readl(addr + IOSAPIC_WINDOW); low32 = readl(addr + IOSAPIC_WINDOW);
low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */ low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */
...@@ -256,24 +265,28 @@ iosapic_set_affinity (unsigned int irq, unsigned long mask) ...@@ -256,24 +265,28 @@ iosapic_set_affinity (unsigned int irq, unsigned long mask)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
unsigned long flags; unsigned long flags;
u32 high32, low32; u32 high32, low32;
int dest, pin; int dest, rte_index;
char *addr; char *addr;
int redir = (irq & (1<<31)) ? 1 : 0; int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
ia64_vector vec;
irq &= (~IA64_IRQ_REDIRECTED);
vec = irq_to_vector(irq);
mask &= cpu_online_map; mask &= cpu_online_map;
if (!mask || irq >= IA64_NUM_VECTORS) if (!mask || vec >= IA64_NUM_VECTORS)
return; return;
dest = cpu_physical_id(ffz(~mask)); dest = cpu_physical_id(ffz(~mask));
pin = iosapic_irq[irq].pin; rte_index = iosapic_intr_info[vec].rte_index;
addr = iosapic_irq[irq].addr; addr = iosapic_intr_info[vec].addr;
if (pin < 0) if (rte_index < 0)
return; /* not an IOSAPIC interrupt */ return; /* not an IOSAPIC interrupt */
set_irq_affinity_info(irq,dest,redir); set_irq_affinity_info(irq, dest, redir);
/* dest contains both id and eid */ /* dest contains both id and eid */
high32 = dest << IOSAPIC_DEST_SHIFT; high32 = dest << IOSAPIC_DEST_SHIFT;
...@@ -281,7 +294,7 @@ iosapic_set_affinity (unsigned int irq, unsigned long mask) ...@@ -281,7 +294,7 @@ iosapic_set_affinity (unsigned int irq, unsigned long mask)
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
{ {
/* get current delivery mode by reading the low32 */ /* get current delivery mode by reading the low32 */
writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
low32 = readl(addr + IOSAPIC_WINDOW); low32 = readl(addr + IOSAPIC_WINDOW);
low32 &= ~(7 << IOSAPIC_DELIVERY_SHIFT); low32 &= ~(7 << IOSAPIC_DELIVERY_SHIFT);
...@@ -292,9 +305,9 @@ iosapic_set_affinity (unsigned int irq, unsigned long mask) ...@@ -292,9 +305,9 @@ iosapic_set_affinity (unsigned int irq, unsigned long mask)
/* change delivery mode to fixed */ /* change delivery mode to fixed */
low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
writel(IOSAPIC_RTE_HIGH(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
writel(high32, addr + IOSAPIC_WINDOW); writel(high32, addr + IOSAPIC_WINDOW);
writel(IOSAPIC_RTE_LOW(pin), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
writel(low32, addr + IOSAPIC_WINDOW); writel(low32, addr + IOSAPIC_WINDOW);
} }
spin_unlock_irqrestore(&iosapic_lock, flags); spin_unlock_irqrestore(&iosapic_lock, flags);
...@@ -317,7 +330,7 @@ iosapic_end_level_irq (unsigned int irq) ...@@ -317,7 +330,7 @@ iosapic_end_level_irq (unsigned int irq)
{ {
ia64_vector vec = irq_to_vector(irq); ia64_vector vec = irq_to_vector(irq);
writel(vec, iosapic_irq[vec].addr + IOSAPIC_EOI); writel(vec, iosapic_intr_info[vec].addr + IOSAPIC_EOI);
} }
#define iosapic_shutdown_level_irq mask_irq #define iosapic_shutdown_level_irq mask_irq
...@@ -388,7 +401,7 @@ iosapic_version (char *addr) ...@@ -388,7 +401,7 @@ iosapic_version (char *addr)
* { * {
* unsigned int version : 8; * unsigned int version : 8;
* unsigned int reserved1 : 8; * unsigned int reserved1 : 8;
* unsigned int pins : 8; * unsigned int max_redir : 8;
* unsigned int reserved2 : 8; * unsigned int reserved2 : 8;
* } * }
*/ */
...@@ -405,70 +418,72 @@ iosapic_reassign_vector (int vector) ...@@ -405,70 +418,72 @@ iosapic_reassign_vector (int vector)
{ {
int new_vector; int new_vector;
if (iosapic_irq[vector].pin >= 0 || iosapic_irq[vector].addr if (iosapic_intr_info[vector].rte_index >= 0 || iosapic_intr_info[vector].addr
|| iosapic_irq[vector].base_irq || iosapic_irq[vector].dmode || iosapic_intr_info[vector].gsi_base || iosapic_intr_info[vector].dmode
|| iosapic_irq[vector].polarity || iosapic_irq[vector].trigger) || iosapic_intr_info[vector].polarity || iosapic_intr_info[vector].trigger)
{ {
new_vector = ia64_alloc_irq(); new_vector = ia64_alloc_vector();
printk("Reassigning vector 0x%x to 0x%x\n", vector, new_vector); printk("Reassigning vector %d to %d\n", vector, new_vector);
memcpy (&iosapic_irq[new_vector], &iosapic_irq[vector], memcpy(&iosapic_intr_info[new_vector], &iosapic_intr_info[vector],
sizeof(struct iosapic_irq)); sizeof(struct iosapic_intr_info));
memset (&iosapic_irq[vector], 0, sizeof(struct iosapic_irq)); memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));
iosapic_irq[vector].pin = -1; iosapic_intr_info[vector].rte_index = -1;
} }
} }
static void static void
register_irq (u32 global_vector, int vector, int pin, unsigned char delivery, register_intr (unsigned int gsi, int vector, unsigned char delivery,
unsigned long polarity, unsigned long edge_triggered, unsigned long polarity, unsigned long edge_triggered,
u32 base_irq, char *iosapic_address) unsigned int gsi_base, char *iosapic_address)
{ {
irq_desc_t *idesc; irq_desc_t *idesc;
struct hw_interrupt_type *irq_type; struct hw_interrupt_type *irq_type;
int rte_index;
gsi_to_vector(global_vector) = vector; rte_index = gsi - gsi_base;
iosapic_irq[vector].pin = pin; iosapic_intr_info[vector].rte_index = rte_index;
iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW; iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
iosapic_irq[vector].dmode = delivery; iosapic_intr_info[vector].dmode = delivery;
/* /*
* In override, it does not provide addr/base_irq. global_vector is enough to * In override, it may not provide addr/gsi_base. GSI is enough to
* locate iosapic addr, base_irq and pin by examining base_irq and max_pin of * locate iosapic addr, gsi_base and rte_index by examining
* registered iosapics (tbd) * gsi_base and num_rte of registered iosapics (tbd)
*/ */
#ifndef OVERRIDE_DEBUG #ifndef OVERRIDE_DEBUG
if (iosapic_address) { if (iosapic_address) {
iosapic_irq[vector].addr = iosapic_address; iosapic_intr_info[vector].addr = iosapic_address;
iosapic_irq[vector].base_irq = base_irq; iosapic_intr_info[vector].gsi_base = gsi_base;
} }
#else #else
if (iosapic_address) { if (iosapic_address) {
if (iosapic_irq[vector].addr && (iosapic_irq[vector].addr != iosapic_address)) if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address))
printk("WARN: register_irq: diff IOSAPIC ADDRESS for gv %x, v %x\n", printk("WARN: register_intr: diff IOSAPIC ADDRESS for GSI 0x%x, vector %d\n",
global_vector, vector); gsi, vector);
iosapic_irq[vector].addr = iosapic_address; iosapic_intr_info[vector].addr = iosapic_address;
if (iosapic_irq[vector].base_irq && (iosapic_irq[vector].base_irq != base_irq)) { if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) {
printk("WARN: register_irq: diff BASE IRQ %x for gv %x, v %x\n", printk("WARN: register_intr: diff GSI base 0x%x for GSI 0x%x, vector %d\n",
base_irq, global_vector, vector); gsi_base, gsi, vector);
} }
iosapic_irq[vector].base_irq = base_irq; iosapic_intr_info[vector].gsi_base = gsi_base;
} else if (!iosapic_irq[vector].addr) } else if (!iosapic_intr_info[vector].addr)
printk("WARN: register_irq: invalid override for gv %x, v %x\n", printk("WARN: register_intr: invalid override for GSI 0x%x, vector %d\n",
global_vector, vector); gsi, vector);
#endif #endif
if (edge_triggered) { if (edge_triggered) {
iosapic_irq[vector].trigger = IOSAPIC_EDGE; iosapic_intr_info[vector].trigger = IOSAPIC_EDGE;
irq_type = &irq_type_iosapic_edge; irq_type = &irq_type_iosapic_edge;
} else { } else {
iosapic_irq[vector].trigger = IOSAPIC_LEVEL; iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL;
irq_type = &irq_type_iosapic_level; irq_type = &irq_type_iosapic_level;
} }
idesc = irq_desc(vector); idesc = irq_desc(vector);
if (idesc->handler != irq_type) { if (idesc->handler != irq_type) {
if (idesc->handler != &no_irq_type) if (idesc->handler != &no_irq_type)
printk("register_irq(): changing vector 0x%02x from " printk("%s: changing vector %d from %s to %s\n",
"%s to %s\n", vector, idesc->handler->typename, irq_type->typename); __FUNCTION__, vector, idesc->handler->typename,
irq_type->typename);
idesc->handler = irq_type; idesc->handler = irq_type;
} }
} }
...@@ -479,24 +494,26 @@ register_irq (u32 global_vector, int vector, int pin, unsigned char delivery, ...@@ -479,24 +494,26 @@ register_irq (u32 global_vector, int vector, int pin, unsigned char delivery,
* program the IOSAPIC RTE. * program the IOSAPIC RTE.
*/ */
int int
iosapic_register_irq (u32 global_vector, unsigned long polarity, unsigned long iosapic_register_intr (unsigned int gsi,
edge_triggered, u32 base_irq, char *iosapic_address) unsigned long polarity, unsigned long edge_triggered,
unsigned int gsi_base, char *iosapic_address)
{ {
int vector; int vector;
unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
vector = iosapic_irq_to_vector(global_vector); vector = gsi_to_vector(gsi);
if (vector < 0) if (vector < 0)
vector = ia64_alloc_irq(); vector = ia64_alloc_vector();
register_irq (global_vector, vector, global_vector - base_irq, register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered, polarity, edge_triggered, gsi_base, iosapic_address);
base_irq, iosapic_address);
printk("IOSAPIC 0x%x(%s,%s) -> Vector 0x%x\n", global_vector, printk("GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
(polarity ? "high" : "low"), (edge_triggered ? "edge" : "level"), vector); gsi, (polarity ? "high" : "low"),
(edge_triggered ? "edge" : "level"), dest, vector);
/* program the IOSAPIC routing table */ /* program the IOSAPIC routing table */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff); set_rte(vector, dest);
return vector; return vector;
} }
...@@ -505,12 +522,14 @@ iosapic_register_irq (u32 global_vector, unsigned long polarity, unsigned long ...@@ -505,12 +522,14 @@ iosapic_register_irq (u32 global_vector, unsigned long polarity, unsigned long
* Note that the irq_base and IOSAPIC address must be set in iosapic_init(). * Note that the irq_base and IOSAPIC address must be set in iosapic_init().
*/ */
int int
iosapic_register_platform_irq (u32 int_type, u32 global_vector, iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
u32 iosapic_vector, u16 eid, u16 id, unsigned long polarity, int iosapic_vector, u16 eid, u16 id,
unsigned long edge_triggered, u32 base_irq, char *iosapic_address) unsigned long polarity, unsigned long edge_triggered,
unsigned int gsi_base, char *iosapic_address)
{ {
unsigned char delivery; unsigned char delivery;
int vector; int vector;
unsigned int dest = ((id << 8) | eid) & 0xffff;
switch (int_type) { switch (int_type) {
case ACPI_INTERRUPT_PMI: case ACPI_INTERRUPT_PMI:
...@@ -523,7 +542,7 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector, ...@@ -523,7 +542,7 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector,
delivery = IOSAPIC_PMI; delivery = IOSAPIC_PMI;
break; break;
case ACPI_INTERRUPT_INIT: case ACPI_INTERRUPT_INIT:
vector = ia64_alloc_irq(); vector = ia64_alloc_vector();
delivery = IOSAPIC_INIT; delivery = IOSAPIC_INIT;
break; break;
case ACPI_INTERRUPT_CPEI: case ACPI_INTERRUPT_CPEI:
...@@ -535,56 +554,137 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector, ...@@ -535,56 +554,137 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector,
return -1; return -1;
} }
register_irq(global_vector, vector, global_vector - base_irq, delivery, polarity, register_intr(gsi, vector, delivery, polarity,
edge_triggered, base_irq, iosapic_address); edge_triggered, gsi_base, iosapic_address);
printk("PLATFORM int 0x%x: IOSAPIC 0x%x(%s,%s) -> Vector 0x%x CPU %.02u:%.02u\n", printk("PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
int_type, global_vector, (polarity ? "high" : "low"), int_type, gsi, (polarity ? "high" : "low"),
(edge_triggered ? "edge" : "level"), vector, eid, id); (edge_triggered ? "edge" : "level"), dest, vector);
/* program the IOSAPIC routing table */ /* program the IOSAPIC routing table */
set_rte(vector, ((id << 8) | eid) & 0xffff); set_rte(vector, dest);
return vector; return vector;
} }
/* /*
* ACPI calls this when it finds an entry for a legacy ISA interrupt. * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
* Note that the irq_base and IOSAPIC address must be set in iosapic_init(). * Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
*/ */
void void
iosapic_register_legacy_irq (unsigned long irq, iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long pin, unsigned long polarity, unsigned long polarity,
unsigned long edge_triggered) unsigned long edge_triggered)
{ {
int vector = isa_irq_to_vector(irq); int index, vector;
unsigned int gsi_base;
char *addr;
unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
register_irq(irq, vector, (int)pin, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered, index = find_iosapic(gsi);
0, NULL); /* ignored for override */
#ifdef DEBUG_IRQ_ROUTING if (index < 0) {
printk("ISA: IRQ %u -> IOSAPIC irq 0x%02x (%s, %s) -> vector %02x\n", printk("ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", isa_irq, gsi);
(unsigned) irq, (unsigned) pin, return;
polarity ? "high" : "low", edge_triggered ? "edge" : "level", }
vector);
#endif vector = isa_irq_to_vector(isa_irq);
addr = iosapic_lists[index].addr;
gsi_base = iosapic_lists[index].gsi_base;
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered,
gsi_base, addr);
DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
isa_irq, gsi,
polarity ? "high" : "low", edge_triggered ? "edge" : "level",
dest, vector);
/* program the IOSAPIC routing table */ /* program the IOSAPIC routing table */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff); set_rte(vector, dest);
}
/*
* Map PCI pin to the corresponding GSI.
* If no such mapping exists, return -1.
*/
static int
pci_pin_to_gsi (int bus, int slot, int pci_pin, unsigned int *gsi)
{
struct pci_vector_struct *r;
for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r)
if (r->bus == bus &&
(r->pci_id >> 16) == slot && r->pin == pci_pin) {
*gsi = r->irq;
return 0;
}
return -1;
}
/*
* Map PCI pin to the corresponding IA-64 interrupt vector. If no such mapping exists,
* try to allocate a new vector. If it fails, return -1.
*/
static int
pci_pin_to_vector (int bus, int slot, int pci_pin)
{
int index, vector;
int gsi_base, pcat_compat;
char *addr;
unsigned int gsi;
if (pci_pin_to_gsi(bus, slot, pci_pin, &gsi) < 0) {
printk("PCI: no interrupt route for %02x:%02x pin %c\n", bus, slot, 'A' + pci_pin);
return -1;
}
vector = gsi_to_vector(gsi);
if (vector < 0) {
/* we should allocate a vector for this interrupt line */
index = find_iosapic(gsi);
if (index < 0) {
printk("PCI: GSI 0x%x has no IOSAPIC mapping\n", gsi);
return -1;
}
addr = iosapic_lists[index].addr;
gsi_base = iosapic_lists[index].gsi_base;
pcat_compat = iosapic_lists[index].pcat_compat;
if (pcat_compat && (gsi < 16))
vector = isa_irq_to_vector(gsi);
else {
/* new GSI; allocate a vector for it */
vector = ia64_alloc_vector();
}
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
0, 0, gsi_base, addr);
DBG("PCI: (%02x:%02x INT%c) -> GSI 0x%x -> vector %d\n",
bus, slot, 'A' + pci_pin, gsi, vector);
}
return vector;
} }
void __init void __devinit
iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat) iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat)
{ {
int irq, max_pin, vector, pin; int num_rte, vector;
unsigned int ver; unsigned int isa_irq, ver;
char *addr; char *addr;
static int first_time = 1; static int first_time = 1;
if (first_time) { if (first_time) {
first_time = 0; first_time = 0;
for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
iosapic_irq[vector].pin = -1; /* mark as unused */ iosapic_intr_info[vector].rte_index = -1; /* mark as unused */
} }
if (pcat_compat) { if (pcat_compat) {
...@@ -599,109 +699,148 @@ iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat) ...@@ -599,109 +699,148 @@ iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat)
addr = ioremap(phys_addr, 0); addr = ioremap(phys_addr, 0);
ver = iosapic_version(addr); ver = iosapic_version(addr);
max_pin = (ver >> 16) & 0xff;
/*
* The MAX_REDIR register holds the highest input pin
* number (starting from 0).
* We add 1 so that we can use it for number of pins (= RTEs)
*/
num_rte = ((ver >> 16) & 0xff) + 1;
iosapic_lists[num_iosapic].addr = addr; iosapic_lists[num_iosapic].addr = addr;
iosapic_lists[num_iosapic].pcat_compat = pcat_compat; iosapic_lists[num_iosapic].pcat_compat = pcat_compat;
iosapic_lists[num_iosapic].base_irq = base_irq; iosapic_lists[num_iosapic].gsi_base = gsi_base;
iosapic_lists[num_iosapic].max_pin = max_pin; iosapic_lists[num_iosapic].num_rte = num_rte;
num_iosapic++; num_iosapic++;
printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n", printk("IOSAPIC: version %x.%x, address 0x%lx, GSIs 0x%x-0x%x\n",
(ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, base_irq, base_irq + max_pin); (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
if ((gsi_base == 0) && pcat_compat) {
unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
if ((base_irq == 0) && pcat_compat) {
/* /*
* Map the legacy ISA devices into the IOSAPIC data. Some of these may * Map the legacy ISA devices into the IOSAPIC data. Some of these may
* get reprogrammed later on with data from the ACPI Interrupt Source * get reprogrammed later on with data from the ACPI Interrupt Source
* Override table. * Override table.
*/ */
for (irq = 0; irq < 16; ++irq) { for (isa_irq = 0; isa_irq < 16; ++isa_irq) {
vector = isa_irq_to_vector(irq); vector = isa_irq_to_vector(isa_irq);
if ((pin = iosapic_irq[vector].pin) == -1)
pin = irq;
register_irq(irq, vector, pin, register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY,
/* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */ /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */
IOSAPIC_LOWEST_PRIORITY, 1, 1, base_irq, addr); 1, 1, gsi_base, addr);
#ifdef DEBUG_IRQ_ROUTING DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n",
printk("ISA: IRQ %u -> IOSAPIC irq 0x%02x (high, edge) -> vector 0x%02x\n", isa_irq, isa_irq, dest, vector);
irq, iosapic_irq[vector].base_irq + iosapic_irq[vector].pin,
vector);
#endif
/* program the IOSAPIC routing table: */ /* program the IOSAPIC routing table: */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff); set_rte(vector, dest);
} }
} }
} }
static void __init
iosapic_init_pci_irq (void)
{
int i, index, vector, pin;
int base_irq, max_pin, pcat_compat;
unsigned int irq;
char *addr;
if (acpi_get_prt(&pci_irq.route, &pci_irq.num_routes))
return;
for (i = 0; i < pci_irq.num_routes; i++) {
irq = pci_irq.route[i].irq; /*
* Set allocated interrupt vector to dev->irq and
* program IOSAPIC to deliver interrupts
*/
void
iosapic_fixup_pci_interrupt (struct pci_dev *dev)
{
unsigned char pci_pin;
int vector;
unsigned int dest;
struct hw_interrupt_type *irq_type;
irq_desc_t *idesc;
index = find_iosapic(irq); pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pci_pin);
if (index < 0) { if (pci_pin) {
printk("PCI: IRQ %u has no IOSAPIC mapping\n", irq); pci_pin--; /* interrupt pins are numberd starting from 1 */
continue;
vector = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pci_pin);
if (vector < 0 && dev->bus->parent) {
/* go back to the bridge */
struct pci_dev *bridge = dev->bus->self;
if (bridge) {
/* allow for multiple bridges on an adapter */
do {
/* do the bridge swizzle... */
pci_pin = (pci_pin + PCI_SLOT(dev->devfn)) % 4;
vector = pci_pin_to_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn),
pci_pin);
} while (vector < 0 && (bridge = bridge->bus->self));
}
if (vector >= 0)
printk(KERN_WARNING
"PCI: using PPB (%s INT%c) to get vector %d\n",
dev->slot_name, 'A' + pci_pin,
vector);
else
printk(KERN_WARNING
"PCI: Couldn't map irq for (%s INT%c)\n",
dev->slot_name, 'A' + pci_pin);
} }
addr = iosapic_lists[index].addr; if (vector >= 0) {
base_irq = iosapic_lists[index].base_irq; dev->irq = vector;
max_pin = iosapic_lists[index].max_pin;
pcat_compat = iosapic_lists[index].pcat_compat; irq_type = &irq_type_iosapic_level;
pin = irq - base_irq; idesc = irq_desc(vector);
if (idesc->handler != irq_type) {
if ((unsigned) pin > max_pin) if (idesc->handler != &no_irq_type)
/* the interrupt route is for another controller... */ printk("%s: changing vector %d from %s to %s\n",
continue; __FUNCTION__, vector,
idesc->handler->typename,
irq_type->typename);
idesc->handler = irq_type;
}
#ifdef CONFIG_SMP
/*
* For platforms that do not support interrupt redirect
* via the XTP interface, we can round-robin the PCI
* device interrupts to the processors
*/
if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
static int cpu_index = 0;
while (!cpu_online(cpu_index))
if (++cpu_index >= NR_CPUS)
cpu_index = 0;
dest = cpu_physical_id(cpu_index) & 0xffff;
} else {
/*
* Direct the interrupt vector to the current cpu,
* platform redirection will distribute them.
*/
dest = (ia64_get_lid() >> 16) & 0xffff;
}
#else
/* direct the interrupt vector to the running cpu id */
dest = (ia64_get_lid() >> 16) & 0xffff;
#endif
if (pcat_compat && (irq < 16)) printk("PCI->APIC IRQ transform: (%s INT%c) -> CPU 0x%04x vector %d\n",
vector = isa_irq_to_vector(irq); dev->slot_name, 'A' + pci_pin, dest, vector);
else { set_rte(vector, dest);
vector = iosapic_irq_to_vector(irq);
if (vector < 0)
/* new iosapic irq: allocate a vector for it */
vector = ia64_alloc_irq();
} }
register_irq(irq, vector, pin, IOSAPIC_LOWEST_PRIORITY, 0, 0, base_irq, addr);
#ifdef DEBUG_IRQ_ROUTING
printk("PCI: (B%d,I%d,P%d) -> IOSAPIC irq 0x%02x -> vector 0x%02x\n",
pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin,
iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector);
#endif
/*
* NOTE: The IOSAPIC RTE will be programmed in iosapic_pci_fixup(). It
* needs to be done there to ensure PCI hotplug works right.
*/
} }
} }
void void
iosapic_pci_fixup (int phase) iosapic_pci_fixup (int phase)
{ {
struct pci_dev *dev; struct pci_dev *dev;
unsigned char pin;
int vector;
struct hw_interrupt_type *irq_type;
irq_desc_t *idesc;
if (phase == 0) { if (phase == 0) {
iosapic_init_pci_irq(); if (acpi_get_prt(&pci_irq.route, &pci_irq.num_routes)) {
printk("%s: acpi_get_prt failed\n", __FILE__);
}
return; return;
} }
...@@ -709,76 +848,9 @@ iosapic_pci_fixup (int phase) ...@@ -709,76 +848,9 @@ iosapic_pci_fixup (int phase)
return; return;
pci_for_each_dev(dev) { pci_for_each_dev(dev) {
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); /* fixup dev->irq and program IOSAPIC */
if (pin) { iosapic_fixup_pci_interrupt(dev);
pin--; /* interrupt pins are numbered starting from 1 */
vector = pci_pin_to_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
if (vector < 0 && dev->bus->parent) {
/* go back to the bridge */
struct pci_dev *bridge = dev->bus->self;
if (bridge) {
/* allow for multiple bridges on an adapter */
do {
/* do the bridge swizzle... */
pin = (pin + PCI_SLOT(dev->devfn)) % 4;
vector = pci_pin_to_vector(bridge->bus->number,
PCI_SLOT(bridge->devfn),
pin);
} while (vector < 0 && (bridge = bridge->bus->self));
}
if (vector >= 0)
printk(KERN_WARNING
"PCI: using PPB(B%d,I%d,P%d) to get vector %02x\n",
dev->bus->number, PCI_SLOT(dev->devfn),
pin, vector);
else
printk(KERN_WARNING
"PCI: Couldn't map irq for (B%d,I%d,P%d)\n",
dev->bus->number, PCI_SLOT(dev->devfn), pin);
}
if (vector >= 0) {
printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> 0x%02x\n",
dev->bus->number, PCI_SLOT(dev->devfn), pin, vector);
dev->irq = vector;
irq_type = &irq_type_iosapic_level;
idesc = irq_desc(vector);
if (idesc->handler != irq_type) {
if (idesc->handler != &no_irq_type)
printk("iosapic_pci_fixup: changing vector 0x%02x "
"from %s to %s\n", vector,
idesc->handler->typename,
irq_type->typename);
idesc->handler = irq_type;
}
#ifdef CONFIG_SMP
/*
* For platforms that do not support interrupt redirect
* via the XTP interface, we can round-robin the PCI
* device interrupts to the processors
*/
if (!(smp_int_redirect & SMP_IRQ_REDIRECTION)) {
static int cpu_index = 0;
while (!cpu_online(cpu_index))
if (++cpu_index >= NR_CPUS)
cpu_index = 0;
set_rte(vector, cpu_physical_id(cpu_index) & 0xffff);
} else {
/*
* Direct the interrupt vector to the current cpu,
* platform redirection will distribute them.
*/
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
}
#else
/* direct the interrupt vector to the running cpu id */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
#endif
}
}
/* /*
* Nothing to fixup * Nothing to fixup
* Fix out-of-range IRQ numbers * Fix out-of-range IRQ numbers
......
...@@ -802,8 +802,7 @@ static struct proc_dir_entry * irq_dir [NR_IRQS]; ...@@ -802,8 +802,7 @@ static struct proc_dir_entry * irq_dir [NR_IRQS];
#define HEX_DIGITS 8 #define HEX_DIGITS 8
static unsigned int parse_hex_value (const char *buffer, static int parse_hex_value (const char *buffer, unsigned long count, unsigned long *ret)
unsigned long count, unsigned long *ret)
{ {
unsigned char hexnum [HEX_DIGITS]; unsigned char hexnum [HEX_DIGITS];
unsigned long value; unsigned long value;
...@@ -846,11 +845,11 @@ static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; ...@@ -846,11 +845,11 @@ static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 }; static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
void set_irq_affinity_info(int irq, int hwid, int redir) void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
{ {
unsigned long mask = 1UL<<cpu_logical_id(hwid); unsigned long mask = 1UL<<cpu_logical_id(hwid);
if (irq >= 0 && irq < NR_IRQS) { if (irq < NR_IRQS) {
irq_affinity[irq] = mask; irq_affinity[irq] = mask;
irq_redir[irq] = (char) (redir & 0xff); irq_redir[irq] = (char) (redir & 0xff);
} }
...@@ -861,14 +860,15 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, ...@@ -861,14 +860,15 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off,
{ {
if (count < HEX_DIGITS+3) if (count < HEX_DIGITS+3)
return -EINVAL; return -EINVAL;
return sprintf (page, "%s%08lx\n", irq_redir[(long)data] ? "r " : "", return sprintf (page, "%s%08lx\n", irq_redir[(unsigned long)data] ? "r " : "",
irq_affinity[(long)data]); irq_affinity[(unsigned long)data]);
} }
static int irq_affinity_write_proc (struct file *file, const char *buffer, static int irq_affinity_write_proc (struct file *file, const char *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
int irq = (long) data, full_count = count, err; unsigned int irq = (unsigned long) data;
int full_count = count, err;
unsigned long new_value; unsigned long new_value;
const char *buf = buffer; const char *buf = buffer;
int redir; int redir;
...@@ -884,6 +884,8 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -884,6 +884,8 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
redir = 0; redir = 0;
err = parse_hex_value(buf, count, &new_value); err = parse_hex_value(buf, count, &new_value);
if (err)
return err;
/* /*
* Do not allow disabling IRQs completely - it's a too easy * Do not allow disabling IRQs completely - it's a too easy
...@@ -893,7 +895,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -893,7 +895,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
if (!(new_value & cpu_online_map)) if (!(new_value & cpu_online_map))
return -EINVAL; return -EINVAL;
irq_desc(irq)->handler->set_affinity(irq | (redir?(1<<31):0), new_value); irq_desc(irq)->handler->set_affinity(irq | (redir? IA64_IRQ_REDIRECTED : 0), new_value);
return full_count; return full_count;
} }
...@@ -912,7 +914,8 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, ...@@ -912,7 +914,8 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
unsigned long *mask = (unsigned long *) data, full_count = count, err; unsigned long *mask = (unsigned long *) data;
int full_count = count, err;
unsigned long new_value; unsigned long new_value;
err = parse_hex_value(buffer, count, &new_value); err = parse_hex_value(buffer, count, &new_value);
...@@ -946,7 +949,7 @@ static void register_irq_proc (unsigned int irq) ...@@ -946,7 +949,7 @@ static void register_irq_proc (unsigned int irq)
if (entry) { if (entry) {
entry->nlink = 1; entry->nlink = 1;
entry->data = (void *)(long)irq; entry->data = (void *)(unsigned long)irq;
entry->read_proc = irq_affinity_read_proc; entry->read_proc = irq_affinity_read_proc;
entry->write_proc = irq_affinity_write_proc; entry->write_proc = irq_affinity_write_proc;
} }
......
...@@ -54,20 +54,15 @@ __u8 isa_irq_to_vector_map[16] = { ...@@ -54,20 +54,15 @@ __u8 isa_irq_to_vector_map[16] = {
0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
}; };
/*
* GSI to IA-64 vector translation table.
*/
__u8 gsi_to_vector_map[255];
int int
ia64_alloc_irq (void) ia64_alloc_vector (void)
{ {
static int next_irq = IA64_FIRST_DEVICE_VECTOR; static int next_vector = IA64_FIRST_DEVICE_VECTOR;
if (next_irq > IA64_LAST_DEVICE_VECTOR) if (next_vector > IA64_LAST_DEVICE_VECTOR)
/* XXX could look for sharable vectors instead of panic'ing... */ /* XXX could look for sharable vectors instead of panic'ing... */
panic("ia64_alloc_irq: out of interrupt vectors!"); panic("ia64_alloc_vector: out of interrupt vectors!");
return next_irq++; return next_vector++;
} }
extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs); extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);
......
...@@ -21,10 +21,10 @@ ...@@ -21,10 +21,10 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/efi.h>
#include <asm/pal.h> #include <asm/pal.h>
#include <asm/sal.h> #include <asm/sal.h>
#include <asm/efi.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/processor.h> #include <asm/processor.h>
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/efi.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/efi.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/perfmon.h> #include <asm/perfmon.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/efi.h>
#include <asm/ia32.h> #include <asm/ia32.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -37,7 +38,6 @@ ...@@ -37,7 +38,6 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/sal.h> #include <asm/sal.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/efi.h>
#include <asm/mca.h> #include <asm/mca.h>
#include <asm/smp.h> #include <asm/smp.h>
...@@ -58,9 +58,8 @@ extern char _end; ...@@ -58,9 +58,8 @@ extern char _end;
unsigned long __per_cpu_offset[NR_CPUS]; unsigned long __per_cpu_offset[NR_CPUS];
#endif #endif
DECLARE_PER_CPU(struct cpuinfo_ia64, cpu_info); DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info);
DEFINE_PER_CPU(unsigned long, ia64_phys_stacked_size_p8);
unsigned long ia64_phys_stacked_size_p8;
unsigned long ia64_cycles_per_usec; unsigned long ia64_cycles_per_usec;
struct ia64_boot_param *ia64_boot_param; struct ia64_boot_param *ia64_boot_param;
struct screen_info screen_info; struct screen_info screen_info;
...@@ -564,11 +563,11 @@ cpu_init (void) ...@@ -564,11 +563,11 @@ cpu_init (void)
my_cpu_data = (void *) get_free_page(GFP_KERNEL); my_cpu_data = (void *) get_free_page(GFP_KERNEL);
memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
__per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start; __per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start;
my_cpu_info = my_cpu_data + ((char *) &cpu_info - __per_cpu_start); my_cpu_info = my_cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start);
#else #else
my_cpu_data = __phys_per_cpu_start; my_cpu_data = __phys_per_cpu_start;
#endif #endif
my_cpu_info = my_cpu_data + ((char *) &cpu_info - __per_cpu_start); my_cpu_info = my_cpu_data + ((char *) &__get_cpu_var(cpu_info) - __per_cpu_start);
/* /*
* We can't pass "local_cpu_data" to identify_cpu() because we haven't called * We can't pass "local_cpu_data" to identify_cpu() because we haven't called
...@@ -652,6 +651,6 @@ cpu_init (void) ...@@ -652,6 +651,6 @@ cpu_init (void)
num_phys_stacked = 96; num_phys_stacked = 96;
} }
/* size of physical stacked register partition plus 8 bytes: */ /* size of physical stacked register partition plus 8 bytes: */
ia64_phys_stacked_size_p8 = num_phys_stacked*8 + 8; __get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8;
platform_cpu_init(); platform_cpu_init();
} }
...@@ -32,12 +32,12 @@ ...@@ -32,12 +32,12 @@
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/efi.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/efi.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -72,7 +72,7 @@ static volatile struct call_data_struct *call_data; ...@@ -72,7 +72,7 @@ static volatile struct call_data_struct *call_data;
#define IPI_CPU_STOP 1 #define IPI_CPU_STOP 1
/* This needs to be cacheline aligned because it is written to by *other* CPUs. */ /* This needs to be cacheline aligned because it is written to by *other* CPUs. */
static DECLARE_PER_CPU(__u64, ipi_operation) ____cacheline_aligned; static DEFINE_PER_CPU(__u64, ipi_operation) ____cacheline_aligned;
static void static void
stop_this_cpu (void) stop_this_cpu (void)
......
...@@ -27,13 +27,13 @@ ...@@ -27,13 +27,13 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/efi.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/current.h> #include <asm/current.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/efi.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/machvec.h> #include <asm/machvec.h>
......
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/efi.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/efi.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/sal.h> #include <asm/sal.h>
......
...@@ -135,8 +135,6 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) ...@@ -135,8 +135,6 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
siginfo_t siginfo; siginfo_t siginfo;
int sig, code; int sig, code;
die_if_kernel("bad break", regs, break_num);
/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
siginfo.si_imm = break_num; siginfo.si_imm = break_num;
...@@ -144,7 +142,8 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) ...@@ -144,7 +142,8 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
siginfo.si_isr = 0; siginfo.si_isr = 0;
switch (break_num) { switch (break_num) {
case 0: /* unknown error */ case 0: /* unknown error (used by GCC for __builtin_abort()) */
die_if_kernel("bad break", regs, break_num);
sig = SIGILL; code = ILL_ILLOPC; sig = SIGILL; code = ILL_ILLOPC;
break; break;
......
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
* Stephane Eranian <eranian@hpl.hp.com> * Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
*/ */
#include <linux/config.h>
#include <asm/asmmacro.h> #include <asm/asmmacro.h>
GLOBAL_ENTRY(bcopy) GLOBAL_ENTRY(bcopy)
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/efi.h>
#include <asm/a.out.h> #include <asm/a.out.h>
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/efi.h>
#include <asm/ia32.h> #include <asm/ia32.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/machvec.h> #include <asm/machvec.h>
......
...@@ -41,7 +41,7 @@ struct ia64_ctx ia64_ctx = { ...@@ -41,7 +41,7 @@ struct ia64_ctx ia64_ctx = {
.max_ctx = ~0U .max_ctx = ~0U
}; };
u8 ia64_need_tlb_flush __per_cpu_data; DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
/* /*
* Acquire the ia64_ctx.lock before calling this function! * Acquire the ia64_ctx.lock before calling this function!
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <asm/efi.h> #include <linux/efi.h>
#include "fpmem.h" #include "fpmem.h"
/* /*
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
* http://oss.sgi.com/projects/GenInfo/NoticeExplan * http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <asm/efi.h> #include <linux/efi.h>
#include <asm/pal.h> #include <asm/pal.h>
#include <asm/sal.h> #include <asm/sal.h>
#include <asm/sn/sn_sal.h> #include <asm/sn/sn_sal.h>
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <asm/efi.h> #include <linux/efi.h>
#include <asm/sn/klclock.h> #include <asm/sn/klclock.h>
/* /*
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/efi.h> #include <linux/efi.h>
#include <asm/page.h> #include <asm/page.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/sn/simulator.h> #include <asm/sn/simulator.h>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
OUTPUT_FORMAT("elf64-ia64-little") OUTPUT_FORMAT("elf64-ia64-little")
OUTPUT_ARCH(ia64) OUTPUT_ARCH(ia64)
ENTRY(phys_start) ENTRY(phys_start)
jiffies = jiffies_64; jiffies = jiffies_64;
SECTIONS SECTIONS
{ {
/* Sections to be discarded */ /* Sections to be discarded */
......
...@@ -100,7 +100,8 @@ const char *acpi_get_sysname (void); ...@@ -100,7 +100,8 @@ const char *acpi_get_sysname (void);
int acpi_boot_init (char *cdline); int acpi_boot_init (char *cdline);
int acpi_request_vector (u32 int_type); int acpi_request_vector (u32 int_type);
int acpi_get_prt (struct pci_vector_struct **vectors, int *count); int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
int acpi_get_interrupt_model(int *type); int acpi_get_interrupt_model (int *type);
int acpi_irq_to_vector (u32 irq);
#ifdef CONFIG_DISCONTIGMEM #ifdef CONFIG_DISCONTIGMEM
#define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */ #define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */
......
...@@ -18,4 +18,7 @@ ...@@ -18,4 +18,7 @@
#define flush_agp_mappings() /* nothing */ #define flush_agp_mappings() /* nothing */
#define flush_agp_cache() mb() #define flush_agp_cache() mb()
/* Page-protection value to be used for AGP memory mapped into kernel space. */
#define PAGE_AGP PAGE_KERNEL
#endif /* _ASM_IA64_AGP_H */ #endif /* _ASM_IA64_AGP_H */
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
* "int" types were carefully placed so as to ensure proper operation * "int" types were carefully placed so as to ensure proper operation
* of the macros. * of the macros.
* *
* Copyright (C) 1998, 1999 Hewlett-Packard Co * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
* Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
*/ */
#include <linux/types.h> #include <linux/types.h>
......
#ifndef _ASM_IA64_EFI_H
#define _ASM_IA64_EFI_H
/*
* Extensible Firmware Interface
* Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 1999, 2002 Hewlett-Packard Co.
* David Mosberger-Tang <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
*/
#include <linux/init.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <asm/page.h>
#include <asm/system.h>
#define EFI_SUCCESS 0
#define EFI_LOAD_ERROR (1L | (1L << 63))
#define EFI_INVALID_PARAMETER (2L | (1L << 63))
#define EFI_UNSUPPORTED (3L | (1L << 63))
#define EFI_BAD_BUFFER_SIZE (4L | (1L << 63))
#define EFI_BUFFER_TOO_SMALL (5L | (1L << 63))
#define EFI_NOT_FOUND (14L | (1L << 63))
typedef unsigned long efi_status_t;
typedef u8 efi_bool_t;
typedef u16 efi_char16_t; /* UNICODE character */
typedef struct {
u8 b[16];
} efi_guid_t;
#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
((efi_guid_t) \
{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
(b) & 0xff, ((b) >> 8) & 0xff, \
(c) & 0xff, ((c) >> 8) & 0xff, \
(d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
/*
* Generic EFI table header
*/
typedef struct {
u64 signature;
u32 revision;
u32 headersize;
u32 crc32;
u32 reserved;
} efi_table_hdr_t;
/*
* Memory map descriptor:
*/
/* Memory types: */
#define EFI_RESERVED_TYPE 0
#define EFI_LOADER_CODE 1
#define EFI_LOADER_DATA 2
#define EFI_BOOT_SERVICES_CODE 3
#define EFI_BOOT_SERVICES_DATA 4
#define EFI_RUNTIME_SERVICES_CODE 5
#define EFI_RUNTIME_SERVICES_DATA 6
#define EFI_CONVENTIONAL_MEMORY 7
#define EFI_UNUSABLE_MEMORY 8
#define EFI_ACPI_RECLAIM_MEMORY 9
#define EFI_ACPI_MEMORY_NVS 10
#define EFI_MEMORY_MAPPED_IO 11
#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
#define EFI_PAL_CODE 13
#define EFI_MAX_MEMORY_TYPE 14
/* Attribute values: */
#define EFI_MEMORY_UC 0x0000000000000001 /* uncached */
#define EFI_MEMORY_WC 0x0000000000000002 /* write-coalescing */
#define EFI_MEMORY_WT 0x0000000000000004 /* write-through */
#define EFI_MEMORY_WB 0x0000000000000008 /* write-back */
#define EFI_MEMORY_WP 0x0000000000001000 /* write-protect */
#define EFI_MEMORY_RP 0x0000000000002000 /* read-protect */
#define EFI_MEMORY_XP 0x0000000000004000 /* execute-protect */
#define EFI_MEMORY_RUNTIME 0x8000000000000000 /* range requires runtime mapping */
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
#define EFI_PAGE_SHIFT 12
typedef struct {
u32 type;
u32 pad;
u64 phys_addr;
u64 virt_addr;
u64 num_pages;
u64 attribute;
} efi_memory_desc_t;
typedef int efi_freemem_callback_t (u64 start, u64 end, void *arg);
/*
* Types and defines for Time Services
*/
#define EFI_TIME_ADJUST_DAYLIGHT 0x1
#define EFI_TIME_IN_DAYLIGHT 0x2
#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
typedef struct {
u16 year;
u8 month;
u8 day;
u8 hour;
u8 minute;
u8 second;
u8 pad1;
u32 nanosecond;
s16 timezone;
u8 daylight;
u8 pad2;
} efi_time_t;
typedef struct {
u32 resolution;
u32 accuracy;
u8 sets_to_zero;
} efi_time_cap_t;
/*
* Types and defines for EFI ResetSystem
*/
#define EFI_RESET_COLD 0
#define EFI_RESET_WARM 1
/*
* EFI Runtime Services table
*/
#define EFI_RUNTIME_SERVICES_SIGNATURE 0x5652453544e5552
#define EFI_RUNTIME_SERVICES_REVISION 0x00010000
typedef struct {
efi_table_hdr_t hdr;
u64 get_time;
u64 set_time;
u64 get_wakeup_time;
u64 set_wakeup_time;
u64 set_virtual_address_map;
u64 convert_pointer;
u64 get_variable;
u64 get_next_variable;
u64 set_variable;
u64 get_next_high_mono_count;
u64 reset_system;
} efi_runtime_services_t;
typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
typedef efi_status_t efi_set_time_t (efi_time_t *tm);
typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
efi_time_t *tm);
typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
unsigned long *data_size, void *data);
typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
efi_guid_t *vendor);
typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 attr,
unsigned long data_size, void *data);
typedef efi_status_t efi_get_next_high_mono_count_t (u64 *count);
typedef void efi_reset_system_t (int reset_type, efi_status_t status,
unsigned long data_size, efi_char16_t *data);
/*
* EFI Configuration Table and GUID definitions
*/
#define NULL_GUID \
EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
#define MPS_TABLE_GUID \
EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define ACPI_TABLE_GUID \
EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define ACPI_20_TABLE_GUID \
EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
#define SMBIOS_TABLE_GUID \
EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define SAL_SYSTEM_TABLE_GUID \
EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
#define HCDP_TABLE_GUID \
EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
typedef struct {
efi_guid_t guid;
u64 table;
} efi_config_table_t;
#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
#define EFI_SYSTEM_TABLE_REVISION ((1 << 16) | 00)
typedef struct {
efi_table_hdr_t hdr;
u64 fw_vendor; /* physical addr of CHAR16 vendor string */
u32 fw_revision;
u64 con_in_handle;
u64 con_in;
u64 con_out_handle;
u64 con_out;
u64 stderr_handle;
u64 stderr;
u64 runtime;
u64 boottime;
u64 nr_tables;
u64 tables;
} efi_system_table_t;
/*
* All runtime access to EFI goes through this structure:
*/
extern struct efi {
efi_system_table_t *systab; /* EFI system table */
void *mps; /* MPS table */
void *acpi; /* ACPI table (IA64 ext 0.71) */
void *acpi20; /* ACPI table (ACPI 2.0) */
void *smbios; /* SM BIOS table */
void *sal_systab; /* SAL system table */
void *boot_info; /* boot info table */
void *hcdp; /* HCDP table */
efi_get_time_t *get_time;
efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time;
efi_set_wakeup_time_t *set_wakeup_time;
efi_get_variable_t *get_variable;
efi_get_next_variable_t *get_next_variable;
efi_set_variable_t *set_variable;
efi_get_next_high_mono_count_t *get_next_high_mono_count;
efi_reset_system_t *reset_system;
} efi;
static inline int
efi_guidcmp (efi_guid_t left, efi_guid_t right)
{
return memcmp(&left, &right, sizeof (efi_guid_t));
}
static inline char *
efi_guid_unparse(efi_guid_t *guid, char *out)
{
sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
guid->b[3], guid->b[2], guid->b[1], guid->b[0],
guid->b[5], guid->b[4], guid->b[7], guid->b[6],
guid->b[8], guid->b[9], guid->b[10], guid->b[11],
guid->b[12], guid->b[13], guid->b[14], guid->b[15]);
return out;
}
extern void efi_init (void);
extern void efi_map_pal_code (void);
extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
extern void efi_gettimeofday (struct timeval *tv);
extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
extern u64 efi_get_iobase (void);
extern u32 efi_mem_type (unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr);
/*
* Variable Attributes
*/
#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
/*
* efi_dir is allocated in arch/ia64/kernel/efi.c.
*/
#ifdef CONFIG_PROC_FS
extern struct proc_dir_entry *efi_dir;
#endif
#endif /* _ASM_IA64_EFI_H */
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
#define _ASM_IA64_FPU_H #define _ASM_IA64_FPU_H
/* /*
* Copyright (C) 1998, 1999 Hewlett-Packard Co * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
* Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
*/ */
#include <asm/types.h> #include <asm/types.h>
......
...@@ -92,12 +92,12 @@ ...@@ -92,12 +92,12 @@
# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
#endif #endif
#define irq_exit() \ #define irq_exit() \
do { \ do { \
preempt_count() -= IRQ_EXIT_OFFSET; \ preempt_count() -= IRQ_EXIT_OFFSET; \
if (!in_interrupt() && softirq_pending(smp_processor_id())) \ if (!in_interrupt() && local_softirq_pending()) \
do_softirq(); \ do_softirq(); \
preempt_enable_no_resched(); \ preempt_enable_no_resched(); \
} while (0) } while (0)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -53,6 +53,10 @@ typedef u8 ia64_vector; ...@@ -53,6 +53,10 @@ typedef u8 ia64_vector;
#define IA64_IPI_RESCHEDULE 0xfd /* SMP reschedule */ #define IA64_IPI_RESCHEDULE 0xfd /* SMP reschedule */
#define IA64_IPI_VECTOR 0xfe /* inter-processor interrupt vector */ #define IA64_IPI_VECTOR 0xfe /* inter-processor interrupt vector */
/* Used for encoding redirected irqs */
#define IA64_IRQ_REDIRECTED (1 << 31)
/* IA64 inter-cpu interrupt related definitions */ /* IA64 inter-cpu interrupt related definitions */
#define IA64_IPI_DEFAULT_BASE_ADDR 0xfee00000 #define IA64_IPI_DEFAULT_BASE_ADDR 0xfee00000
...@@ -68,14 +72,12 @@ enum { ...@@ -68,14 +72,12 @@ enum {
extern __u8 isa_irq_to_vector_map[16]; extern __u8 isa_irq_to_vector_map[16];
#define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)] #define isa_irq_to_vector(x) isa_irq_to_vector_map[(x)]
extern __u8 gsi_to_vector_map[255];
#define gsi_to_vector(x) gsi_to_vector_map[(x)]
extern unsigned long ipi_base_addr; extern unsigned long ipi_base_addr;
extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */ extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt controller */
extern int ia64_alloc_irq (void); /* allocate a free irq */ extern int ia64_alloc_vector (void); /* allocate a free vector */
extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
......
...@@ -85,11 +85,25 @@ ide_init_default_hwifs (void) ...@@ -85,11 +85,25 @@ ide_init_default_hwifs (void)
for(index = 0; index < MAX_HWIFS; index++) { for(index = 0; index < MAX_HWIFS; index++) {
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index)); hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw); ide_register_hw(&hw, NULL);
} }
#endif #endif
} }
#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
#define ide_check_region(from,extent) check_region((from), (extent))
#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
#define ide_release_region(from,extent) release_region((from), (extent))
/*
* The following are not needed for the non-m68k ports
*/
#define ide_ack_intr(hwif) (1)
#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* __ASM_IA64_IDE_H */ #endif /* __ASM_IA64_IDE_H */
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* over and over again with slight variations and possibly making a * over and over again with slight variations and possibly making a
* mistake somewhere. * mistake somewhere.
* *
* Copyright (C) 1998-2001 Hewlett-Packard Co * Copyright (C) 1998-2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com> * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com> * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
...@@ -277,9 +277,9 @@ __outsl (unsigned long port, void *src, unsigned long count) ...@@ -277,9 +277,9 @@ __outsl (unsigned long port, void *src, unsigned long count)
} }
/* /*
* Unfortunately, some platforms are broken and do not follow the * Unfortunately, some platforms are broken and do not follow the IA-64 architecture
* IA-64 architecture specification regarding legacy I/O support. * specification regarding legacy I/O support. Thus, we have to make these operations
* Thus, we have to make these operations platform dependent... * platform dependent...
*/ */
#define __inb platform_inb #define __inb platform_inb
#define __inw platform_inw #define __inw platform_inw
...@@ -289,19 +289,19 @@ __outsl (unsigned long port, void *src, unsigned long count) ...@@ -289,19 +289,19 @@ __outsl (unsigned long port, void *src, unsigned long count)
#define __outl platform_outl #define __outl platform_outl
#define __mmiob platform_mmiob #define __mmiob platform_mmiob
#define inb __inb #define inb(p) __inb(p)
#define inw __inw #define inw(p) __inw(p)
#define inl __inl #define inl(p) __inl(p)
#define insb __insb #define insb(p,d,c) __insb(p,d,c)
#define insw __insw #define insw(p,d,c) __insw(p,d,c)
#define insl __insl #define insl(p,d,c) __insl(p,d,c)
#define outb __outb #define outb(v,p) __outb(v,p)
#define outw __outw #define outw(v,p) __outw(v,p)
#define outl __outl #define outl(v,p) __outl(v,p)
#define outsb __outsb #define outsb(p,s,c) __outsb(p,s,c)
#define outsw __outsw #define outsw(p,s,c) __outsw(p,s,c)
#define outsl __outsl #define outsl(p,s,c) __outsl(p,s,c)
#define mmiob __mmiob #define mmiob() __mmiob()
/* /*
* The address passed to these functions are ioremap()ped already. * The address passed to these functions are ioremap()ped already.
......
...@@ -51,17 +51,24 @@ ...@@ -51,17 +51,24 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern void __init iosapic_init (unsigned long address, unsigned int base_irq, extern void __devinit iosapic_init (unsigned long address,
int pcat_compat); unsigned int gsi_base,
extern int iosapic_register_irq (u32 global_vector, unsigned long polarity, int pcat_compat);
unsigned long edge_triggered, u32 base_irq, extern int gsi_to_vector (unsigned int gsi);
char *iosapic_address); extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
extern void iosapic_register_legacy_irq (unsigned long irq, unsigned long pin, unsigned long edge_triggered,
unsigned long polarity, unsigned long trigger); u32 gsi_base, char *iosapic_address);
extern int iosapic_register_platform_irq (u32 int_type, u32 global_vector, u32 iosapic_vector, extern void iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
u16 eid, u16 id, unsigned long polarity, unsigned long polarity,
unsigned long edge_triggered, u32 base_irq, unsigned long edge_triggered);
char *iosapic_address); extern int iosapic_register_platform_intr (u32 int_type,
unsigned int gsi,
int pmi_vector,
u16 eid, u16 id,
unsigned long polarity,
unsigned long edge_triggered,
unsigned int gsi_base,
char *iosapic_address);
extern unsigned int iosapic_version (char *addr); extern unsigned int iosapic_version (char *addr);
extern void iosapic_pci_fixup (int); extern void iosapic_pci_fixup (int);
......
...@@ -27,6 +27,6 @@ irq_cannonicalize (int irq) ...@@ -27,6 +27,6 @@ irq_cannonicalize (int irq)
extern void disable_irq (unsigned int); extern void disable_irq (unsigned int);
extern void disable_irq_nosync (unsigned int); extern void disable_irq_nosync (unsigned int);
extern void enable_irq (unsigned int); extern void enable_irq (unsigned int);
extern void set_irq_affinity_info (int irq, int dest, int redir); extern void set_irq_affinity_info (unsigned int irq, int dest, int redir);
#endif /* _ASM_IA64_IRQ_H */ #endif /* _ASM_IA64_IRQ_H */
#ifndef _ASM_IA64_KMAP_TYPES_H
#define _ASM_IA64_KMAP_TYPES_H
#include <linux/config.h>
#if CONFIG_DEBUG_HIGHMEM
# define D(n) __KM_FENCE_##n ,
#else
# define D(n)
#endif
enum km_type {
D(0) KM_BOUNCE_READ,
D(1) KM_SKB_SUNRPC_DATA,
D(2) KM_SKB_DATA_SOFTIRQ,
D(3) KM_USER0,
D(4) KM_USER1,
D(5) KM_BIO_SRC_IRQ,
D(6) KM_BIO_DST_IRQ,
D(7) KM_PTE0,
D(8) KM_PTE1,
D(9) KM_IRQ0,
D(10) KM_IRQ1,
D(11) KM_TYPE_NR
};
#undef D
#endif /* _ASM_IA64_KMAP_TYPES_H */
#ifndef _ASM_IA64_MC146818RTC_H
#define _ASM_IA64_MC146818RTC_H
/*
* Machine dependent access functions for RTC registers.
*/
/* empty include file to satisfy the include in genrtc.c */
#endif /* _ASM_IA64_MC146818RTC_H */
...@@ -36,7 +36,7 @@ struct ia64_ctx { ...@@ -36,7 +36,7 @@ struct ia64_ctx {
}; };
extern struct ia64_ctx ia64_ctx; extern struct ia64_ctx ia64_ctx;
extern u8 ia64_need_tlb_flush __per_cpu_data; DECLARE_PER_CPU(u8, ia64_need_tlb_flush);
extern void wrap_mmu_context (struct mm_struct *mm); extern void wrap_mmu_context (struct mm_struct *mm);
...@@ -56,9 +56,9 @@ delayed_tlb_flush (void) ...@@ -56,9 +56,9 @@ delayed_tlb_flush (void)
{ {
extern void __flush_tlb_all (void); extern void __flush_tlb_all (void);
if (unlikely(ia64_need_tlb_flush)) { if (unlikely(__get_cpu_var(ia64_need_tlb_flush))) {
__flush_tlb_all(); __flush_tlb_all();
ia64_need_tlb_flush = 0; __get_cpu_var(ia64_need_tlb_flush) = 0;
} }
} }
......
#ifndef _ASM_IA64_PERCPU_H #ifndef _ASM_IA64_PERCPU_H
#define _ASM_IA64_PERCPU_H #define _ASM_IA64_PERCPU_H
#include <linux/config.h>
#include <linux/compiler.h>
/* /*
* Copyright (C) 2002 Hewlett-Packard Co * Copyright (C) 2002 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
...@@ -8,7 +11,7 @@ ...@@ -8,7 +11,7 @@
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
#define THIS_CPU(var) (var##__per_cpu) /* use this to mark accesses to per-CPU variables... */ #define THIS_CPU(var) (var##__per_cpu) /* use this to mark accesses to per-CPU variables... */
#else /* !__ASSEMBLY__ */ #else /* !__ASSEMBLY__ */
...@@ -22,8 +25,12 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; ...@@ -22,8 +25,12 @@ extern unsigned long __per_cpu_offset[NR_CPUS];
#endif #endif
#define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu #define DECLARE_PER_CPU(type, name) extern __typeof__(type) name##__per_cpu
#define per_cpu(var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) (var##__per_cpu) #define __get_cpu_var(var) (var##__per_cpu)
#ifdef CONFIG_SMP
# define per_cpu(var, cpu) (*RELOC_HIDE(&var##__per_cpu, __per_cpu_offset[cpu]))
#else
# define per_cpu(var, cpu) __get_cpu_var(var)
#endif
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
......
...@@ -15,9 +15,6 @@ ...@@ -15,9 +15,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/percpu.h>
#include <linux/compiler.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/kregs.h> #include <asm/kregs.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -81,8 +78,10 @@ ...@@ -81,8 +78,10 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/threads.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/compiler.h>
#include <linux/percpu.h>
#include <linux/threads.h>
#include <asm/fpu.h> #include <asm/fpu.h>
#include <asm/offsets.h> #include <asm/offsets.h>
......
...@@ -24,9 +24,9 @@ ...@@ -24,9 +24,9 @@
*/ */
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/efi.h>
#include <asm/pal.h> #include <asm/pal.h>
#include <asm/efi.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/fpu.h> #include <asm/fpu.h>
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
* Copyright (C) 1999 Don Dugger <don.dugger@intel.com> * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/percpu.h>
#include <asm/kregs.h> #include <asm/kregs.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -26,6 +25,7 @@ ...@@ -26,6 +25,7 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/percpu.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -368,8 +368,8 @@ extern void ia64_save_extra (struct task_struct *task); ...@@ -368,8 +368,8 @@ extern void ia64_save_extra (struct task_struct *task);
extern void ia64_load_extra (struct task_struct *task); extern void ia64_load_extra (struct task_struct *task);
#if defined(CONFIG_SMP) && defined(CONFIG_PERFMON) #if defined(CONFIG_SMP) && defined(CONFIG_PERFMON)
extern int __per_cpu_data pfm_syst_wide; DECLARE_PER_CPU(int, pfm_syst_wide);
# define PERFMON_IS_SYSWIDE() (this_cpu(pfm_syst_wide) != 0) # define PERFMON_IS_SYSWIDE() (get_cpu_var(pfm_syst_wide) != 0)
#else #else
# define PERFMON_IS_SYSWIDE() (0) # define PERFMON_IS_SYSWIDE() (0)
#endif #endif
......
...@@ -2,14 +2,13 @@ ...@@ -2,14 +2,13 @@
#define _ASM_IA64_TYPES_H #define _ASM_IA64_TYPES_H
/* /*
* This file is never included by application software unless * This file is never included by application software unless explicitly requested (e.g.,
* explicitly requested (e.g., via linux/types.h) in which case the * via linux/types.h) in which case the application is Linux specific so (user-) name
* application is Linux specific so (user-) name space pollution is * space pollution is not a major issue. However, for interoperability, libraries still
* not a major issue. However, for interoperability, libraries still
* need to be careful to avoid a name clashes. * need to be careful to avoid a name clashes.
* *
* Copyright (C) 1998-2000 Hewlett-Packard Co * Copyright (C) 1998-2000, 2002 Hewlett-Packard Co
* Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> * David Mosberger-Tang <davidm@hpl.hp.com>
*/ */
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
...@@ -18,9 +17,6 @@ ...@@ -18,9 +17,6 @@
#else #else
# define __IA64_UL(x) ((unsigned long)(x)) # define __IA64_UL(x) ((unsigned long)(x))
# define __IA64_UL_CONST(x) x##UL # define __IA64_UL_CONST(x) x##UL
#endif
#ifndef __ASSEMBLY__
typedef unsigned int umode_t; typedef unsigned int umode_t;
......
...@@ -223,10 +223,15 @@ ...@@ -223,10 +223,15 @@
#define __NR_sched_setaffinity 1231 #define __NR_sched_setaffinity 1231
#define __NR_sched_getaffinity 1232 #define __NR_sched_getaffinity 1232
#define __NR_security 1233 #define __NR_security 1233
#define __NR_get_large_pages 1234 #define __NR_alloc_hugepages 1234
#define __NR_free_large_pages 1235 #define __NR_free_hugepages 1235
#define __NR_share_large_pages 1236 /* 1236 currently unused */
#define __NR_unshare_large_pages 1237 /* 1237 currently unused */
#define __NR_io_setup 1238
#define __NR_io_destroy 1239
#define __NR_io_getevents 1240
#define __NR_io_submit 1241
#define __NR_io_cancel 1242
#if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
......
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