aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kernel/pci-dma_32.c3
-rw-r--r--arch/x86/kernel/pci-dma_64.c1
-rw-r--r--arch/x86/kernel/reboot_fixups_32.c6
-rw-r--r--arch/x86/pci/acpi.c194
-rw-r--r--arch/x86/pci/common.c19
-rw-r--r--arch/x86/pci/fixup.c47
-rw-r--r--arch/x86/pci/i386.c13
-rw-r--r--arch/x86/pci/irq.c39
-rw-r--r--arch/x86/pci/pci.h2
9 files changed, 315 insertions, 9 deletions
diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c
index 048f09b62553..0aae2f3847a5 100644
--- a/arch/x86/kernel/pci-dma_32.c
+++ b/arch/x86/kernel/pci-dma_32.c
@@ -63,7 +63,8 @@ void dma_free_coherent(struct device *dev, size_t size,
63{ 63{
64 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; 64 struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
65 int order = get_order(size); 65 int order = get_order(size);
66 66
67 WARN_ON(irqs_disabled()); /* for portability */
67 if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { 68 if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) {
68 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; 69 int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
69 70
diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c
index 29711445c818..9576a2eb375e 100644
--- a/arch/x86/kernel/pci-dma_64.c
+++ b/arch/x86/kernel/pci-dma_64.c
@@ -167,6 +167,7 @@ EXPORT_SYMBOL(dma_alloc_coherent);
167void dma_free_coherent(struct device *dev, size_t size, 167void dma_free_coherent(struct device *dev, size_t size,
168 void *vaddr, dma_addr_t bus) 168 void *vaddr, dma_addr_t bus)
169{ 169{
170 WARN_ON(irqs_disabled()); /* for portability */
170 if (dma_ops->unmap_single) 171 if (dma_ops->unmap_single)
171 dma_ops->unmap_single(dev, bus, size, 0); 172 dma_ops->unmap_single(dev, bus, size, 0);
172 free_pages((unsigned long)vaddr, get_order(size)); 173 free_pages((unsigned long)vaddr, get_order(size));
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c
index 03e1cce58f49..139eb03490f5 100644
--- a/arch/x86/kernel/reboot_fixups_32.c
+++ b/arch/x86/kernel/reboot_fixups_32.c
@@ -11,6 +11,7 @@
11 11
12#include <asm/delay.h> 12#include <asm/delay.h>
13#include <linux/pci.h> 13#include <linux/pci.h>
14#include <linux/interrupt.h>
14#include <asm/reboot_fixups.h> 15#include <asm/reboot_fixups.h>
15#include <asm/msr.h> 16#include <asm/msr.h>
16 17
@@ -56,6 +57,11 @@ void mach_reboot_fixups(void)
56 struct pci_dev *dev; 57 struct pci_dev *dev;
57 int i; 58 int i;
58 59
60 /* we can be called from sysrq-B code. In such a case it is
61 * prohibited to dig PCI */
62 if (in_interrupt())
63 return;
64
59 for (i=0; i < ARRAY_SIZE(fixups_table); i++) { 65 for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
60 cur = &(fixups_table[i]); 66 cur = &(fixups_table[i]);
61 dev = pci_get_device(cur->vendor, cur->device, NULL); 67 dev = pci_get_device(cur->vendor, cur->device, NULL);
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index bc8a44bddaa7..27a391da9a98 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -2,15 +2,199 @@
2#include <linux/acpi.h> 2#include <linux/acpi.h>
3#include <linux/init.h> 3#include <linux/init.h>
4#include <linux/irq.h> 4#include <linux/irq.h>
5#include <linux/dmi.h>
5#include <asm/numa.h> 6#include <asm/numa.h>
6#include "pci.h" 7#include "pci.h"
7 8
9static int __devinit can_skip_ioresource_align(struct dmi_system_id *d)
10{
11 pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
12 printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
13 return 0;
14}
15
16static struct dmi_system_id acpi_pciprobe_dmi_table[] = {
17/*
18 * Systems where PCI IO resource ISA alignment can be skipped
19 * when the ISA enable bit in the bridge control is not set
20 */
21 {
22 .callback = can_skip_ioresource_align,
23 .ident = "IBM System x3800",
24 .matches = {
25 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
26 DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
27 },
28 },
29 {
30 .callback = can_skip_ioresource_align,
31 .ident = "IBM System x3850",
32 .matches = {
33 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
34 DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
35 },
36 },
37 {
38 .callback = can_skip_ioresource_align,
39 .ident = "IBM System x3950",
40 .matches = {
41 DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
42 DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
43 },
44 },
45 {}
46};
47
48struct pci_root_info {
49 char *name;
50 unsigned int res_num;
51 struct resource *res;
52 struct pci_bus *bus;
53 int busnum;
54};
55
56static acpi_status
57resource_to_addr(struct acpi_resource *resource,
58 struct acpi_resource_address64 *addr)
59{
60 acpi_status status;
61
62 status = acpi_resource_to_address64(resource, addr);
63 if (ACPI_SUCCESS(status) &&
64 (addr->resource_type == ACPI_MEMORY_RANGE ||
65 addr->resource_type == ACPI_IO_RANGE) &&
66 addr->address_length > 0 &&
67 addr->producer_consumer == ACPI_PRODUCER) {
68 return AE_OK;
69 }
70 return AE_ERROR;
71}
72
73static acpi_status
74count_resource(struct acpi_resource *acpi_res, void *data)
75{
76 struct pci_root_info *info = data;
77 struct acpi_resource_address64 addr;
78 acpi_status status;
79
80 status = resource_to_addr(acpi_res, &addr);
81 if (ACPI_SUCCESS(status))
82 info->res_num++;
83 return AE_OK;
84}
85
86static acpi_status
87setup_resource(struct acpi_resource *acpi_res, void *data)
88{
89 struct pci_root_info *info = data;
90 struct resource *res;
91 struct acpi_resource_address64 addr;
92 acpi_status status;
93 unsigned long flags;
94 struct resource *root;
95
96 status = resource_to_addr(acpi_res, &addr);
97 if (!ACPI_SUCCESS(status))
98 return AE_OK;
99
100 if (addr.resource_type == ACPI_MEMORY_RANGE) {
101 root = &iomem_resource;
102 flags = IORESOURCE_MEM;
103 if (addr.info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
104 flags |= IORESOURCE_PREFETCH;
105 } else if (addr.resource_type == ACPI_IO_RANGE) {
106 root = &ioport_resource;
107 flags = IORESOURCE_IO;
108 } else
109 return AE_OK;
110
111 res = &info->res[info->res_num];
112 res->name = info->name;
113 res->flags = flags;
114 res->start = addr.minimum + addr.translation_offset;
115 res->end = res->start + addr.address_length - 1;
116 res->child = NULL;
117
118 if (insert_resource(root, res)) {
119 printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
120 "from %s for %s\n", (unsigned long) res->start,
121 (unsigned long) res->end, root->name, info->name);
122 } else {
123 info->bus->resource[info->res_num] = res;
124 info->res_num++;
125 }
126 return AE_OK;
127}
128
129static void
130adjust_transparent_bridge_resources(struct pci_bus *bus)
131{
132 struct pci_dev *dev;
133
134 list_for_each_entry(dev, &bus->devices, bus_list) {
135 int i;
136 u16 class = dev->class >> 8;
137
138 if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent) {
139 for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
140 dev->subordinate->resource[i] =
141 dev->bus->resource[i - 3];
142 }
143 }
144}
145
146static void
147get_current_resources(struct acpi_device *device, int busnum,
148 struct pci_bus *bus)
149{
150 struct pci_root_info info;
151 size_t size;
152
153 info.bus = bus;
154 info.res_num = 0;
155 acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
156 &info);
157 if (!info.res_num)
158 return;
159
160 size = sizeof(*info.res) * info.res_num;
161 info.res = kmalloc(size, GFP_KERNEL);
162 if (!info.res)
163 goto res_alloc_fail;
164
165 info.name = kmalloc(12, GFP_KERNEL);
166 if (!info.name)
167 goto name_alloc_fail;
168 sprintf(info.name, "PCI Bus #%02x", busnum);
169
170 info.res_num = 0;
171 acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
172 &info);
173 if (info.res_num)
174 adjust_transparent_bridge_resources(bus);
175
176 return;
177
178name_alloc_fail:
179 kfree(info.res);
180res_alloc_fail:
181 return;
182}
183
8struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) 184struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
9{ 185{
10 struct pci_bus *bus; 186 struct pci_bus *bus;
11 struct pci_sysdata *sd; 187 struct pci_sysdata *sd;
12 int pxm; 188 int pxm;
13 189
190 dmi_check_system(acpi_pciprobe_dmi_table);
191
192 if (domain && !pci_domains_supported) {
193 printk(KERN_WARNING "PCI: Multiple domains not supported "
194 "(dom %d, bus %d)\n", domain, busnum);
195 return NULL;
196 }
197
14 /* Allocate per-root-bus (not per bus) arch-specific data. 198 /* Allocate per-root-bus (not per bus) arch-specific data.
15 * TODO: leak; this memory is never freed. 199 * TODO: leak; this memory is never freed.
16 * It's arguable whether it's worth the trouble to care. 200 * It's arguable whether it's worth the trouble to care.
@@ -21,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
21 return NULL; 205 return NULL;
22 } 206 }
23 207
24 if (domain != 0) { 208 sd->domain = domain;
25 printk(KERN_WARNING "PCI: Multiple domains not supported\n");
26 kfree(sd);
27 return NULL;
28 }
29
30 sd->node = -1; 209 sd->node = -1;
31 210
32 pxm = acpi_get_pxm(device->handle); 211 pxm = acpi_get_pxm(device->handle);
@@ -47,6 +226,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
47 } 226 }
48 } 227 }
49#endif 228#endif
229
230 if (bus && (pci_probe & PCI_USE__CRS))
231 get_current_resources(device, busnum, bus);
50 232
51 return bus; 233 return bus;
52} 234}
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 07d5223442bf..2d71bbc411d2 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops;
29 29
30static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) 30static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
31{ 31{
32 return raw_pci_ops->read(0, bus->number, devfn, where, size, value); 32 return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
33 devfn, where, size, value);
33} 34}
34 35
35static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) 36static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
36{ 37{
37 return raw_pci_ops->write(0, bus->number, devfn, where, size, value); 38 return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
39 devfn, where, size, value);
38} 40}
39 41
40struct pci_ops pci_root_ops = { 42struct pci_ops pci_root_ops = {
@@ -287,6 +289,16 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
287 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"), 289 DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
288 }, 290 },
289 }, 291 },
292#ifdef __i386__
293 {
294 .callback = assign_all_busses,
295 .ident = "Compaq EVO N800c",
296 .matches = {
297 DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
298 DMI_MATCH(DMI_PRODUCT_NAME, "EVO N800c"),
299 },
300 },
301#endif
290 {} 302 {}
291}; 303};
292 304
@@ -426,6 +438,9 @@ char * __devinit pcibios_setup(char *str)
426 } else if (!strcmp(str, "assign-busses")) { 438 } else if (!strcmp(str, "assign-busses")) {
427 pci_probe |= PCI_ASSIGN_ALL_BUSSES; 439 pci_probe |= PCI_ASSIGN_ALL_BUSSES;
428 return NULL; 440 return NULL;
441 } else if (!strcmp(str, "use_crs")) {
442 pci_probe |= PCI_USE__CRS;
443 return NULL;
429 } else if (!strcmp(str, "routeirq")) { 444 } else if (!strcmp(str, "routeirq")) {
430 pci_routeirq = 1; 445 pci_routeirq = 1;
431 return NULL; 446 return NULL;
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index c82cbf4c7226..6cff66dd0c91 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -353,6 +353,53 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
353} 353}
354DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); 354DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
355 355
356
357static struct dmi_system_id __devinitdata msi_k8t_dmi_table[] = {
358 {
359 .ident = "MSI-K8T-Neo2Fir",
360 .matches = {
361 DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
362 DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"),
363 },
364 },
365 {}
366};
367
368/*
369 * The AMD-Athlon64 board MSI "K8T Neo2-FIR" disables the onboard sound
370 * card if a PCI-soundcard is added.
371 *
372 * The BIOS only gives options "DISABLED" and "AUTO". This code sets
373 * the corresponding register-value to enable the soundcard.
374 *
375 * The soundcard is only enabled, if the mainborad is identified
376 * via DMI-tables and the soundcard is detected to be off.
377 */
378static void __devinit pci_fixup_msi_k8t_onboard_sound(struct pci_dev *dev)
379{
380 unsigned char val;
381 if (!dmi_check_system(msi_k8t_dmi_table))
382 return; /* only applies to MSI K8T Neo2-FIR */
383
384 pci_read_config_byte(dev, 0x50, &val);
385 if (val & 0x40) {
386 pci_write_config_byte(dev, 0x50, val & (~0x40));
387
388 /* verify the change for status output */
389 pci_read_config_byte(dev, 0x50, &val);
390 if (val & 0x40)
391 printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
392 "can't enable onboard soundcard!\n");
393 else
394 printk(KERN_INFO "PCI: Detected MSI K8T Neo2-FIR, "
395 "enabled onboard soundcard.\n");
396 }
397}
398DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
399 pci_fixup_msi_k8t_onboard_sound);
400DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
401 pci_fixup_msi_k8t_onboard_sound);
402
356/* 403/*
357 * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. 404 * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
358 * 405 *
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index bcd2f94b732c..42ba0e2da1a0 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -33,6 +33,15 @@
33 33
34#include "pci.h" 34#include "pci.h"
35 35
36static int
37skip_isa_ioresource_align(struct pci_dev *dev) {
38
39 if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) &&
40 !(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_ISA))
41 return 1;
42 return 0;
43}
44
36/* 45/*
37 * We need to avoid collisions with `mirrored' VGA ports 46 * We need to avoid collisions with `mirrored' VGA ports
38 * and other strange ISA hardware, so we always want the 47 * and other strange ISA hardware, so we always want the
@@ -50,9 +59,13 @@ void
50pcibios_align_resource(void *data, struct resource *res, 59pcibios_align_resource(void *data, struct resource *res,
51 resource_size_t size, resource_size_t align) 60 resource_size_t size, resource_size_t align)
52{ 61{
62 struct pci_dev *dev = data;
63
53 if (res->flags & IORESOURCE_IO) { 64 if (res->flags & IORESOURCE_IO) {
54 resource_size_t start = res->start; 65 resource_size_t start = res->start;
55 66
67 if (skip_isa_ioresource_align(dev))
68 return;
56 if (start & 0x300) { 69 if (start & 0x300) {
57 start = (start + 0x3ff) & ~0x3ff; 70 start = (start + 0x3ff) & ~0x3ff;
58 res->start = start; 71 res->start = start;
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index d98c6b096f8e..c52150fdf82b 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -492,6 +492,26 @@ static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq
492 return 1; 492 return 1;
493} 493}
494 494
495/*
496 * PicoPower PT86C523
497 */
498static int pirq_pico_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
499{
500 outb(0x10 + ((pirq - 1) >> 1), 0x24);
501 return ((pirq - 1) & 1) ? (inb(0x26) >> 4) : (inb(0x26) & 0xf);
502}
503
504static int pirq_pico_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
505 int irq)
506{
507 unsigned int x;
508 outb(0x10 + ((pirq - 1) >> 1), 0x24);
509 x = inb(0x26);
510 x = ((pirq - 1) & 1) ? ((x & 0x0f) | (irq << 4)) : ((x & 0xf0) | (irq));
511 outb(x, 0x26);
512 return 1;
513}
514
495#ifdef CONFIG_PCI_BIOS 515#ifdef CONFIG_PCI_BIOS
496 516
497static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) 517static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
@@ -721,6 +741,24 @@ static __init int amd_router_probe(struct irq_router *r, struct pci_dev *router,
721 return 1; 741 return 1;
722} 742}
723 743
744static __init int pico_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
745{
746 switch (device) {
747 case PCI_DEVICE_ID_PICOPOWER_PT86C523:
748 r->name = "PicoPower PT86C523";
749 r->get = pirq_pico_get;
750 r->set = pirq_pico_set;
751 return 1;
752
753 case PCI_DEVICE_ID_PICOPOWER_PT86C523BBP:
754 r->name = "PicoPower PT86C523 rev. BB+";
755 r->get = pirq_pico_get;
756 r->set = pirq_pico_set;
757 return 1;
758 }
759 return 0;
760}
761
724static __initdata struct irq_router_handler pirq_routers[] = { 762static __initdata struct irq_router_handler pirq_routers[] = {
725 { PCI_VENDOR_ID_INTEL, intel_router_probe }, 763 { PCI_VENDOR_ID_INTEL, intel_router_probe },
726 { PCI_VENDOR_ID_AL, ali_router_probe }, 764 { PCI_VENDOR_ID_AL, ali_router_probe },
@@ -732,6 +770,7 @@ static __initdata struct irq_router_handler pirq_routers[] = {
732 { PCI_VENDOR_ID_VLSI, vlsi_router_probe }, 770 { PCI_VENDOR_ID_VLSI, vlsi_router_probe },
733 { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe }, 771 { PCI_VENDOR_ID_SERVERWORKS, serverworks_router_probe },
734 { PCI_VENDOR_ID_AMD, amd_router_probe }, 772 { PCI_VENDOR_ID_AMD, amd_router_probe },
773 { PCI_VENDOR_ID_PICOPOWER, pico_router_probe },
735 /* Someone with docs needs to add the ATI Radeon IGP */ 774 /* Someone with docs needs to add the ATI Radeon IGP */
736 { 0, NULL } 775 { 0, NULL }
737}; 776};
diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h
index 8c66f275756f..ac56d3916c50 100644
--- a/arch/x86/pci/pci.h
+++ b/arch/x86/pci/pci.h
@@ -26,6 +26,8 @@
26#define PCI_ASSIGN_ROMS 0x1000 26#define PCI_ASSIGN_ROMS 0x1000
27#define PCI_BIOS_IRQ_SCAN 0x2000 27#define PCI_BIOS_IRQ_SCAN 0x2000
28#define PCI_ASSIGN_ALL_BUSSES 0x4000 28#define PCI_ASSIGN_ALL_BUSSES 0x4000
29#define PCI_CAN_SKIP_ISA_ALIGN 0x8000
30#define PCI_USE__CRS 0x10000
29 31
30extern unsigned int pci_probe; 32extern unsigned int pci_probe;
31extern unsigned long pirq_table_addr; 33extern unsigned long pirq_table_addr;