@@ -41,6 +41,9 @@
#include <linux/interrupt.h>
#include <linux/debugfs.h>
#include <asm/unaligned.h>
+#ifdef CONFIG_PCI_MMCONFIG
+#include <asm/pci_x86.h>
+#endif
#include "apei-internal.h"
@@ -449,7 +452,7 @@ int apei_resources_sub(struct apei_resources *resources1,
}
EXPORT_SYMBOL_GPL(apei_resources_sub);
-static int apei_get_nvs_callback(__u64 start, __u64 size, void *data)
+static int apei_get_res_callback(__u64 start, __u64 size, void *data)
{
struct apei_resources *resources = data;
return apei_res_add(&resources->iomem, start, size);
@@ -457,9 +460,42 @@ static int apei_get_nvs_callback(__u64 start, __u64 size, void *data)
static int apei_get_nvs_resources(struct apei_resources *resources)
{
- return acpi_nvs_for_each_region(apei_get_nvs_callback, resources);
+ return acpi_nvs_for_each_region(apei_get_res_callback, resources);
}
+#ifdef CONFIG_PCI_MMCONFIG
+static int pci_mmcfg_for_each_region(int (*func)(__u64 start, __u64 size,
+ void *data), void *data)
+{
+ struct pci_mmcfg_region *cfg;
+ int rc;
+
+ if ((pci_probe & PCI_PROBE_MMCONF) == 0)
+ return 0;
+
+ if (list_empty(&pci_mmcfg_list))
+ return 0;
+
+ list_for_each_entry(cfg, &pci_mmcfg_list, list) {
+ rc = func(cfg->res.start, resource_size(&cfg->res), data);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static int apei_get_mmcfg_resources(struct apei_resources *resources)
+{
+ return pci_mmcfg_for_each_region(apei_get_res_callback, resources);
+}
+#else
+static int apei_get_mmcfg_resources(struct apei_resources *resources)
+{
+ return 0;
+}
+#endif
+
/*
* IO memory/port resource management mechanism is used to check
* whether memory/port area used by GARs conflicts with normal memory
@@ -470,7 +506,7 @@ int apei_resources_request(struct apei_resources *resources,
{
struct apei_res *res, *res_bak = NULL;
struct resource *r;
- struct apei_resources nvs_resources;
+ struct apei_resources nvs_resources, mmcfg_res;
int rc;
rc = apei_resources_sub(resources, &apei_resources_all);
@@ -485,10 +521,18 @@ int apei_resources_request(struct apei_resources *resources,
apei_resources_init(&nvs_resources);
rc = apei_get_nvs_resources(&nvs_resources);
if (rc)
- goto res_fini;
+ goto nvs_res_fini;
rc = apei_resources_sub(resources, &nvs_resources);
if (rc)
- goto res_fini;
+ goto nvs_res_fini;
+
+ apei_resources_init(&mmcfg_res);
+ rc = apei_get_mmcfg_resources(&mmcfg_res);
+ if (rc)
+ goto mmcfg_res_fini;
+ rc = apei_resources_sub(resources, &mmcfg_res);
+ if (rc)
+ goto mmcfg_res_fini;
rc = -EINVAL;
list_for_each_entry(res, &resources->iomem, list) {
@@ -536,7 +580,9 @@ err_unmap_iomem:
break;
release_mem_region(res->start, res->end - res->start);
}
-res_fini:
+mmcfg_res_fini:
+ apei_resources_fini(&mmcfg_res);
+nvs_res_fini:
apei_resources_fini(&nvs_resources);
return rc;
}