1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/platform_device.h>
3 #include <linux/memregion.h>
4 #include <linux/module.h>
9 module_param_named(disable, nohmem, bool, 0444);
11 static struct resource hmem_active = {
12 .name = "HMEM devices",
15 .flags = IORESOURCE_MEM,
18 void hmem_register_device(int target_nid, struct resource *r)
20 /* define a clean / non-busy resource for the platform device */
21 struct resource res = {
24 .flags = IORESOURCE_MEM,
25 .desc = IORES_DESC_SOFT_RESERVED,
27 struct platform_device *pdev;
28 struct memregion_info info;
34 rc = region_intersects(res.start, resource_size(&res), IORESOURCE_MEM,
35 IORES_DESC_SOFT_RESERVED);
36 if (rc != REGION_INTERSECTS)
39 id = memregion_alloc(GFP_KERNEL);
41 pr_err("memregion allocation failure for %pr\n", &res);
45 pdev = platform_device_alloc("hmem", id);
47 pr_err("hmem device allocation failure for %pr\n", &res);
51 if (!__request_region(&hmem_active, res.start, resource_size(&res),
52 dev_name(&pdev->dev), 0)) {
53 dev_dbg(&pdev->dev, "hmem range %pr already active\n", &res);
57 pdev->dev.numa_node = numa_map_to_online_node(target_nid);
58 info = (struct memregion_info) {
59 .target_node = target_nid,
61 rc = platform_device_add_data(pdev, &info, sizeof(info));
63 pr_err("hmem memregion_info allocation failure for %pr\n", &res);
67 rc = platform_device_add_resources(pdev, &res, 1);
69 pr_err("hmem resource allocation failure for %pr\n", &res);
73 rc = platform_device_add(pdev);
75 dev_err(&pdev->dev, "device add failed for %pr\n", &res);
82 __release_region(&hmem_active, res.start, resource_size(&res));
84 platform_device_put(pdev);
89 static __init int hmem_register_one(struct resource *res, void *data)
91 hmem_register_device(phys_to_target_node(res->start), res);
96 static __init int hmem_init(void)
98 walk_iomem_res_desc(IORES_DESC_SOFT_RESERVED,
99 IORESOURCE_MEM, 0, -1, NULL, hmem_register_one);
104 * As this is a fallback for address ranges unclaimed by the ACPI HMAT
105 * parsing it must be at an initcall level greater than hmat_init().
107 late_initcall(hmem_init);