pmem.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * Copyright (c) 2015, Christoph Hellwig.
  3. * Copyright (c) 2015, Intel Corporation.
  4. */
  5. #include <linux/platform_device.h>
  6. #include <linux/libnvdimm.h>
  7. #include <linux/module.h>
  8. #include <asm/e820.h>
  9. static void e820_pmem_release(struct device *dev)
  10. {
  11. struct nvdimm_bus *nvdimm_bus = dev->platform_data;
  12. if (nvdimm_bus)
  13. nvdimm_bus_unregister(nvdimm_bus);
  14. }
  15. static struct platform_device e820_pmem = {
  16. .name = "e820_pmem",
  17. .id = -1,
  18. .dev = {
  19. .release = e820_pmem_release,
  20. },
  21. };
  22. static const struct attribute_group *e820_pmem_attribute_groups[] = {
  23. &nvdimm_bus_attribute_group,
  24. NULL,
  25. };
  26. static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
  27. &nd_region_attribute_group,
  28. &nd_device_attribute_group,
  29. NULL,
  30. };
  31. static __init int register_e820_pmem(void)
  32. {
  33. static struct nvdimm_bus_descriptor nd_desc;
  34. struct device *dev = &e820_pmem.dev;
  35. struct nvdimm_bus *nvdimm_bus;
  36. int rc, i;
  37. rc = platform_device_register(&e820_pmem);
  38. if (rc)
  39. return rc;
  40. nd_desc.attr_groups = e820_pmem_attribute_groups;
  41. nd_desc.provider_name = "e820";
  42. nvdimm_bus = nvdimm_bus_register(dev, &nd_desc);
  43. if (!nvdimm_bus)
  44. goto err;
  45. dev->platform_data = nvdimm_bus;
  46. for (i = 0; i < e820.nr_map; i++) {
  47. struct e820entry *ei = &e820.map[i];
  48. struct resource res = {
  49. .flags = IORESOURCE_MEM,
  50. .start = ei->addr,
  51. .end = ei->addr + ei->size - 1,
  52. };
  53. struct nd_region_desc ndr_desc;
  54. if (ei->type != E820_PRAM)
  55. continue;
  56. memset(&ndr_desc, 0, sizeof(ndr_desc));
  57. ndr_desc.res = &res;
  58. ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
  59. ndr_desc.numa_node = NUMA_NO_NODE;
  60. if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
  61. goto err;
  62. }
  63. return 0;
  64. err:
  65. dev_err(dev, "failed to register legacy persistent memory ranges\n");
  66. platform_device_unregister(&e820_pmem);
  67. return -ENXIO;
  68. }
  69. device_initcall(register_e820_pmem);