Commit f5f7e4d0 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Greg Kroah-Hartman

[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.
parent f7d6ae35
...@@ -201,54 +201,84 @@ static int __devinit pci_sanity_check(struct pci_raw_ops *o) ...@@ -201,54 +201,84 @@ static int __devinit pci_sanity_check(struct pci_raw_ops *o)
return 0; return 0;
} }
static int __init pci_direct_init(void) static int __init pci_check_type1(void)
{ {
unsigned int tmp;
unsigned long flags; unsigned long flags;
unsigned int tmp;
int works = 0;
local_irq_save(flags); local_irq_save(flags);
/* outb(0x01, 0xCFB);
* Check if configuration type 1 works. tmp = inl(0xCF8);
*/ outl(0x80000000, 0xCF8);
if (pci_probe & PCI_PROBE_CONF1) { if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) {
outb (0x01, 0xCFB); works = 1;
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);
} }
outl(tmp, 0xCF8);
local_irq_restore(flags);
return works;
}
static int __init pci_check_type2(void)
{
unsigned long flags;
int works = 0;
local_irq_save(flags);
/* outb(0x00, 0xCFB);
* Check if configuration type 2 works. outb(0x00, 0xCF8);
*/ outb(0x00, 0xCFA);
if (pci_probe & PCI_PROBE_CONF2) { if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 &&
outb (0x00, 0xCFB); pci_sanity_check(&pci_direct_conf2)) {
outb (0x00, 0xCF8); works = 1;
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;
}
} }
local_irq_restore(flags); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment