|
@@ -1571,6 +1571,48 @@ static int ars_status_process_records(struct nvdimm_bus *nvdimm_bus,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void acpi_nfit_remove_resource(void *data)
|
|
|
+{
|
|
|
+ struct resource *res = data;
|
|
|
+
|
|
|
+ remove_resource(res);
|
|
|
+}
|
|
|
+
|
|
|
+static int acpi_nfit_insert_resource(struct acpi_nfit_desc *acpi_desc,
|
|
|
+ struct nd_region_desc *ndr_desc)
|
|
|
+{
|
|
|
+ struct resource *res, *nd_res = ndr_desc->res;
|
|
|
+ int is_pmem, ret;
|
|
|
+
|
|
|
+ /* No operation if the region is already registered as PMEM */
|
|
|
+ is_pmem = region_intersects(nd_res->start, resource_size(nd_res),
|
|
|
+ IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY);
|
|
|
+ if (is_pmem == REGION_INTERSECTS)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ res = devm_kzalloc(acpi_desc->dev, sizeof(*res), GFP_KERNEL);
|
|
|
+ if (!res)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ res->name = "Persistent Memory";
|
|
|
+ res->start = nd_res->start;
|
|
|
+ res->end = nd_res->end;
|
|
|
+ res->flags = IORESOURCE_MEM;
|
|
|
+ res->desc = IORES_DESC_PERSISTENT_MEMORY;
|
|
|
+
|
|
|
+ ret = insert_resource(&iomem_resource, res);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = devm_add_action(acpi_desc->dev, acpi_nfit_remove_resource, res);
|
|
|
+ if (ret) {
|
|
|
+ remove_resource(res);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int acpi_nfit_find_poison(struct acpi_nfit_desc *acpi_desc,
|
|
|
struct nd_region_desc *ndr_desc)
|
|
|
{
|
|
@@ -1781,6 +1823,12 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
|
|
|
|
|
|
nvdimm_bus = acpi_desc->nvdimm_bus;
|
|
|
if (nfit_spa_type(spa) == NFIT_SPA_PM) {
|
|
|
+ rc = acpi_nfit_insert_resource(acpi_desc, ndr_desc);
|
|
|
+ if (rc)
|
|
|
+ dev_warn(acpi_desc->dev,
|
|
|
+ "failed to insert pmem resource to iomem: %d\n",
|
|
|
+ rc);
|
|
|
+
|
|
|
rc = acpi_nfit_find_poison(acpi_desc, ndr_desc);
|
|
|
if (rc) {
|
|
|
dev_err(acpi_desc->dev,
|