Pull ec into release branch
[pandora-kernel.git] / arch / i386 / pci / common.c
index 0a362e3..3f78d4d 100644 (file)
@@ -20,6 +20,7 @@
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
                                PCI_PROBE_MMCONF;
 
+static int pci_bf_sort;
 int pci_routeirq;
 int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
@@ -117,6 +118,20 @@ void __devinit  pcibios_fixup_bus(struct pci_bus *b)
        pci_read_bridge_bases(b);
 }
 
+/*
+ * Only use DMI information to set this if nothing was passed
+ * on the kernel command line (which was parsed earlier).
+ */
+
+static int __devinit set_bf_sort(struct dmi_system_id *d)
+{
+       if (pci_bf_sort == pci_bf_sort_default) {
+               pci_bf_sort = pci_dmi_bf;
+               printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident);
+       }
+       return 0;
+}
+
 /*
  * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus)
  */
@@ -130,11 +145,11 @@ static int __devinit assign_all_busses(struct dmi_system_id *d)
 }
 #endif
 
+static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
+#ifdef __i386__
 /*
  * Laptops which need pci=assign-busses to see Cardbus cards
  */
-static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
-#ifdef __i386__
        {
                .callback = assign_all_busses,
                .ident = "Samsung X20 Laptop",
@@ -144,6 +159,134 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = {
                },
        },
 #endif         /* __i386__ */
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 1950",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 1955",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 2900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge 2950",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "Dell PowerEdge R900",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R900"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL20p G3",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G3"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL20p G4",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL20p G4"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL30p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL30p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL25p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL25p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL35p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL35p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL45p G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL45p G2",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL45p G2"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL460c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL460c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL465c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL480c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL480c G1"),
+               },
+       },
+       {
+               .callback = set_bf_sort,
+               .ident = "HP ProLiant BL685c G1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c G1"),
+               },
+       },
        {}
 };
 
@@ -189,6 +332,8 @@ static int __init pcibios_init(void)
 
        pcibios_resource_survey();
 
+       if (pci_bf_sort >= pci_force_bf)
+               pci_sort_breadthfirst();
 #ifdef CONFIG_PCI_BIOS
        if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
                pcibios_sort();
@@ -203,6 +348,12 @@ char * __devinit  pcibios_setup(char *str)
        if (!strcmp(str, "off")) {
                pci_probe = 0;
                return NULL;
+       } else if (!strcmp(str, "bfsort")) {
+               pci_bf_sort = pci_force_bf;
+               return NULL;
+       } else if (!strcmp(str, "nobfsort")) {
+               pci_bf_sort = pci_force_nobf;
+               return NULL;
        }
 #ifdef CONFIG_PCI_BIOS
        else if (!strcmp(str, "bios")) {
@@ -242,6 +393,10 @@ char * __devinit  pcibios_setup(char *str)
                acpi_noirq_set();
                return NULL;
        }
+       else if (!strcmp(str, "noearly")) {
+               pci_probe |= PCI_PROBE_NOEARLY;
+               return NULL;
+       }
 #ifndef CONFIG_X86_VISWS
        else if (!strcmp(str, "usepirqmask")) {
                pci_probe |= PCI_USE_PIRQ_MASK;
@@ -279,12 +434,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        if ((err = pcibios_enable_resources(dev, mask)) < 0)
                return err;
 
-       return pcibios_enable_irq(dev);
+       if (!dev->msi_enabled)
+               return pcibios_enable_irq(dev);
+       return 0;
 }
 
 void pcibios_disable_device (struct pci_dev *dev)
 {
-       pcibios_disable_resources(dev);
-       if (pcibios_disable_irq)
+       if (!dev->msi_enabled && pcibios_disable_irq)
                pcibios_disable_irq(dev);
 }