diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/arm/Kconfig | 5 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/irq.c | 7 | ||||
| -rw-r--r-- | arch/arm/oprofile/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/oprofile/backtrace.c | 144 | ||||
| -rw-r--r-- | arch/arm/oprofile/init.c | 2 | ||||
| -rw-r--r-- | arch/arm/oprofile/op_arm_model.h | 2 | ||||
| -rw-r--r-- | arch/i386/boot/tools/build.c | 3 | ||||
| -rw-r--r-- | arch/i386/kernel/acpi/boot.c | 57 | ||||
| -rw-r--r-- | arch/i386/pci/common.c | 8 | ||||
| -rw-r--r-- | arch/i386/pci/irq.c | 51 | ||||
| -rw-r--r-- | arch/i386/pci/legacy.c | 2 | ||||
| -rw-r--r-- | arch/i386/pci/mmconfig.c | 39 | ||||
| -rw-r--r-- | arch/i386/pci/numa.c | 2 | ||||
| -rw-r--r-- | arch/i386/pci/pci.h | 1 | ||||
| -rw-r--r-- | arch/ia64/kernel/acpi.c | 30 | ||||
| -rw-r--r-- | arch/ia64/kernel/iosapic.c | 134 | ||||
| -rw-r--r-- | arch/ia64/pci/pci.c | 38 | ||||
| -rw-r--r-- | arch/ppc/kernel/pci.c | 21 | ||||
| -rw-r--r-- | arch/ppc64/kernel/irq.c | 2 | ||||
| -rw-r--r-- | arch/ppc64/kernel/pci.c | 22 | ||||
| -rw-r--r-- | arch/sparc/Kconfig | 56 | ||||
| -rw-r--r-- | arch/x86_64/pci/mmconfig.c | 68 |
22 files changed, 554 insertions, 142 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c8d94dcd8ef7..620f2ca94ed2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -361,6 +361,11 @@ config NO_IDLE_HZ | |||
| 361 | Alternatively, if you want dynamic tick automatically enabled | 361 | Alternatively, if you want dynamic tick automatically enabled |
| 362 | during boot, pass "dyntick=enable" via the kernel command string. | 362 | during boot, pass "dyntick=enable" via the kernel command string. |
| 363 | 363 | ||
| 364 | Please note that dynamic tick may affect the accuracy of | ||
| 365 | timekeeping on some platforms depending on the implementation. | ||
| 366 | Currently at least OMAP platform is known to have accurate | ||
| 367 | timekeeping with dynamic tick. | ||
| 368 | |||
| 364 | config ARCH_DISCONTIGMEM_ENABLE | 369 | config ARCH_DISCONTIGMEM_ENABLE |
| 365 | bool | 370 | bool |
| 366 | default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) | 371 | default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) |
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c index b668c48f4399..cf9f46d88061 100644 --- a/arch/arm/mach-s3c2410/irq.c +++ b/arch/arm/mach-s3c2410/irq.c | |||
| @@ -40,8 +40,11 @@ | |||
| 40 | * 04-Nov-2004 Ben Dooks | 40 | * 04-Nov-2004 Ben Dooks |
| 41 | * Fix standard IRQ wake for EINT0..4 and RTC | 41 | * Fix standard IRQ wake for EINT0..4 and RTC |
| 42 | * | 42 | * |
| 43 | * 22-Feb-2004 Ben Dooks | 43 | * 22-Feb-2005 Ben Dooks |
| 44 | * Fixed edge-triggering on ADC IRQ | 44 | * Fixed edge-triggering on ADC IRQ |
| 45 | * | ||
| 46 | * 28-Jun-2005 Ben Dooks | ||
| 47 | * Mark IRQ_LCD valid | ||
| 45 | */ | 48 | */ |
| 46 | 49 | ||
| 47 | #include <linux/init.h> | 50 | #include <linux/init.h> |
| @@ -366,7 +369,6 @@ static struct irqchip s3c_irq_eint0t4 = { | |||
| 366 | #define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) | 369 | #define INTMSK_UART1 (1UL << (IRQ_UART1 - IRQ_EINT0)) |
| 367 | #define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) | 370 | #define INTMSK_UART2 (1UL << (IRQ_UART2 - IRQ_EINT0)) |
| 368 | #define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) | 371 | #define INTMSK_ADCPARENT (1UL << (IRQ_ADCPARENT - IRQ_EINT0)) |
| 369 | #define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) | ||
| 370 | 372 | ||
| 371 | static inline void | 373 | static inline void |
| 372 | s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit, | 374 | s3c_irqsub_mask(unsigned int irqno, unsigned int parentbit, |
| @@ -716,7 +718,6 @@ void __init s3c24xx_init_irq(void) | |||
| 716 | case IRQ_UART0: | 718 | case IRQ_UART0: |
| 717 | case IRQ_UART1: | 719 | case IRQ_UART1: |
| 718 | case IRQ_UART2: | 720 | case IRQ_UART2: |
| 719 | case IRQ_LCD: | ||
| 720 | case IRQ_ADCPARENT: | 721 | case IRQ_ADCPARENT: |
| 721 | set_irq_chip(irqno, &s3c_irq_level_chip); | 722 | set_irq_chip(irqno, &s3c_irq_level_chip); |
| 722 | set_irq_handler(irqno, do_level_IRQ); | 723 | set_irq_handler(irqno, do_level_IRQ); |
diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile index ba1a6e9f2b28..8ffb523e6c77 100644 --- a/arch/arm/oprofile/Makefile +++ b/arch/arm/oprofile/Makefile | |||
| @@ -6,6 +6,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ | |||
| 6 | oprofilefs.o oprofile_stats.o \ | 6 | oprofilefs.o oprofile_stats.o \ |
| 7 | timer_int.o ) | 7 | timer_int.o ) |
| 8 | 8 | ||
| 9 | oprofile-y := $(DRIVER_OBJS) init.o | 9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o |
| 10 | oprofile-$(CONFIG_CPU_XSCALE) += common.o op_model_xscale.o | 10 | oprofile-$(CONFIG_CPU_XSCALE) += common.o op_model_xscale.o |
| 11 | 11 | ||
diff --git a/arch/arm/oprofile/backtrace.c b/arch/arm/oprofile/backtrace.c new file mode 100644 index 000000000000..ec58d3e2eb8b --- /dev/null +++ b/arch/arm/oprofile/backtrace.c | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | /* | ||
| 2 | * Arm specific backtracing code for oprofile | ||
| 3 | * | ||
| 4 | * Copyright 2005 Openedhand Ltd. | ||
| 5 | * | ||
| 6 | * Author: Richard Purdie <rpurdie@openedhand.com> | ||
| 7 | * | ||
| 8 | * Based on i386 oprofile backtrace code by John Levon, David Smith | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/oprofile.h> | ||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <linux/mm.h> | ||
| 19 | #include <asm/ptrace.h> | ||
| 20 | #include <asm/uaccess.h> | ||
| 21 | |||
| 22 | |||
| 23 | /* | ||
| 24 | * The registers we're interested in are at the end of the variable | ||
| 25 | * length saved register structure. The fp points at the end of this | ||
| 26 | * structure so the address of this struct is: | ||
| 27 | * (struct frame_tail *)(xxx->fp)-1 | ||
| 28 | */ | ||
| 29 | struct frame_tail { | ||
| 30 | struct frame_tail *fp; | ||
| 31 | unsigned long sp; | ||
| 32 | unsigned long lr; | ||
| 33 | } __attribute__((packed)); | ||
| 34 | |||
| 35 | |||
| 36 | #ifdef CONFIG_FRAME_POINTER | ||
| 37 | static struct frame_tail* kernel_backtrace(struct frame_tail *tail) | ||
| 38 | { | ||
| 39 | oprofile_add_trace(tail->lr); | ||
| 40 | |||
| 41 | /* frame pointers should strictly progress back up the stack | ||
| 42 | * (towards higher addresses) */ | ||
| 43 | if (tail >= tail->fp) | ||
| 44 | return NULL; | ||
| 45 | |||
| 46 | return tail->fp-1; | ||
| 47 | } | ||
| 48 | #endif | ||
| 49 | |||
| 50 | static struct frame_tail* user_backtrace(struct frame_tail *tail) | ||
| 51 | { | ||
| 52 | struct frame_tail buftail; | ||
| 53 | |||
| 54 | /* hardware pte might not be valid due to dirty/accessed bit emulation | ||
| 55 | * so we use copy_from_user and benefit from exception fixups */ | ||
| 56 | if (copy_from_user(&buftail, tail, sizeof(struct frame_tail))) | ||
| 57 | return NULL; | ||
| 58 | |||
| 59 | oprofile_add_trace(buftail.lr); | ||
| 60 | |||
| 61 | /* frame pointers should strictly progress back up the stack | ||
| 62 | * (towards higher addresses) */ | ||
| 63 | if (tail >= buftail.fp) | ||
| 64 | return NULL; | ||
| 65 | |||
| 66 | return buftail.fp-1; | ||
| 67 | } | ||
| 68 | |||
| 69 | /* Compare two addresses and see if they're on the same page */ | ||
| 70 | #define CMP_ADDR_EQUAL(x,y,offset) ((((unsigned long) x) >> PAGE_SHIFT) \ | ||
| 71 | == ((((unsigned long) y) + offset) >> PAGE_SHIFT)) | ||
| 72 | |||
| 73 | /* check that the page(s) containing the frame tail are present */ | ||
| 74 | static int pages_present(struct frame_tail *tail) | ||
| 75 | { | ||
| 76 | struct mm_struct * mm = current->mm; | ||
| 77 | |||
| 78 | if (!check_user_page_readable(mm, (unsigned long)tail)) | ||
| 79 | return 0; | ||
| 80 | |||
| 81 | if (CMP_ADDR_EQUAL(tail, tail, 8)) | ||
| 82 | return 1; | ||
| 83 | |||
| 84 | if (!check_user_page_readable(mm, ((unsigned long)tail) + 8)) | ||
| 85 | return 0; | ||
| 86 | |||
| 87 | return 1; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * | | /\ Higher addresses | ||
| 92 | * | | | ||
| 93 | * --------------- stack base (address of current_thread_info) | ||
| 94 | * | thread info | | ||
| 95 | * . . | ||
| 96 | * | stack | | ||
| 97 | * --------------- saved regs->ARM_fp value if valid (frame_tail address) | ||
| 98 | * . . | ||
| 99 | * --------------- struct pt_regs stored on stack (struct pt_regs *) | ||
| 100 | * | | | ||
| 101 | * . . | ||
| 102 | * | | | ||
| 103 | * --------------- %esp | ||
| 104 | * | | | ||
| 105 | * | | \/ Lower addresses | ||
| 106 | * | ||
| 107 | * Thus, &pt_regs <-> stack base restricts the valid(ish) fp values | ||
| 108 | */ | ||
| 109 | static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs) | ||
| 110 | { | ||
| 111 | unsigned long tailaddr = (unsigned long)tail; | ||
| 112 | unsigned long stack = (unsigned long)regs; | ||
| 113 | unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE; | ||
| 114 | |||
| 115 | return (tailaddr > stack) && (tailaddr < stack_base); | ||
| 116 | } | ||
| 117 | |||
| 118 | void arm_backtrace(struct pt_regs const *regs, unsigned int depth) | ||
| 119 | { | ||
| 120 | struct frame_tail *tail; | ||
| 121 | unsigned long last_address = 0; | ||
| 122 | |||
| 123 | tail = ((struct frame_tail *) regs->ARM_fp) - 1; | ||
| 124 | |||
| 125 | if (!user_mode(regs)) { | ||
| 126 | |||
| 127 | #ifdef CONFIG_FRAME_POINTER | ||
| 128 | while (depth-- && tail && valid_kernel_stack(tail, regs)) { | ||
| 129 | tail = kernel_backtrace(tail); | ||
| 130 | } | ||
| 131 | #endif | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | |||
| 135 | while (depth-- && tail && !((unsigned long) tail & 3)) { | ||
| 136 | if ((!CMP_ADDR_EQUAL(last_address, tail, 0) | ||
| 137 | || !CMP_ADDR_EQUAL(last_address, tail, 8)) | ||
| 138 | && !pages_present(tail)) | ||
| 139 | return; | ||
| 140 | last_address = (unsigned long) tail; | ||
| 141 | tail = user_backtrace(tail); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
diff --git a/arch/arm/oprofile/init.c b/arch/arm/oprofile/init.c index cce3d3015eb7..d315a3a86c86 100644 --- a/arch/arm/oprofile/init.c +++ b/arch/arm/oprofile/init.c | |||
| @@ -20,6 +20,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
| 20 | ret = pmu_init(ops, &op_xscale_spec); | 20 | ret = pmu_init(ops, &op_xscale_spec); |
| 21 | #endif | 21 | #endif |
| 22 | 22 | ||
| 23 | ops->backtrace = arm_backtrace; | ||
| 24 | |||
| 23 | return ret; | 25 | return ret; |
| 24 | } | 26 | } |
| 25 | 27 | ||
diff --git a/arch/arm/oprofile/op_arm_model.h b/arch/arm/oprofile/op_arm_model.h index 2d4caf4781ad..2148d07484b7 100644 --- a/arch/arm/oprofile/op_arm_model.h +++ b/arch/arm/oprofile/op_arm_model.h | |||
| @@ -24,6 +24,8 @@ struct op_arm_model_spec { | |||
| 24 | extern struct op_arm_model_spec op_xscale_spec; | 24 | extern struct op_arm_model_spec op_xscale_spec; |
| 25 | #endif | 25 | #endif |
| 26 | 26 | ||
| 27 | extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth); | ||
| 28 | |||
| 27 | extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec); | 29 | extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec); |
| 28 | extern void pmu_exit(void); | 30 | extern void pmu_exit(void); |
| 29 | #endif /* OP_ARM_MODEL_H */ | 31 | #endif /* OP_ARM_MODEL_H */ |
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c index 4a17956512e1..6835f6d47c31 100644 --- a/arch/i386/boot/tools/build.c +++ b/arch/i386/boot/tools/build.c | |||
| @@ -70,7 +70,8 @@ void usage(void) | |||
| 70 | 70 | ||
| 71 | int main(int argc, char ** argv) | 71 | int main(int argc, char ** argv) |
| 72 | { | 72 | { |
| 73 | unsigned int i, c, sz, setup_sectors; | 73 | unsigned int i, sz, setup_sectors; |
| 74 | int c; | ||
| 74 | u32 sys_size; | 75 | u32 sys_size; |
| 75 | byte major_root, minor_root; | 76 | byte major_root, minor_root; |
| 76 | struct stat sb; | 77 | struct stat sb; |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 9f63ae0f404b..b7808a89d945 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
| @@ -159,9 +159,15 @@ char *__acpi_map_table(unsigned long phys, unsigned long size) | |||
| 159 | #endif | 159 | #endif |
| 160 | 160 | ||
| 161 | #ifdef CONFIG_PCI_MMCONFIG | 161 | #ifdef CONFIG_PCI_MMCONFIG |
| 162 | static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | 162 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ |
| 163 | struct acpi_table_mcfg_config *pci_mmcfg_config; | ||
| 164 | int pci_mmcfg_config_num; | ||
| 165 | |||
| 166 | int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | ||
| 163 | { | 167 | { |
| 164 | struct acpi_table_mcfg *mcfg; | 168 | struct acpi_table_mcfg *mcfg; |
| 169 | unsigned long i; | ||
| 170 | int config_size; | ||
| 165 | 171 | ||
| 166 | if (!phys_addr || !size) | 172 | if (!phys_addr || !size) |
| 167 | return -EINVAL; | 173 | return -EINVAL; |
| @@ -172,18 +178,38 @@ static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | |||
| 172 | return -ENODEV; | 178 | return -ENODEV; |
| 173 | } | 179 | } |
| 174 | 180 | ||
| 175 | if (mcfg->base_reserved) { | 181 | /* how many config structures do we have */ |
| 176 | printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n"); | 182 | pci_mmcfg_config_num = 0; |
| 183 | i = size - sizeof(struct acpi_table_mcfg); | ||
| 184 | while (i >= sizeof(struct acpi_table_mcfg_config)) { | ||
| 185 | ++pci_mmcfg_config_num; | ||
| 186 | i -= sizeof(struct acpi_table_mcfg_config); | ||
| 187 | }; | ||
| 188 | if (pci_mmcfg_config_num == 0) { | ||
| 189 | printk(KERN_ERR PREFIX "MMCONFIG has no entries\n"); | ||
| 177 | return -ENODEV; | 190 | return -ENODEV; |
| 178 | } | 191 | } |
| 179 | 192 | ||
| 180 | pci_mmcfg_base_addr = mcfg->base_address; | 193 | config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config); |
| 194 | pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL); | ||
| 195 | if (!pci_mmcfg_config) { | ||
| 196 | printk(KERN_WARNING PREFIX | ||
| 197 | "No memory for MCFG config tables\n"); | ||
| 198 | return -ENOMEM; | ||
| 199 | } | ||
| 200 | |||
| 201 | memcpy(pci_mmcfg_config, &mcfg->config, config_size); | ||
| 202 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | ||
| 203 | if (mcfg->config[i].base_reserved) { | ||
| 204 | printk(KERN_ERR PREFIX | ||
| 205 | "MMCONFIG not in low 4GB of memory\n"); | ||
| 206 | return -ENODEV; | ||
| 207 | } | ||
| 208 | } | ||
| 181 | 209 | ||
| 182 | return 0; | 210 | return 0; |
| 183 | } | 211 | } |
| 184 | #else | 212 | #endif /* CONFIG_PCI_MMCONFIG */ |
| 185 | #define acpi_parse_mcfg NULL | ||
| 186 | #endif /* !CONFIG_PCI_MMCONFIG */ | ||
| 187 | 213 | ||
| 188 | #ifdef CONFIG_X86_LOCAL_APIC | 214 | #ifdef CONFIG_X86_LOCAL_APIC |
| 189 | static int __init | 215 | static int __init |
| @@ -507,6 +533,22 @@ acpi_unmap_lsapic(int cpu) | |||
| 507 | EXPORT_SYMBOL(acpi_unmap_lsapic); | 533 | EXPORT_SYMBOL(acpi_unmap_lsapic); |
| 508 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ | 534 | #endif /* CONFIG_ACPI_HOTPLUG_CPU */ |
| 509 | 535 | ||
| 536 | int | ||
| 537 | acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) | ||
| 538 | { | ||
| 539 | /* TBD */ | ||
| 540 | return -EINVAL; | ||
| 541 | } | ||
| 542 | EXPORT_SYMBOL(acpi_register_ioapic); | ||
| 543 | |||
| 544 | int | ||
| 545 | acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base) | ||
| 546 | { | ||
| 547 | /* TBD */ | ||
| 548 | return -EINVAL; | ||
| 549 | } | ||
| 550 | EXPORT_SYMBOL(acpi_unregister_ioapic); | ||
| 551 | |||
| 510 | static unsigned long __init | 552 | static unsigned long __init |
| 511 | acpi_scan_rsdp ( | 553 | acpi_scan_rsdp ( |
| 512 | unsigned long start, | 554 | unsigned long start, |
| @@ -1123,7 +1165,6 @@ int __init acpi_boot_init(void) | |||
| 1123 | acpi_process_madt(); | 1165 | acpi_process_madt(); |
| 1124 | 1166 | ||
| 1125 | acpi_table_parse(ACPI_HPET, acpi_parse_hpet); | 1167 | acpi_table_parse(ACPI_HPET, acpi_parse_hpet); |
| 1126 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
| 1127 | 1168 | ||
| 1128 | return 0; | 1169 | return 0; |
| 1129 | } | 1170 | } |
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 720975e1af50..87325263cd4f 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
| @@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | | |||
| 25 | 25 | ||
| 26 | int pci_routeirq; | 26 | int pci_routeirq; |
| 27 | int pcibios_last_bus = -1; | 27 | int pcibios_last_bus = -1; |
| 28 | struct pci_bus *pci_root_bus = NULL; | 28 | unsigned long pirq_table_addr; |
| 29 | struct pci_bus *pci_root_bus; | ||
| 29 | struct pci_raw_ops *raw_pci_ops; | 30 | struct pci_raw_ops *raw_pci_ops; |
| 30 | 31 | ||
| 31 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) | 32 | static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) |
| @@ -133,7 +134,7 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) | |||
| 133 | 134 | ||
| 134 | printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); | 135 | printk("PCI: Probing PCI hardware (bus %02x)\n", busnum); |
| 135 | 136 | ||
| 136 | return pci_scan_bus(busnum, &pci_root_ops, NULL); | 137 | return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, NULL); |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 139 | extern u8 pci_cache_line_size; | 140 | extern u8 pci_cache_line_size; |
| @@ -188,6 +189,9 @@ char * __devinit pcibios_setup(char *str) | |||
| 188 | } else if (!strcmp(str, "biosirq")) { | 189 | } else if (!strcmp(str, "biosirq")) { |
| 189 | pci_probe |= PCI_BIOS_IRQ_SCAN; | 190 | pci_probe |= PCI_BIOS_IRQ_SCAN; |
| 190 | return NULL; | 191 | return NULL; |
| 192 | } else if (!strncmp(str, "pirqaddr=", 9)) { | ||
| 193 | pirq_table_addr = simple_strtoul(str+9, NULL, 0); | ||
| 194 | return NULL; | ||
| 191 | } | 195 | } |
| 192 | #endif | 196 | #endif |
| 193 | #ifdef CONFIG_PCI_DIRECT | 197 | #ifdef CONFIG_PCI_DIRECT |
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c index 83458f81e661..78ca1ecbb907 100644 --- a/arch/i386/pci/irq.c +++ b/arch/i386/pci/irq.c | |||
| @@ -58,6 +58,35 @@ struct irq_router_handler { | |||
| 58 | int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; | 58 | int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; |
| 59 | 59 | ||
| 60 | /* | 60 | /* |
| 61 | * Check passed address for the PCI IRQ Routing Table signature | ||
| 62 | * and perform checksum verification. | ||
| 63 | */ | ||
| 64 | |||
| 65 | static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr) | ||
| 66 | { | ||
| 67 | struct irq_routing_table *rt; | ||
| 68 | int i; | ||
| 69 | u8 sum; | ||
| 70 | |||
| 71 | rt = (struct irq_routing_table *) addr; | ||
| 72 | if (rt->signature != PIRQ_SIGNATURE || | ||
| 73 | rt->version != PIRQ_VERSION || | ||
| 74 | rt->size % 16 || | ||
| 75 | rt->size < sizeof(struct irq_routing_table)) | ||
| 76 | return NULL; | ||
| 77 | sum = 0; | ||
| 78 | for (i=0; i < rt->size; i++) | ||
| 79 | sum += addr[i]; | ||
| 80 | if (!sum) { | ||
| 81 | DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt); | ||
| 82 | return rt; | ||
| 83 | } | ||
| 84 | return NULL; | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | |||
| 89 | /* | ||
| 61 | * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. | 90 | * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. |
| 62 | */ | 91 | */ |
| 63 | 92 | ||
| @@ -65,23 +94,17 @@ static struct irq_routing_table * __init pirq_find_routing_table(void) | |||
| 65 | { | 94 | { |
| 66 | u8 *addr; | 95 | u8 *addr; |
| 67 | struct irq_routing_table *rt; | 96 | struct irq_routing_table *rt; |
| 68 | int i; | ||
| 69 | u8 sum; | ||
| 70 | 97 | ||
| 98 | if (pirq_table_addr) { | ||
| 99 | rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr)); | ||
| 100 | if (rt) | ||
| 101 | return rt; | ||
| 102 | printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n"); | ||
| 103 | } | ||
| 71 | for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { | 104 | for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { |
| 72 | rt = (struct irq_routing_table *) addr; | 105 | rt = pirq_check_routing_table(addr); |
| 73 | if (rt->signature != PIRQ_SIGNATURE || | 106 | if (rt) |
| 74 | rt->version != PIRQ_VERSION || | ||
| 75 | rt->size % 16 || | ||
| 76 | rt->size < sizeof(struct irq_routing_table)) | ||
| 77 | continue; | ||
| 78 | sum = 0; | ||
| 79 | for(i=0; i<rt->size; i++) | ||
| 80 | sum += addr[i]; | ||
| 81 | if (!sum) { | ||
| 82 | DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt); | ||
| 83 | return rt; | 107 | return rt; |
| 84 | } | ||
| 85 | } | 108 | } |
| 86 | return NULL; | 109 | return NULL; |
| 87 | } | 110 | } |
diff --git a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c index 1492e3753869..149a9588c256 100644 --- a/arch/i386/pci/legacy.c +++ b/arch/i386/pci/legacy.c | |||
| @@ -45,6 +45,8 @@ static int __init pci_legacy_init(void) | |||
| 45 | 45 | ||
| 46 | printk("PCI: Probing PCI hardware\n"); | 46 | printk("PCI: Probing PCI hardware\n"); |
| 47 | pci_root_bus = pcibios_scan_root(0); | 47 | pci_root_bus = pcibios_scan_root(0); |
| 48 | if (pci_root_bus) | ||
| 49 | pci_bus_add_devices(pci_root_bus); | ||
| 48 | 50 | ||
| 49 | pcibios_fixup_peer_bridges(); | 51 | pcibios_fixup_peer_bridges(); |
| 50 | 52 | ||
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 021a50aa51f4..60f0e7a1162a 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
| @@ -11,11 +11,9 @@ | |||
| 11 | 11 | ||
| 12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/acpi.h> | ||
| 14 | #include "pci.h" | 15 | #include "pci.h" |
| 15 | 16 | ||
| 16 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | ||
| 17 | u32 pci_mmcfg_base_addr; | ||
| 18 | |||
| 19 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | 17 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
| 20 | 18 | ||
| 21 | /* The base address of the last MMCONFIG device accessed */ | 19 | /* The base address of the last MMCONFIG device accessed */ |
| @@ -24,10 +22,31 @@ static u32 mmcfg_last_accessed_device; | |||
| 24 | /* | 22 | /* |
| 25 | * Functions for accessing PCI configuration space with MMCONFIG accesses | 23 | * Functions for accessing PCI configuration space with MMCONFIG accesses |
| 26 | */ | 24 | */ |
| 25 | static u32 get_base_addr(unsigned int seg, int bus) | ||
| 26 | { | ||
| 27 | int cfg_num = -1; | ||
| 28 | struct acpi_table_mcfg_config *cfg; | ||
| 29 | |||
| 30 | while (1) { | ||
| 31 | ++cfg_num; | ||
| 32 | if (cfg_num >= pci_mmcfg_config_num) { | ||
| 33 | /* something bad is going on, no cfg table is found. */ | ||
| 34 | /* so we fall back to the old way we used to do this */ | ||
| 35 | /* and just rely on the first entry to be correct. */ | ||
| 36 | return pci_mmcfg_config[0].base_address; | ||
| 37 | } | ||
| 38 | cfg = &pci_mmcfg_config[cfg_num]; | ||
| 39 | if (cfg->pci_segment_group_number != seg) | ||
| 40 | continue; | ||
| 41 | if ((cfg->start_bus_number <= bus) && | ||
| 42 | (cfg->end_bus_number >= bus)) | ||
| 43 | return cfg->base_address; | ||
| 44 | } | ||
| 45 | } | ||
| 27 | 46 | ||
| 28 | static inline void pci_exp_set_dev_base(int bus, int devfn) | 47 | static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn) |
| 29 | { | 48 | { |
| 30 | u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12); | 49 | u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12); |
| 31 | if (dev_base != mmcfg_last_accessed_device) { | 50 | if (dev_base != mmcfg_last_accessed_device) { |
| 32 | mmcfg_last_accessed_device = dev_base; | 51 | mmcfg_last_accessed_device = dev_base; |
| 33 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); | 52 | set_fixmap_nocache(FIX_PCIE_MCFG, dev_base); |
| @@ -44,7 +63,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
| 44 | 63 | ||
| 45 | spin_lock_irqsave(&pci_config_lock, flags); | 64 | spin_lock_irqsave(&pci_config_lock, flags); |
| 46 | 65 | ||
| 47 | pci_exp_set_dev_base(bus, devfn); | 66 | pci_exp_set_dev_base(seg, bus, devfn); |
| 48 | 67 | ||
| 49 | switch (len) { | 68 | switch (len) { |
| 50 | case 1: | 69 | case 1: |
| @@ -73,7 +92,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | |||
| 73 | 92 | ||
| 74 | spin_lock_irqsave(&pci_config_lock, flags); | 93 | spin_lock_irqsave(&pci_config_lock, flags); |
| 75 | 94 | ||
| 76 | pci_exp_set_dev_base(bus, devfn); | 95 | pci_exp_set_dev_base(seg, bus, devfn); |
| 77 | 96 | ||
| 78 | switch (len) { | 97 | switch (len) { |
| 79 | case 1: | 98 | case 1: |
| @@ -101,7 +120,11 @@ static int __init pci_mmcfg_init(void) | |||
| 101 | { | 120 | { |
| 102 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 121 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
| 103 | goto out; | 122 | goto out; |
| 104 | if (!pci_mmcfg_base_addr) | 123 | |
| 124 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
| 125 | if ((pci_mmcfg_config_num == 0) || | ||
| 126 | (pci_mmcfg_config == NULL) || | ||
| 127 | (pci_mmcfg_config[0].base_address == 0)) | ||
| 105 | goto out; | 128 | goto out; |
| 106 | 129 | ||
| 107 | /* Kludge for now. Don't use mmconfig on AMD systems because | 130 | /* Kludge for now. Don't use mmconfig on AMD systems because |
diff --git a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c index 9e3695461899..adbe17a38f6f 100644 --- a/arch/i386/pci/numa.c +++ b/arch/i386/pci/numa.c | |||
| @@ -115,6 +115,8 @@ static int __init pci_numa_init(void) | |||
| 115 | return 0; | 115 | return 0; |
| 116 | 116 | ||
| 117 | pci_root_bus = pcibios_scan_root(0); | 117 | pci_root_bus = pcibios_scan_root(0); |
| 118 | if (pci_root_bus) | ||
| 119 | pci_bus_add_devices(pci_root_bus); | ||
| 118 | if (num_online_nodes() > 1) | 120 | if (num_online_nodes() > 1) |
| 119 | for_each_online_node(quad) { | 121 | for_each_online_node(quad) { |
| 120 | if (quad == 0) | 122 | if (quad == 0) |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index a8fc80ca69f3..a80f0f55ff51 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 | 27 | #define PCI_ASSIGN_ALL_BUSSES 0x4000 |
| 28 | 28 | ||
| 29 | extern unsigned int pci_probe; | 29 | extern unsigned int pci_probe; |
| 30 | extern unsigned long pirq_table_addr; | ||
| 30 | 31 | ||
| 31 | /* pci-i386.c */ | 32 | /* pci-i386.c */ |
| 32 | 33 | ||
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 72dfd9e7de0f..cda06f88c66e 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
| @@ -236,9 +236,7 @@ acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end) | |||
| 236 | if (BAD_MADT_ENTRY(iosapic, end)) | 236 | if (BAD_MADT_ENTRY(iosapic, end)) |
| 237 | return -EINVAL; | 237 | return -EINVAL; |
| 238 | 238 | ||
| 239 | iosapic_init(iosapic->address, iosapic->global_irq_base); | 239 | return iosapic_init(iosapic->address, iosapic->global_irq_base); |
| 240 | |||
| 241 | return 0; | ||
| 242 | } | 240 | } |
| 243 | 241 | ||
| 244 | 242 | ||
| @@ -772,7 +770,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic); | |||
| 772 | 770 | ||
| 773 | 771 | ||
| 774 | #ifdef CONFIG_ACPI_NUMA | 772 | #ifdef CONFIG_ACPI_NUMA |
| 775 | acpi_status __init | 773 | acpi_status __devinit |
| 776 | acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) | 774 | acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) |
| 777 | { | 775 | { |
| 778 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 776 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
| @@ -825,4 +823,28 @@ acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret) | |||
| 825 | return AE_OK; | 823 | return AE_OK; |
| 826 | } | 824 | } |
| 827 | #endif /* CONFIG_NUMA */ | 825 | #endif /* CONFIG_NUMA */ |
| 826 | |||
| 827 | int | ||
| 828 | acpi_register_ioapic (acpi_handle handle, u64 phys_addr, u32 gsi_base) | ||
| 829 | { | ||
| 830 | int err; | ||
| 831 | |||
| 832 | if ((err = iosapic_init(phys_addr, gsi_base))) | ||
| 833 | return err; | ||
| 834 | |||
| 835 | #if CONFIG_ACPI_NUMA | ||
| 836 | acpi_map_iosapic(handle, 0, NULL, NULL); | ||
| 837 | #endif /* CONFIG_ACPI_NUMA */ | ||
| 838 | |||
| 839 | return 0; | ||
| 840 | } | ||
| 841 | EXPORT_SYMBOL(acpi_register_ioapic); | ||
| 842 | |||
| 843 | int | ||
| 844 | acpi_unregister_ioapic (acpi_handle handle, u32 gsi_base) | ||
| 845 | { | ||
| 846 | return iosapic_remove(gsi_base); | ||
| 847 | } | ||
| 848 | EXPORT_SYMBOL(acpi_unregister_ioapic); | ||
| 849 | |||
| 828 | #endif /* CONFIG_ACPI_BOOT */ | 850 | #endif /* CONFIG_ACPI_BOOT */ |
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c index 88b014381df5..c170be095ccd 100644 --- a/arch/ia64/kernel/iosapic.c +++ b/arch/ia64/kernel/iosapic.c | |||
| @@ -129,14 +129,13 @@ static struct iosapic { | |||
| 129 | char __iomem *addr; /* base address of IOSAPIC */ | 129 | char __iomem *addr; /* base address of IOSAPIC */ |
| 130 | unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ | 130 | unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ |
| 131 | unsigned short num_rte; /* number of RTE in this IOSAPIC */ | 131 | unsigned short num_rte; /* number of RTE in this IOSAPIC */ |
| 132 | int rtes_inuse; /* # of RTEs in use on this IOSAPIC */ | ||
| 132 | #ifdef CONFIG_NUMA | 133 | #ifdef CONFIG_NUMA |
| 133 | unsigned short node; /* numa node association via pxm */ | 134 | unsigned short node; /* numa node association via pxm */ |
| 134 | #endif | 135 | #endif |
| 135 | } iosapic_lists[NR_IOSAPICS]; | 136 | } iosapic_lists[NR_IOSAPICS]; |
| 136 | 137 | ||
| 137 | static int num_iosapic; | 138 | static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */ |
| 138 | |||
| 139 | static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */ | ||
| 140 | 139 | ||
| 141 | static int iosapic_kmalloc_ok; | 140 | static int iosapic_kmalloc_ok; |
| 142 | static LIST_HEAD(free_rte_list); | 141 | static LIST_HEAD(free_rte_list); |
| @@ -149,7 +148,7 @@ find_iosapic (unsigned int gsi) | |||
| 149 | { | 148 | { |
| 150 | int i; | 149 | int i; |
| 151 | 150 | ||
| 152 | for (i = 0; i < num_iosapic; i++) { | 151 | for (i = 0; i < NR_IOSAPICS; i++) { |
| 153 | if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte) | 152 | if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte) |
| 154 | return i; | 153 | return i; |
| 155 | } | 154 | } |
| @@ -598,6 +597,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery, | |||
| 598 | rte->refcnt++; | 597 | rte->refcnt++; |
| 599 | list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes); | 598 | list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes); |
| 600 | iosapic_intr_info[vector].count++; | 599 | iosapic_intr_info[vector].count++; |
| 600 | iosapic_lists[index].rtes_inuse++; | ||
| 601 | } | 601 | } |
| 602 | else if (vector_is_shared(vector)) { | 602 | else if (vector_is_shared(vector)) { |
| 603 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; | 603 | struct iosapic_intr_info *info = &iosapic_intr_info[vector]; |
| @@ -778,7 +778,7 @@ void | |||
| 778 | iosapic_unregister_intr (unsigned int gsi) | 778 | iosapic_unregister_intr (unsigned int gsi) |
| 779 | { | 779 | { |
| 780 | unsigned long flags; | 780 | unsigned long flags; |
| 781 | int irq, vector; | 781 | int irq, vector, index; |
| 782 | irq_desc_t *idesc; | 782 | irq_desc_t *idesc; |
| 783 | u32 low32; | 783 | u32 low32; |
| 784 | unsigned long trigger, polarity; | 784 | unsigned long trigger, polarity; |
| @@ -819,6 +819,9 @@ iosapic_unregister_intr (unsigned int gsi) | |||
| 819 | list_del(&rte->rte_list); | 819 | list_del(&rte->rte_list); |
| 820 | iosapic_intr_info[vector].count--; | 820 | iosapic_intr_info[vector].count--; |
| 821 | iosapic_free_rte(rte); | 821 | iosapic_free_rte(rte); |
| 822 | index = find_iosapic(gsi); | ||
| 823 | iosapic_lists[index].rtes_inuse--; | ||
| 824 | WARN_ON(iosapic_lists[index].rtes_inuse < 0); | ||
| 822 | 825 | ||
| 823 | trigger = iosapic_intr_info[vector].trigger; | 826 | trigger = iosapic_intr_info[vector].trigger; |
| 824 | polarity = iosapic_intr_info[vector].polarity; | 827 | polarity = iosapic_intr_info[vector].polarity; |
| @@ -952,30 +955,86 @@ iosapic_system_init (int system_pcat_compat) | |||
| 952 | } | 955 | } |
| 953 | } | 956 | } |
| 954 | 957 | ||
| 955 | void __init | 958 | static inline int |
| 959 | iosapic_alloc (void) | ||
| 960 | { | ||
| 961 | int index; | ||
| 962 | |||
| 963 | for (index = 0; index < NR_IOSAPICS; index++) | ||
| 964 | if (!iosapic_lists[index].addr) | ||
| 965 | return index; | ||
| 966 | |||
| 967 | printk(KERN_WARNING "%s: failed to allocate iosapic\n", __FUNCTION__); | ||
| 968 | return -1; | ||
| 969 | } | ||
| 970 | |||
| 971 | static inline void | ||
| 972 | iosapic_free (int index) | ||
| 973 | { | ||
| 974 | memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0])); | ||
| 975 | } | ||
| 976 | |||
| 977 | static inline int | ||
| 978 | iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver) | ||
| 979 | { | ||
| 980 | int index; | ||
| 981 | unsigned int gsi_end, base, end; | ||
| 982 | |||
| 983 | /* check gsi range */ | ||
| 984 | gsi_end = gsi_base + ((ver >> 16) & 0xff); | ||
| 985 | for (index = 0; index < NR_IOSAPICS; index++) { | ||
| 986 | if (!iosapic_lists[index].addr) | ||
| 987 | continue; | ||
| 988 | |||
| 989 | base = iosapic_lists[index].gsi_base; | ||
| 990 | end = base + iosapic_lists[index].num_rte - 1; | ||
| 991 | |||
| 992 | if (gsi_base < base && gsi_end < base) | ||
| 993 | continue;/* OK */ | ||
| 994 | |||
| 995 | if (gsi_base > end && gsi_end > end) | ||
| 996 | continue; /* OK */ | ||
| 997 | |||
| 998 | return -EBUSY; | ||
| 999 | } | ||
| 1000 | return 0; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | int __devinit | ||
| 956 | iosapic_init (unsigned long phys_addr, unsigned int gsi_base) | 1004 | iosapic_init (unsigned long phys_addr, unsigned int gsi_base) |
| 957 | { | 1005 | { |
| 958 | int num_rte; | 1006 | int num_rte, err, index; |
| 959 | unsigned int isa_irq, ver; | 1007 | unsigned int isa_irq, ver; |
| 960 | char __iomem *addr; | 1008 | char __iomem *addr; |
| 1009 | unsigned long flags; | ||
| 1010 | |||
| 1011 | spin_lock_irqsave(&iosapic_lock, flags); | ||
| 1012 | { | ||
| 1013 | addr = ioremap(phys_addr, 0); | ||
| 1014 | ver = iosapic_version(addr); | ||
| 961 | 1015 | ||
| 962 | addr = ioremap(phys_addr, 0); | 1016 | if ((err = iosapic_check_gsi_range(gsi_base, ver))) { |
| 963 | ver = iosapic_version(addr); | 1017 | iounmap(addr); |
| 1018 | spin_unlock_irqrestore(&iosapic_lock, flags); | ||
| 1019 | return err; | ||
| 1020 | } | ||
| 964 | 1021 | ||
| 965 | /* | 1022 | /* |
| 966 | * The MAX_REDIR register holds the highest input pin | 1023 | * The MAX_REDIR register holds the highest input pin |
| 967 | * number (starting from 0). | 1024 | * number (starting from 0). |
| 968 | * We add 1 so that we can use it for number of pins (= RTEs) | 1025 | * We add 1 so that we can use it for number of pins (= RTEs) |
| 969 | */ | 1026 | */ |
| 970 | num_rte = ((ver >> 16) & 0xff) + 1; | 1027 | num_rte = ((ver >> 16) & 0xff) + 1; |
| 971 | 1028 | ||
| 972 | iosapic_lists[num_iosapic].addr = addr; | 1029 | index = iosapic_alloc(); |
| 973 | iosapic_lists[num_iosapic].gsi_base = gsi_base; | 1030 | iosapic_lists[index].addr = addr; |
| 974 | iosapic_lists[num_iosapic].num_rte = num_rte; | 1031 | iosapic_lists[index].gsi_base = gsi_base; |
| 1032 | iosapic_lists[index].num_rte = num_rte; | ||
| 975 | #ifdef CONFIG_NUMA | 1033 | #ifdef CONFIG_NUMA |
| 976 | iosapic_lists[num_iosapic].node = MAX_NUMNODES; | 1034 | iosapic_lists[index].node = MAX_NUMNODES; |
| 977 | #endif | 1035 | #endif |
| 978 | num_iosapic++; | 1036 | } |
| 1037 | spin_unlock_irqrestore(&iosapic_lock, flags); | ||
| 979 | 1038 | ||
| 980 | if ((gsi_base == 0) && pcat_compat) { | 1039 | if ((gsi_base == 0) && pcat_compat) { |
| 981 | /* | 1040 | /* |
| @@ -986,10 +1045,43 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base) | |||
| 986 | for (isa_irq = 0; isa_irq < 16; ++isa_irq) | 1045 | for (isa_irq = 0; isa_irq < 16; ++isa_irq) |
| 987 | iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); | 1046 | iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); |
| 988 | } | 1047 | } |
| 1048 | return 0; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | #ifdef CONFIG_HOTPLUG | ||
| 1052 | int | ||
| 1053 | iosapic_remove (unsigned int gsi_base) | ||
| 1054 | { | ||
| 1055 | int index, err = 0; | ||
| 1056 | unsigned long flags; | ||
| 1057 | |||
| 1058 | spin_lock_irqsave(&iosapic_lock, flags); | ||
| 1059 | { | ||
| 1060 | index = find_iosapic(gsi_base); | ||
| 1061 | if (index < 0) { | ||
| 1062 | printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n", | ||
| 1063 | __FUNCTION__, gsi_base); | ||
| 1064 | goto out; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | if (iosapic_lists[index].rtes_inuse) { | ||
| 1068 | err = -EBUSY; | ||
| 1069 | printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n", | ||
| 1070 | __FUNCTION__, gsi_base); | ||
| 1071 | goto out; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | iounmap(iosapic_lists[index].addr); | ||
| 1075 | iosapic_free(index); | ||
| 1076 | } | ||
| 1077 | out: | ||
| 1078 | spin_unlock_irqrestore(&iosapic_lock, flags); | ||
| 1079 | return err; | ||
| 989 | } | 1080 | } |
| 1081 | #endif /* CONFIG_HOTPLUG */ | ||
| 990 | 1082 | ||
| 991 | #ifdef CONFIG_NUMA | 1083 | #ifdef CONFIG_NUMA |
| 992 | void __init | 1084 | void __devinit |
| 993 | map_iosapic_to_node(unsigned int gsi_base, int node) | 1085 | map_iosapic_to_node(unsigned int gsi_base, int node) |
| 994 | { | 1086 | { |
| 995 | int index; | 1087 | int index; |
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index e3fc4edea113..720a861f88be 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
| @@ -312,7 +312,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus) | |||
| 312 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, | 312 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, |
| 313 | &info); | 313 | &info); |
| 314 | 314 | ||
| 315 | pbus = pci_scan_bus(bus, &pci_root_ops, controller); | 315 | pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller); |
| 316 | if (pbus) | 316 | if (pbus) |
| 317 | pcibios_setup_root_windows(pbus, controller); | 317 | pcibios_setup_root_windows(pbus, controller); |
| 318 | 318 | ||
| @@ -373,6 +373,25 @@ void pcibios_bus_to_resource(struct pci_dev *dev, | |||
| 373 | res->end = region->end + offset; | 373 | res->end = region->end + offset; |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | static int __devinit is_valid_resource(struct pci_dev *dev, int idx) | ||
| 377 | { | ||
| 378 | unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; | ||
| 379 | struct resource *devr = &dev->resource[idx]; | ||
| 380 | |||
| 381 | if (!dev->bus) | ||
| 382 | return 0; | ||
| 383 | for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) { | ||
| 384 | struct resource *busr = dev->bus->resource[i]; | ||
| 385 | |||
| 386 | if (!busr || ((busr->flags ^ devr->flags) & type_mask)) | ||
| 387 | continue; | ||
| 388 | if ((devr->start) && (devr->start >= busr->start) && | ||
| 389 | (devr->end <= busr->end)) | ||
| 390 | return 1; | ||
| 391 | } | ||
| 392 | return 0; | ||
| 393 | } | ||
| 394 | |||
| 376 | static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) | 395 | static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) |
| 377 | { | 396 | { |
| 378 | struct pci_bus_region region; | 397 | struct pci_bus_region region; |
| @@ -386,7 +405,8 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) | |||
| 386 | region.start = dev->resource[i].start; | 405 | region.start = dev->resource[i].start; |
| 387 | region.end = dev->resource[i].end; | 406 | region.end = dev->resource[i].end; |
| 388 | pcibios_bus_to_resource(dev, &dev->resource[i], ®ion); | 407 | pcibios_bus_to_resource(dev, &dev->resource[i], ®ion); |
| 389 | pci_claim_resource(dev, i); | 408 | if ((is_valid_resource(dev, i))) |
| 409 | pci_claim_resource(dev, i); | ||
| 390 | } | 410 | } |
| 391 | } | 411 | } |
| 392 | 412 | ||
| @@ -398,6 +418,10 @@ pcibios_fixup_bus (struct pci_bus *b) | |||
| 398 | { | 418 | { |
| 399 | struct pci_dev *dev; | 419 | struct pci_dev *dev; |
| 400 | 420 | ||
| 421 | if (b->self) { | ||
| 422 | pci_read_bridge_bases(b); | ||
| 423 | pcibios_fixup_device_resources(b->self); | ||
| 424 | } | ||
| 401 | list_for_each_entry(dev, &b->devices, bus_list) | 425 | list_for_each_entry(dev, &b->devices, bus_list) |
| 402 | pcibios_fixup_device_resources(dev); | 426 | pcibios_fixup_device_resources(dev); |
| 403 | 427 | ||
| @@ -418,18 +442,24 @@ pcibios_enable_resources (struct pci_dev *dev, int mask) | |||
| 418 | u16 cmd, old_cmd; | 442 | u16 cmd, old_cmd; |
| 419 | int idx; | 443 | int idx; |
| 420 | struct resource *r; | 444 | struct resource *r; |
| 445 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | ||
| 421 | 446 | ||
| 422 | if (!dev) | 447 | if (!dev) |
| 423 | return -EINVAL; | 448 | return -EINVAL; |
| 424 | 449 | ||
| 425 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | 450 | pci_read_config_word(dev, PCI_COMMAND, &cmd); |
| 426 | old_cmd = cmd; | 451 | old_cmd = cmd; |
| 427 | for (idx=0; idx<6; idx++) { | 452 | for (idx=0; idx<PCI_NUM_RESOURCES; idx++) { |
| 428 | /* Only set up the desired resources. */ | 453 | /* Only set up the desired resources. */ |
| 429 | if (!(mask & (1 << idx))) | 454 | if (!(mask & (1 << idx))) |
| 430 | continue; | 455 | continue; |
| 431 | 456 | ||
| 432 | r = &dev->resource[idx]; | 457 | r = &dev->resource[idx]; |
| 458 | if (!(r->flags & type_mask)) | ||
| 459 | continue; | ||
| 460 | if ((idx == PCI_ROM_RESOURCE) && | ||
| 461 | (!(r->flags & IORESOURCE_ROM_ENABLE))) | ||
| 462 | continue; | ||
| 433 | if (!r->start && r->end) { | 463 | if (!r->start && r->end) { |
| 434 | printk(KERN_ERR | 464 | printk(KERN_ERR |
| 435 | "PCI: Device %s not available because of resource collisions\n", | 465 | "PCI: Device %s not available because of resource collisions\n", |
| @@ -441,8 +471,6 @@ pcibios_enable_resources (struct pci_dev *dev, int mask) | |||
| 441 | if (r->flags & IORESOURCE_MEM) | 471 | if (r->flags & IORESOURCE_MEM) |
| 442 | cmd |= PCI_COMMAND_MEMORY; | 472 | cmd |= PCI_COMMAND_MEMORY; |
| 443 | } | 473 | } |
| 444 | if (dev->resource[PCI_ROM_RESOURCE].start) | ||
| 445 | cmd |= PCI_COMMAND_MEMORY; | ||
| 446 | if (cmd != old_cmd) { | 474 | if (cmd != old_cmd) { |
| 447 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); | 475 | printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); |
| 448 | pci_write_config_word(dev, PCI_COMMAND, cmd); | 476 | pci_write_config_word(dev, PCI_COMMAND, cmd); |
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 6d7b92d72458..70cfb6ffd877 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c | |||
| @@ -1495,7 +1495,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | |||
| 1495 | *offset += hose->pci_mem_offset; | 1495 | *offset += hose->pci_mem_offset; |
| 1496 | res_bit = IORESOURCE_MEM; | 1496 | res_bit = IORESOURCE_MEM; |
| 1497 | } else { | 1497 | } else { |
| 1498 | io_offset = (unsigned long)hose->io_base_virt; | 1498 | io_offset = hose->io_base_virt - ___IO_BASE; |
| 1499 | *offset += io_offset; | 1499 | *offset += io_offset; |
| 1500 | res_bit = IORESOURCE_IO; | 1500 | res_bit = IORESOURCE_IO; |
| 1501 | } | 1501 | } |
| @@ -1522,7 +1522,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | |||
| 1522 | 1522 | ||
| 1523 | /* found it! construct the final physical address */ | 1523 | /* found it! construct the final physical address */ |
| 1524 | if (mmap_state == pci_mmap_io) | 1524 | if (mmap_state == pci_mmap_io) |
| 1525 | *offset += hose->io_base_phys - _IO_BASE; | 1525 | *offset += hose->io_base_phys - io_offset; |
| 1526 | return rp; | 1526 | return rp; |
| 1527 | } | 1527 | } |
| 1528 | 1528 | ||
| @@ -1739,6 +1739,23 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
| 1739 | return result; | 1739 | return result; |
| 1740 | } | 1740 | } |
| 1741 | 1741 | ||
| 1742 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
| 1743 | const struct resource *rsrc, | ||
| 1744 | u64 *start, u64 *end) | ||
| 1745 | { | ||
| 1746 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
| 1747 | unsigned long offset = 0; | ||
| 1748 | |||
| 1749 | if (hose == NULL) | ||
| 1750 | return; | ||
| 1751 | |||
| 1752 | if (rsrc->flags & IORESOURCE_IO) | ||
| 1753 | offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys; | ||
| 1754 | |||
| 1755 | *start = rsrc->start + offset; | ||
| 1756 | *end = rsrc->end + offset; | ||
| 1757 | } | ||
| 1758 | |||
| 1742 | void __init | 1759 | void __init |
| 1743 | pci_init_resource(struct resource *res, unsigned long start, unsigned long end, | 1760 | pci_init_resource(struct resource *res, unsigned long start, unsigned long end, |
| 1744 | int flags, char *name) | 1761 | int flags, char *name) |
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c index 3defc8c33adf..ffe300611f00 100644 --- a/arch/ppc64/kernel/irq.c +++ b/arch/ppc64/kernel/irq.c | |||
| @@ -245,7 +245,7 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) | |||
| 245 | 245 | ||
| 246 | spin_lock(&desc->lock); | 246 | spin_lock(&desc->lock); |
| 247 | if (!noirqdebug) | 247 | if (!noirqdebug) |
| 248 | note_interrupt(irq, desc, action_ret); | 248 | note_interrupt(irq, desc, action_ret, regs); |
| 249 | if (likely(!(desc->status & IRQ_PENDING))) | 249 | if (likely(!(desc->status & IRQ_PENDING))) |
| 250 | break; | 250 | break; |
| 251 | desc->status &= ~IRQ_PENDING; | 251 | desc->status &= ~IRQ_PENDING; |
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 580676f87d23..ae6f579d3fa0 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
| @@ -351,7 +351,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | |||
| 351 | *offset += hose->pci_mem_offset; | 351 | *offset += hose->pci_mem_offset; |
| 352 | res_bit = IORESOURCE_MEM; | 352 | res_bit = IORESOURCE_MEM; |
| 353 | } else { | 353 | } else { |
| 354 | io_offset = (unsigned long)hose->io_base_virt; | 354 | io_offset = (unsigned long)hose->io_base_virt - pci_io_base; |
| 355 | *offset += io_offset; | 355 | *offset += io_offset; |
| 356 | res_bit = IORESOURCE_IO; | 356 | res_bit = IORESOURCE_IO; |
| 357 | } | 357 | } |
| @@ -378,7 +378,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev, | |||
| 378 | 378 | ||
| 379 | /* found it! construct the final physical address */ | 379 | /* found it! construct the final physical address */ |
| 380 | if (mmap_state == pci_mmap_io) | 380 | if (mmap_state == pci_mmap_io) |
| 381 | *offset += hose->io_base_phys - io_offset; | 381 | *offset += hose->io_base_phys - io_offset; |
| 382 | return rp; | 382 | return rp; |
| 383 | } | 383 | } |
| 384 | 384 | ||
| @@ -944,4 +944,22 @@ int pci_read_irq_line(struct pci_dev *pci_dev) | |||
| 944 | } | 944 | } |
| 945 | EXPORT_SYMBOL(pci_read_irq_line); | 945 | EXPORT_SYMBOL(pci_read_irq_line); |
| 946 | 946 | ||
| 947 | void pci_resource_to_user(const struct pci_dev *dev, int bar, | ||
| 948 | const struct resource *rsrc, | ||
| 949 | u64 *start, u64 *end) | ||
| 950 | { | ||
| 951 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
| 952 | unsigned long offset = 0; | ||
| 953 | |||
| 954 | if (hose == NULL) | ||
| 955 | return; | ||
| 956 | |||
| 957 | if (rsrc->flags & IORESOURCE_IO) | ||
| 958 | offset = pci_io_base - (unsigned long)hose->io_base_virt + | ||
| 959 | hose->io_base_phys; | ||
| 960 | |||
| 961 | *start = rsrc->start + offset; | ||
| 962 | *end = rsrc->end + offset; | ||
| 963 | } | ||
| 964 | |||
| 947 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 965 | #endif /* CONFIG_PPC_MULTIPLATFORM */ |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 262e13d086fe..7a117ef473c5 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
| @@ -270,66 +270,10 @@ endmenu | |||
| 270 | 270 | ||
| 271 | source "drivers/Kconfig" | 271 | source "drivers/Kconfig" |
| 272 | 272 | ||
| 273 | config PRINTER | ||
| 274 | tristate "Parallel printer support" | ||
| 275 | depends on PARPORT | ||
| 276 | ---help--- | ||
| 277 | If you intend to attach a printer to the parallel port of your Linux | ||
| 278 | box (as opposed to using a serial printer; if the connector at the | ||
| 279 | printer has 9 or 25 holes ["female"], then it's serial), say Y. | ||
| 280 | Also read the Printing-HOWTO, available from | ||
| 281 | <http://www.tldp.org/docs.html#howto>. | ||
| 282 | |||
| 283 | It is possible to share one parallel port among several devices | ||
| 284 | (e.g. printer and ZIP drive) and it is safe to compile the | ||
| 285 | corresponding drivers into the kernel. If you want to compile this | ||
| 286 | driver as a module however, choose M here and read | ||
| 287 | <file:Documentation/parport.txt>. The module will be called lp. | ||
| 288 | |||
| 289 | If you have several parallel ports, you can specify which ports to | ||
| 290 | use with the "lp" kernel command line option. (Try "man bootparam" | ||
| 291 | or see the documentation of your boot loader (silo) about how to pass | ||
| 292 | options to the kernel at boot time.) The syntax of the "lp" command | ||
| 293 | line option can be found in <file:drivers/char/lp.c>. | ||
| 294 | |||
| 295 | If you have more than 8 printers, you need to increase the LP_NO | ||
| 296 | macro in lp.c and the PARPORT_MAX macro in parport.h. | ||
| 297 | |||
| 298 | source "mm/Kconfig" | ||
| 299 | |||
| 300 | endmenu | ||
| 301 | |||
| 302 | source "drivers/base/Kconfig" | ||
| 303 | |||
| 304 | source "drivers/video/Kconfig" | ||
| 305 | |||
| 306 | source "drivers/mtd/Kconfig" | ||
| 307 | |||
| 308 | source "drivers/serial/Kconfig" | ||
| 309 | |||
| 310 | if !SUN4 | 273 | if !SUN4 |
| 311 | source "drivers/sbus/char/Kconfig" | 274 | source "drivers/sbus/char/Kconfig" |
| 312 | endif | 275 | endif |
| 313 | 276 | ||
| 314 | source "drivers/block/Kconfig" | ||
| 315 | |||
| 316 | # Don't frighten a common SBus user | ||
| 317 | if PCI | ||
| 318 | |||
| 319 | source "drivers/ide/Kconfig" | ||
| 320 | |||
| 321 | endif | ||
| 322 | |||
| 323 | source "drivers/isdn/Kconfig" | ||
| 324 | |||
| 325 | source "drivers/scsi/Kconfig" | ||
| 326 | |||
| 327 | source "drivers/fc4/Kconfig" | ||
| 328 | |||
| 329 | source "drivers/md/Kconfig" | ||
| 330 | |||
| 331 | source "net/Kconfig" | ||
| 332 | |||
| 333 | # This one must be before the filesystem configs. -DaveM | 277 | # This one must be before the filesystem configs. -DaveM |
| 334 | 278 | ||
| 335 | menu "Unix98 PTY support" | 279 | menu "Unix98 PTY support" |
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index b693c232fd07..657e88aa0902 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
| @@ -7,25 +7,50 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 10 | #include <linux/acpi.h> | ||
| 10 | #include "pci.h" | 11 | #include "pci.h" |
| 11 | 12 | ||
| 12 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 13 | #define MMCONFIG_APER_SIZE (256*1024*1024) |
| 13 | 14 | ||
| 14 | /* The physical address of the MMCONFIG aperture. Set from ACPI tables. */ | ||
| 15 | u32 pci_mmcfg_base_addr; | ||
| 16 | |||
| 17 | /* Static virtual mapping of the MMCONFIG aperture */ | 15 | /* Static virtual mapping of the MMCONFIG aperture */ |
| 18 | char *pci_mmcfg_virt; | 16 | struct mmcfg_virt { |
| 17 | struct acpi_table_mcfg_config *cfg; | ||
| 18 | char *virt; | ||
| 19 | }; | ||
| 20 | static struct mmcfg_virt *pci_mmcfg_virt; | ||
| 19 | 21 | ||
| 20 | static inline char *pci_dev_base(unsigned int bus, unsigned int devfn) | 22 | static char *get_virt(unsigned int seg, int bus) |
| 21 | { | 23 | { |
| 22 | return pci_mmcfg_virt + ((bus << 20) | (devfn << 12)); | 24 | int cfg_num = -1; |
| 25 | struct acpi_table_mcfg_config *cfg; | ||
| 26 | |||
| 27 | while (1) { | ||
| 28 | ++cfg_num; | ||
| 29 | if (cfg_num >= pci_mmcfg_config_num) { | ||
| 30 | /* something bad is going on, no cfg table is found. */ | ||
| 31 | /* so we fall back to the old way we used to do this */ | ||
| 32 | /* and just rely on the first entry to be correct. */ | ||
| 33 | return pci_mmcfg_virt[0].virt; | ||
| 34 | } | ||
| 35 | cfg = pci_mmcfg_virt[cfg_num].cfg; | ||
| 36 | if (cfg->pci_segment_group_number != seg) | ||
| 37 | continue; | ||
| 38 | if ((cfg->start_bus_number <= bus) && | ||
| 39 | (cfg->end_bus_number >= bus)) | ||
| 40 | return pci_mmcfg_virt[cfg_num].virt; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn) | ||
| 45 | { | ||
| 46 | |||
| 47 | return get_virt(seg, bus) + ((bus << 20) | (devfn << 12)); | ||
| 23 | } | 48 | } |
| 24 | 49 | ||
| 25 | static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | 50 | static int pci_mmcfg_read(unsigned int seg, unsigned int bus, |
| 26 | unsigned int devfn, int reg, int len, u32 *value) | 51 | unsigned int devfn, int reg, int len, u32 *value) |
| 27 | { | 52 | { |
| 28 | char *addr = pci_dev_base(bus, devfn); | 53 | char *addr = pci_dev_base(seg, bus, devfn); |
| 29 | 54 | ||
| 30 | if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) | 55 | if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095))) |
| 31 | return -EINVAL; | 56 | return -EINVAL; |
| @@ -48,7 +73,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus, | |||
| 48 | static int pci_mmcfg_write(unsigned int seg, unsigned int bus, | 73 | static int pci_mmcfg_write(unsigned int seg, unsigned int bus, |
| 49 | unsigned int devfn, int reg, int len, u32 value) | 74 | unsigned int devfn, int reg, int len, u32 value) |
| 50 | { | 75 | { |
| 51 | char *addr = pci_dev_base(bus,devfn); | 76 | char *addr = pci_dev_base(seg, bus, devfn); |
| 52 | 77 | ||
| 53 | if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) | 78 | if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) |
| 54 | return -EINVAL; | 79 | return -EINVAL; |
| @@ -75,9 +100,15 @@ static struct pci_raw_ops pci_mmcfg = { | |||
| 75 | 100 | ||
| 76 | static int __init pci_mmcfg_init(void) | 101 | static int __init pci_mmcfg_init(void) |
| 77 | { | 102 | { |
| 103 | int i; | ||
| 104 | |||
| 78 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) | 105 | if ((pci_probe & PCI_PROBE_MMCONF) == 0) |
| 79 | return 0; | 106 | return 0; |
| 80 | if (!pci_mmcfg_base_addr) | 107 | |
| 108 | acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg); | ||
| 109 | if ((pci_mmcfg_config_num == 0) || | ||
| 110 | (pci_mmcfg_config == NULL) || | ||
| 111 | (pci_mmcfg_config[0].base_address == 0)) | ||
| 81 | return 0; | 112 | return 0; |
| 82 | 113 | ||
| 83 | /* Kludge for now. Don't use mmconfig on AMD systems because | 114 | /* Kludge for now. Don't use mmconfig on AMD systems because |
| @@ -88,13 +119,22 @@ static int __init pci_mmcfg_init(void) | |||
| 88 | return 0; | 119 | return 0; |
| 89 | 120 | ||
| 90 | /* RED-PEN i386 doesn't do _nocache right now */ | 121 | /* RED-PEN i386 doesn't do _nocache right now */ |
| 91 | pci_mmcfg_virt = ioremap_nocache(pci_mmcfg_base_addr, MMCONFIG_APER_SIZE); | 122 | pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); |
| 92 | if (!pci_mmcfg_virt) { | 123 | if (pci_mmcfg_virt == NULL) { |
| 93 | printk("PCI: Cannot map mmconfig aperture\n"); | 124 | printk("PCI: Can not allocate memory for mmconfig structures\n"); |
| 94 | return 0; | 125 | return 0; |
| 95 | } | 126 | } |
| 127 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | ||
| 128 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; | ||
| 129 | pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE); | ||
| 130 | if (!pci_mmcfg_virt[i].virt) { | ||
| 131 | printk("PCI: Cannot map mmconfig aperture for segment %d\n", | ||
| 132 | pci_mmcfg_config[i].pci_segment_group_number); | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address); | ||
| 136 | } | ||
| 96 | 137 | ||
| 97 | printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_base_addr); | ||
| 98 | raw_pci_ops = &pci_mmcfg; | 138 | raw_pci_ops = &pci_mmcfg; |
| 99 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; | 139 | pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; |
| 100 | 140 | ||
