[PATCH] PCI: i386/pci/direct.c fixes
- Request resources before using them
- Don't allocate GFP_KERNEL memory with interrupts disabled
- Split pci_direct_init() into three functions to prevent it from
getting too long.
arch/i386/pci/direct.c | 106 +++++++++++++++++++++++++++++++------------------
1 files changed, 68 insertions(+), 38 deletions(-)
diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
--- a/arch/i386/pci/direct.c Thu Jun 26 17:38:57 2003
+++ b/arch/i386/pci/direct.c Thu Jun 26 17:38:57 2003
@@ -201,54 +201,84 @@
return 0;
}
-static int __init pci_direct_init(void)
+static int __init pci_check_type1(void)
{
- unsigned int tmp;
unsigned long flags;
+ unsigned int tmp;
+ int works = 0;
local_irq_save(flags);
- /*
- * Check if configuration type 1 works.
- */
- if (pci_probe & PCI_PROBE_CONF1) {
- outb (0x01, 0xCFB);
- tmp = inl (0xCF8);
- outl (0x80000000, 0xCF8);
- if (inl (0xCF8) == 0x80000000 &&
- pci_sanity_check(&pci_direct_conf1)) {
- outl (tmp, 0xCF8);
- local_irq_restore(flags);
- printk(KERN_INFO "PCI: Using configuration type 1\n");
- if (!request_region(0xCF8, 8, "PCI conf1"))
- raw_pci_ops = NULL;
- else
- raw_pci_ops = &pci_direct_conf1;
- return 0;
- }
- outl (tmp, 0xCF8);
+ outb(0x01, 0xCFB);
+ tmp = inl(0xCF8);
+ outl(0x80000000, 0xCF8);
+ if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
+ works = 1;
}
+ outl(tmp, 0xCF8);
+ local_irq_restore(flags);
+
+ return works;
+}
- /*
- * Check if configuration type 2 works.
- */
- if (pci_probe & PCI_PROBE_CONF2) {
- outb (0x00, 0xCFB);
- outb (0x00, 0xCF8);
- outb (0x00, 0xCFA);
- if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 &&
- pci_sanity_check(&pci_direct_conf2)) {
- local_irq_restore(flags);
- printk(KERN_INFO "PCI: Using configuration type 2\n");
- if (!request_region(0xCF8, 4, "PCI conf2"))
- raw_pci_ops = NULL;
- else
- raw_pci_ops = &pci_direct_conf2;
- return 0;
- }
+static int __init pci_check_type2(void)
+{
+ unsigned long flags;
+ int works = 0;
+
+ local_irq_save(flags);
+
+ outb(0x00, 0xCFB);
+ outb(0x00, 0xCF8);
+ outb(0x00, 0xCFA);
+ if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
+ pci_sanity_check(&pci_direct_conf2)) {
+ works = 1;
}
local_irq_restore(flags);
+
+ return works;
+}
+
+static int __init pci_direct_init(void)
+{
+ struct resource *region, *region2;
+
+ if ((pci_probe & PCI_PROBE_CONF1) == 0)
+ goto type2;
+ region = request_region(0xCF8, 8, "PCI conf1");
+ if (!region)
+ goto type2;
+
+ if (pci_check_type1()) {
+ printk(KERN_INFO "PCI: Using configuration type 1\n");
+ raw_pci_ops = &pci_direct_conf1;
+ return 0;
+ }
+ release_resource(region);
+
+ type2:
+ if ((!pci_probe & PCI_PROBE_CONF2) == 0)
+ goto out;
+ region = request_region(0xCF8, 4, "PCI conf2");
+ if (!region)
+ goto out;
+ region2 = request_region(0xC000, 0x1000, "PCI conf2");
+ if (!region2)
+ goto fail2;
+
+ if (pci_check_type2()) {
+ printk(KERN_INFO "PCI: Using configuration type 2\n");
+ raw_pci_ops = &pci_direct_conf2;
+ return 0;
+ }
+
+ release_resource(region2);
+ fail2:
+ release_resource(region);
+
+ out:
return 0;
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/