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