x86/PCI: Prevent mmconfig memory corruption
[safe/jmp/linux-2.6] / arch / x86 / pci / mmconfig-shared.c
index 71d69b8..8f3f9a5 100644 (file)
@@ -97,6 +97,18 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
        return new;
 }
 
+struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
+{
+       struct pci_mmcfg_region *cfg;
+
+       list_for_each_entry(cfg, &pci_mmcfg_list, list)
+               if (cfg->segment == segment &&
+                   cfg->start_bus <= bus && bus <= cfg->end_bus)
+                       return cfg;
+
+       return NULL;
+}
+
 static const char __init *pci_mmcfg_e7520(void)
 {
        u32 win;
@@ -291,22 +303,17 @@ static void __init pci_mmcfg_check_end_bus_number(void)
 {
        struct pci_mmcfg_region *cfg, *cfgx;
 
-       /* last one*/
-       cfg = list_entry(pci_mmcfg_list.prev, typeof(*cfg), list);
-       if (cfg)
-               if (cfg->end_bus < cfg->start_bus)
-                       cfg->end_bus = 255;
-
-       if (list_is_singular(&pci_mmcfg_list))
-               return;
-
-       /* don't overlap please */
+       /* Fixup overlaps */
        list_for_each_entry(cfg, &pci_mmcfg_list, list) {
                if (cfg->end_bus < cfg->start_bus)
                        cfg->end_bus = 255;
 
+               /* Don't access the list head ! */
+               if (cfg->list.next == &pci_mmcfg_list)
+                       break;
+
                cfgx = list_entry(cfg->list.next, typeof(*cfg), list);
-               if (cfg != cfgx && cfg->end_bus >= cfgx->start_bus)
+               if (cfg->end_bus >= cfgx->start_bus)
                        cfg->end_bus = cfgx->start_bus - 1;
        }
 }