aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/pci
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-08-10 13:46:28 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-10 13:46:28 -0400
commit2f058256cb64e346f4fb4499ff4e0f1c2791a4b4 (patch)
tree91e06602f4d3abb6812ea8c9bc9ba4501e14c84e /arch/i386/pci
parent0274aa2506fd2fe89a58dd6cd64d3b3f7b976af8 (diff)
parent86b3786078d63242d3194ffc58ae8dae1d1bbef3 (diff)
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'arch/i386/pci')
-rw-r--r--arch/i386/pci/acpi.c1
-rw-r--r--arch/i386/pci/common.c15
-rw-r--r--arch/i386/pci/i386.c11
-rw-r--r--arch/i386/pci/irq.c97
-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/pcbios.c4
-rw-r--r--arch/i386/pci/pci.h2
-rw-r--r--arch/i386/pci/visws.c4
10 files changed, 142 insertions, 35 deletions
diff --git a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
index 2db65ec45dc3..42913f43feb0 100644
--- a/arch/i386/pci/acpi.c
+++ b/arch/i386/pci/acpi.c
@@ -30,6 +30,7 @@ static int __init pci_acpi_init(void)
30 acpi_irq_penalty_init(); 30 acpi_irq_penalty_init();
31 pcibios_scanned++; 31 pcibios_scanned++;
32 pcibios_enable_irq = acpi_pci_irq_enable; 32 pcibios_enable_irq = acpi_pci_irq_enable;
33 pcibios_disable_irq = acpi_pci_irq_disable;
33 34
34 if (pci_routeirq) { 35 if (pci_routeirq) {
35 /* 36 /*
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index 720975e1af50..ade5bc57c34c 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
@@ -249,3 +254,9 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
249 254
250 return pcibios_enable_irq(dev); 255 return pcibios_enable_irq(dev);
251} 256}
257
258void pcibios_disable_device (struct pci_dev *dev)
259{
260 if (pcibios_disable_irq)
261 pcibios_disable_irq(dev);
262}
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 da21b1d07c15..86348b68fda1 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -56,6 +56,36 @@ struct irq_router_handler {
56}; 56};
57 57
58int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 58int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
59void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
60
61/*
62 * Check passed address for the PCI IRQ Routing Table signature
63 * and perform checksum verification.
64 */
65
66static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
67{
68 struct irq_routing_table *rt;
69 int i;
70 u8 sum;
71
72 rt = (struct irq_routing_table *) addr;
73 if (rt->signature != PIRQ_SIGNATURE ||
74 rt->version != PIRQ_VERSION ||
75 rt->size % 16 ||
76 rt->size < sizeof(struct irq_routing_table))
77 return NULL;
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;
84 }
85 return NULL;
86}
87
88
59 89
60/* 90/*
61 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table. 91 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
@@ -65,23 +95,17 @@ static struct irq_routing_table * __init pirq_find_routing_table(void)
65{ 95{
66 u8 *addr; 96 u8 *addr;
67 struct irq_routing_table *rt; 97 struct irq_routing_table *rt;
68 int i;
69 u8 sum;
70 98
99 if (pirq_table_addr) {
100 rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
101 if (rt)
102 return rt;
103 printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
104 }
71 for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) { 105 for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
72 rt = (struct irq_routing_table *) addr; 106 rt = pirq_check_routing_table(addr);
73 if (rt->signature != PIRQ_SIGNATURE || 107 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; 108 return rt;
84 }
85 } 109 }
86 return NULL; 110 return NULL;
87} 111}
@@ -227,6 +251,24 @@ static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
227} 251}
228 252
229/* 253/*
254 * The VIA pirq rules are nibble-based, like ALI,
255 * but without the ugly irq number munging.
256 * However, for 82C586, nibble map is different .
257 */
258static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
259{
260 static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
261 return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
262}
263
264static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
265{
266 static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
267 write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
268 return 1;
269}
270
271/*
230 * ITE 8330G pirq rules are nibble-based 272 * ITE 8330G pirq rules are nibble-based
231 * FIXME: pirqmap may be { 1, 0, 3, 2 }, 273 * FIXME: pirqmap may be { 1, 0, 3, 2 },
232 * 2+3 are both mapped to irq 9 on my system 274 * 2+3 are both mapped to irq 9 on my system
@@ -509,9 +551,20 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
509static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) 551static __init int via_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
510{ 552{
511 /* FIXME: We should move some of the quirk fixup stuff here */ 553 /* FIXME: We should move some of the quirk fixup stuff here */
554
555 if (router->device == PCI_DEVICE_ID_VIA_82C686 &&
556 device == PCI_DEVICE_ID_VIA_82C586_0) {
557 /* Asus k7m bios wrongly reports 82C686A as 586-compatible */
558 device = PCI_DEVICE_ID_VIA_82C686;
559 }
560
512 switch(device) 561 switch(device)
513 { 562 {
514 case PCI_DEVICE_ID_VIA_82C586_0: 563 case PCI_DEVICE_ID_VIA_82C586_0:
564 r->name = "VIA";
565 r->get = pirq_via586_get;
566 r->set = pirq_via586_set;
567 return 1;
515 case PCI_DEVICE_ID_VIA_82C596: 568 case PCI_DEVICE_ID_VIA_82C596:
516 case PCI_DEVICE_ID_VIA_82C686: 569 case PCI_DEVICE_ID_VIA_82C686:
517 case PCI_DEVICE_ID_VIA_8231: 570 case PCI_DEVICE_ID_VIA_8231:
@@ -1006,24 +1059,28 @@ static int __init pcibios_irq_init(void)
1006subsys_initcall(pcibios_irq_init); 1059subsys_initcall(pcibios_irq_init);
1007 1060
1008 1061
1009static void pirq_penalize_isa_irq(int irq) 1062static void pirq_penalize_isa_irq(int irq, int active)
1010{ 1063{
1011 /* 1064 /*
1012 * If any ISAPnP device reports an IRQ in its list of possible 1065 * If any ISAPnP device reports an IRQ in its list of possible
1013 * IRQ's, we try to avoid assigning it to PCI devices. 1066 * IRQ's, we try to avoid assigning it to PCI devices.
1014 */ 1067 */
1015 if (irq < 16) 1068 if (irq < 16) {
1016 pirq_penalty[irq] += 100; 1069 if (active)
1070 pirq_penalty[irq] += 1000;
1071 else
1072 pirq_penalty[irq] += 100;
1073 }
1017} 1074}
1018 1075
1019void pcibios_penalize_isa_irq(int irq) 1076void pcibios_penalize_isa_irq(int irq, int active)
1020{ 1077{
1021#ifdef CONFIG_ACPI_PCI 1078#ifdef CONFIG_ACPI_PCI
1022 if (!acpi_noirq) 1079 if (!acpi_noirq)
1023 acpi_penalize_isa_irq(irq); 1080 acpi_penalize_isa_irq(irq, active);
1024 else 1081 else
1025#endif 1082#endif
1026 pirq_penalize_isa_irq(irq); 1083 pirq_penalize_isa_irq(irq, active);
1027} 1084}
1028 1085
1029static int pirq_enable_irq(struct pci_dev *dev) 1086static int pirq_enable_irq(struct pci_dev *dev)
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/pcbios.c b/arch/i386/pci/pcbios.c
index 141421b673b0..b9d65f0bc2d1 100644
--- a/arch/i386/pci/pcbios.c
+++ b/arch/i386/pci/pcbios.c
@@ -4,6 +4,7 @@
4 4
5#include <linux/pci.h> 5#include <linux/pci.h>
6#include <linux/init.h> 6#include <linux/init.h>
7#include <linux/module.h>
7#include "pci.h" 8#include "pci.h"
8#include "pci-functions.h" 9#include "pci-functions.h"
9 10
@@ -456,7 +457,7 @@ struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
456 free_page(page); 457 free_page(page);
457 return rt; 458 return rt;
458} 459}
459 460EXPORT_SYMBOL(pcibios_get_irq_routing_table);
460 461
461int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq) 462int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
462{ 463{
@@ -473,6 +474,7 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
473 "S" (&pci_indirect)); 474 "S" (&pci_indirect));
474 return !(ret & 0xff00); 475 return !(ret & 0xff00);
475} 476}
477EXPORT_SYMBOL(pcibios_set_irq_routing);
476 478
477static int __init pci_pcbios_init(void) 479static int __init pci_pcbios_init(void)
478{ 480{
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index a8fc80ca69f3..127d53ad16be 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
@@ -72,3 +73,4 @@ extern int pcibios_scanned;
72extern spinlock_t pci_config_lock; 73extern spinlock_t pci_config_lock;
73 74
74extern int (*pcibios_enable_irq)(struct pci_dev *dev); 75extern int (*pcibios_enable_irq)(struct pci_dev *dev);
76extern void (*pcibios_disable_irq)(struct pci_dev *dev);
diff --git a/arch/i386/pci/visws.c b/arch/i386/pci/visws.c
index 6a9248784439..6c17433fdf7d 100644
--- a/arch/i386/pci/visws.c
+++ b/arch/i386/pci/visws.c
@@ -18,10 +18,12 @@
18extern struct pci_raw_ops pci_direct_conf1; 18extern struct pci_raw_ops pci_direct_conf1;
19 19
20static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; } 20static int pci_visws_enable_irq(struct pci_dev *dev) { return 0; }
21static void pci_visws_disable_irq(struct pci_dev *dev) { }
21 22
22int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq; 23int (*pcibios_enable_irq)(struct pci_dev *dev) = &pci_visws_enable_irq;
24void (*pcibios_disable_irq)(struct pci_dev *dev) = &pci_visws_disable_irq;
23 25
24void __init pcibios_penalize_isa_irq(int irq) {} 26void __init pcibios_penalize_isa_irq(int irq, int active) {}
25 27
26 28
27unsigned int pci_bus0, pci_bus1; 29unsigned int pci_bus0, pci_bus1;