linux/drivers/nvdimm/e820.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2015, Christoph Hellwig.
   3 * Copyright (c) 2015, Intel Corporation.
   4 */
   5#include <linux/platform_device.h>
   6#include <linux/memory_hotplug.h>
   7#include <linux/libnvdimm.h>
   8#include <linux/module.h>
   9
  10static const struct attribute_group *e820_pmem_attribute_groups[] = {
  11        &nvdimm_bus_attribute_group,
  12        NULL,
  13};
  14
  15static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
  16        &nd_region_attribute_group,
  17        &nd_device_attribute_group,
  18        NULL,
  19};
  20
  21static int e820_pmem_remove(struct platform_device *pdev)
  22{
  23        struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);
  24
  25        nvdimm_bus_unregister(nvdimm_bus);
  26        return 0;
  27}
  28
  29#ifdef CONFIG_MEMORY_HOTPLUG
  30static int e820_range_to_nid(resource_size_t addr)
  31{
  32        return memory_add_physaddr_to_nid(addr);
  33}
  34#else
  35static int e820_range_to_nid(resource_size_t addr)
  36{
  37        return NUMA_NO_NODE;
  38}
  39#endif
  40
  41static int e820_pmem_probe(struct platform_device *pdev)
  42{
  43        static struct nvdimm_bus_descriptor nd_desc;
  44        struct device *dev = &pdev->dev;
  45        struct nvdimm_bus *nvdimm_bus;
  46        struct resource *p;
  47
  48        nd_desc.attr_groups = e820_pmem_attribute_groups;
  49        nd_desc.provider_name = "e820";
  50        nd_desc.module = THIS_MODULE;
  51        nvdimm_bus = nvdimm_bus_register(dev, &nd_desc);
  52        if (!nvdimm_bus)
  53                goto err;
  54        platform_set_drvdata(pdev, nvdimm_bus);
  55
  56        for (p = iomem_resource.child; p ; p = p->sibling) {
  57                struct nd_region_desc ndr_desc;
  58
  59                if (p->desc != IORES_DESC_PERSISTENT_MEMORY_LEGACY)
  60                        continue;
  61
  62                memset(&ndr_desc, 0, sizeof(ndr_desc));
  63                ndr_desc.res = p;
  64                ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
  65                ndr_desc.numa_node = e820_range_to_nid(p->start);
  66                set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
  67                if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
  68                        goto err;
  69        }
  70
  71        return 0;
  72
  73 err:
  74        nvdimm_bus_unregister(nvdimm_bus);
  75        dev_err(dev, "failed to register legacy persistent memory ranges\n");
  76        return -ENXIO;
  77}
  78
  79static struct platform_driver e820_pmem_driver = {
  80        .probe = e820_pmem_probe,
  81        .remove = e820_pmem_remove,
  82        .driver = {
  83                .name = "e820_pmem",
  84        },
  85};
  86
  87module_platform_driver(e820_pmem_driver);
  88
  89MODULE_ALIAS("platform:e820_pmem*");
  90MODULE_LICENSE("GPL v2");
  91MODULE_AUTHOR("Intel Corporation");
  92