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