diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-28 17:59:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-28 17:59:07 -0400 |
commit | adb2705a89e8b41abcf29c0ed86f4ce93ab36734 (patch) | |
tree | 01d772570d58cce24b61874e711fd9f51e2729e7 /arch/i386 | |
parent | f340c0d1a3f40fdcba69cd291530a4debc58748f (diff) | |
parent | 8644d2a42bdba2d513f71c07eaf1b6f9b718b8eb (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
Diffstat (limited to 'arch/i386')
-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 |
7 files changed, 128 insertions, 32 deletions
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 | ||