Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/platform_device.h>
  3#include <linux/memregion.h>
  4#include <linux/module.h>
  5#include <linux/dax.h>
  6#include <linux/mm.h>
  7
  8static bool nohmem;
  9module_param_named(disable, nohmem, bool, 0444);
 10
 11void hmem_register_device(int target_nid, struct resource *r)
 12{
 13	/* define a clean / non-busy resource for the platform device */
 14	struct resource res = {
 15		.start = r->start,
 16		.end = r->end,
 17		.flags = IORESOURCE_MEM,
 18	};
 19	struct platform_device *pdev;
 20	struct memregion_info info;
 21	int rc, id;
 22
 23	if (nohmem)
 24		return;
 25
 26	rc = region_intersects(res.start, resource_size(&res), IORESOURCE_MEM,
 27			IORES_DESC_SOFT_RESERVED);
 28	if (rc != REGION_INTERSECTS)
 29		return;
 30
 31	id = memregion_alloc(GFP_KERNEL);
 32	if (id < 0) {
 33		pr_err("memregion allocation failure for %pr\n", &res);
 34		return;
 35	}
 36
 37	pdev = platform_device_alloc("hmem", id);
 38	if (!pdev) {
 39		pr_err("hmem device allocation failure for %pr\n", &res);
 40		goto out_pdev;
 41	}
 42
 43	pdev->dev.numa_node = numa_map_to_online_node(target_nid);
 44	info = (struct memregion_info) {
 45		.target_node = target_nid,
 46	};
 47	rc = platform_device_add_data(pdev, &info, sizeof(info));
 48	if (rc < 0) {
 49		pr_err("hmem memregion_info allocation failure for %pr\n", &res);
 50		goto out_pdev;
 51	}
 52
 53	rc = platform_device_add_resources(pdev, &res, 1);
 54	if (rc < 0) {
 55		pr_err("hmem resource allocation failure for %pr\n", &res);
 56		goto out_resource;
 57	}
 58
 59	rc = platform_device_add(pdev);
 60	if (rc < 0) {
 61		dev_err(&pdev->dev, "device add failed for %pr\n", &res);
 62		goto out_resource;
 63	}
 64
 65	return;
 66
 67out_resource:
 68	put_device(&pdev->dev);
 69out_pdev:
 70	memregion_free(id);
 71}
 72
 73static __init int hmem_register_one(struct resource *res, void *data)
 74{
 75	/*
 76	 * If the resource is not a top-level resource it was already
 77	 * assigned to a device by the HMAT parsing.
 78	 */
 79	if (res->parent != &iomem_resource) {
 80		pr_info("HMEM: skip %pr, already claimed\n", res);
 81		return 0;
 82	}
 83
 84	hmem_register_device(phys_to_target_node(res->start), res);
 85
 86	return 0;
 87}
 88
 89static __init int hmem_init(void)
 90{
 91	walk_iomem_res_desc(IORES_DESC_SOFT_RESERVED,
 92			IORESOURCE_MEM, 0, -1, NULL, hmem_register_one);
 93	return 0;
 94}
 95
 96/*
 97 * As this is a fallback for address ranges unclaimed by the ACPI HMAT
 98 * parsing it must be at an initcall level greater than hmat_init().
 99 */
100late_initcall(hmem_init);