aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci
diff options
context:
space:
mode:
authorArtem B. Bityuckiy <dedekind@infradead.org>2005-07-06 10:43:18 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-07-06 13:40:38 -0400
commitb3539219c9ea20ebf6a5ea3cc534f423a3607c41 (patch)
treed17c31c0eac0a7290ba5011b59a100fd9e9c9532 /arch/i386/pci
parent6430a8def12edebc1c9c7c2621d33ca0e8653c33 (diff)
parenta18bcb7450840f07a772a45229de4811d930f461 (diff)
Merge with rsync://fileserver/linux
Update to 2.6.12-rc3
Diffstat (limited to 'arch/i386/pci')
-rw-r--r--arch/i386/pci/common.c9
-rw-r--r--arch/i386/pci/i386.c11
-rw-r--r--arch/i386/pci/irq.c51
-rw-r--r--arch/i386/pci/legacy.c2
-rw-r--r--arch/i386/pci/mmconfig.c39
-rw-r--r--arch/i386/pci/numa.c2
-rw-r--r--arch/i386/pci/pci.h1
7 files changed, 88 insertions, 27 deletions
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 720975e1af50..70bcd53451f6 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
26int pci_routeirq; 26int pci_routeirq;
27int pcibios_last_bus = -1; 27int pcibios_last_bus = -1;
28struct pci_bus *pci_root_bus = NULL; 28unsigned long pirq_table_addr;
29struct pci_bus *pci_root_bus;
29struct pci_raw_ops *raw_pci_ops; 30struct pci_raw_ops *raw_pci_ops;
30 31
31static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 32static 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
139extern u8 pci_cache_line_size; 140extern u8 pci_cache_line_size;
@@ -164,6 +165,7 @@ static int __init pcibios_init(void)
164 if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) 165 if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
165 pcibios_sort(); 166 pcibios_sort();
166#endif 167#endif
168 pci_assign_unassigned_resources();
167 return 0; 169 return 0;
168} 170}
169 171
@@ -188,6 +190,9 @@ char * __devinit pcibios_setup(char *str)
188 } else if (!strcmp(str, "biosirq")) { 190 } else if (!strcmp(str, "biosirq")) {
189 pci_probe |= PCI_BIOS_IRQ_SCAN; 191 pci_probe |= PCI_BIOS_IRQ_SCAN;
190 return NULL; 192 return NULL;
193 } else if (!strncmp(str, "pirqaddr=", 9)) {
194 pirq_table_addr = simple_strtoul(str+9, NULL, 0);
195 return NULL;
191 } 196 }
192#endif 197#endif
193#ifdef CONFIG_PCI_DIRECT 198#ifdef CONFIG_PCI_DIRECT
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index c205ea7e233b..93a364c82150 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -106,11 +106,16 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
106 if ((dev = bus->self)) { 106 if ((dev = bus->self)) {
107 for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { 107 for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
108 r = &dev->resource[idx]; 108 r = &dev->resource[idx];
109 if (!r->start) 109 if (!r->flags)
110 continue; 110 continue;
111 pr = pci_find_parent_resource(dev, r); 111 pr = pci_find_parent_resource(dev, r);
112 if (!pr || request_resource(pr, r) < 0) 112 if (!r->start || !pr || request_resource(pr, r) < 0) {
113 printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev)); 113 printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
114 /* Something is wrong with the region.
115 Invalidate the resource to prevent child
116 resource allocations in this range. */
117 r->flags = 0;
118 }
114 } 119 }
115 } 120 }
116 pcibios_allocate_bus_resources(&bus->children); 121 pcibios_allocate_bus_resources(&bus->children);
@@ -227,7 +232,7 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
227 232
228 pci_read_config_word(dev, PCI_COMMAND, &cmd); 233 pci_read_config_word(dev, PCI_COMMAND, &cmd);
229 old_cmd = cmd; 234 old_cmd = cmd;
230 for(idx=0; idx<6; idx++) { 235 for(idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
231 /* Only set up the requested stuff */ 236 /* Only set up the requested stuff */
232 if (!(mask & (1<<idx))) 237 if (!(mask & (1<<idx)))
233 continue; 238 continue;
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 {
58int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 58int (*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
65static 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. */
17u32 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 */
25static 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
28static inline void pci_exp_set_dev_base(int bus, int devfn) 47static 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
29extern unsigned int pci_probe; 29extern unsigned int pci_probe;
30extern unsigned long pirq_table_addr;
30 31
31/* pci-i386.c */ 32/* pci-i386.c */
32 33