forked from Minki/linux
004f1afbe1
The expectation is that the legacy / non-standard pmem discovery method (e820 type-12) will only ever be used to describe small quantities of persistent memory. Larger capacities will be described via the ACPI NFIT. When "allocate struct page from pmem" support is added this default policy can be overridden by assigning a legacy pmem namespace to a pfn device, however this would be only be necessary if a platform used the legacy mechanism to define a very large range. Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
88 lines
2.0 KiB
C
88 lines
2.0 KiB
C
/*
|
|
* Copyright (c) 2015, Christoph Hellwig.
|
|
* Copyright (c) 2015, Intel Corporation.
|
|
*/
|
|
#include <linux/platform_device.h>
|
|
#include <linux/libnvdimm.h>
|
|
#include <linux/module.h>
|
|
|
|
static const struct attribute_group *e820_pmem_attribute_groups[] = {
|
|
&nvdimm_bus_attribute_group,
|
|
NULL,
|
|
};
|
|
|
|
static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
|
|
&nd_region_attribute_group,
|
|
&nd_device_attribute_group,
|
|
NULL,
|
|
};
|
|
|
|
static int e820_pmem_remove(struct platform_device *pdev)
|
|
{
|
|
struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);
|
|
|
|
nvdimm_bus_unregister(nvdimm_bus);
|
|
return 0;
|
|
}
|
|
|
|
static int e820_pmem_probe(struct platform_device *pdev)
|
|
{
|
|
static struct nvdimm_bus_descriptor nd_desc;
|
|
struct device *dev = &pdev->dev;
|
|
struct nvdimm_bus *nvdimm_bus;
|
|
struct resource *p;
|
|
|
|
nd_desc.attr_groups = e820_pmem_attribute_groups;
|
|
nd_desc.provider_name = "e820";
|
|
nvdimm_bus = nvdimm_bus_register(dev, &nd_desc);
|
|
if (!nvdimm_bus)
|
|
goto err;
|
|
platform_set_drvdata(pdev, nvdimm_bus);
|
|
|
|
for (p = iomem_resource.child; p ; p = p->sibling) {
|
|
struct nd_region_desc ndr_desc;
|
|
|
|
if (strncmp(p->name, "Persistent Memory (legacy)", 26) != 0)
|
|
continue;
|
|
|
|
memset(&ndr_desc, 0, sizeof(ndr_desc));
|
|
ndr_desc.res = p;
|
|
ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
|
|
ndr_desc.numa_node = NUMA_NO_NODE;
|
|
set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
|
|
if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
|
|
goto err;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
nvdimm_bus_unregister(nvdimm_bus);
|
|
dev_err(dev, "failed to register legacy persistent memory ranges\n");
|
|
return -ENXIO;
|
|
}
|
|
|
|
static struct platform_driver e820_pmem_driver = {
|
|
.probe = e820_pmem_probe,
|
|
.remove = e820_pmem_remove,
|
|
.driver = {
|
|
.name = "e820_pmem",
|
|
},
|
|
};
|
|
|
|
static __init int e820_pmem_init(void)
|
|
{
|
|
return platform_driver_register(&e820_pmem_driver);
|
|
}
|
|
|
|
static __exit void e820_pmem_exit(void)
|
|
{
|
|
platform_driver_unregister(&e820_pmem_driver);
|
|
}
|
|
|
|
MODULE_ALIAS("platform:e820_pmem*");
|
|
MODULE_LICENSE("GPL v2");
|
|
MODULE_AUTHOR("Intel Corporation");
|
|
module_init(e820_pmem_init);
|
|
module_exit(e820_pmem_exit);
|