diff options
Diffstat (limited to 'arch/i386')
| -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 |
8 files changed, 130 insertions, 33 deletions
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 | ||
