Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/dax/hmem/device.c
26428 views
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
8
static bool nohmem;
9
module_param_named(disable, nohmem, bool, 0444);
10
11
static bool platform_initialized;
12
static DEFINE_MUTEX(hmem_resource_lock);
13
static struct resource hmem_active = {
14
.name = "HMEM devices",
15
.start = 0,
16
.end = -1,
17
.flags = IORESOURCE_MEM,
18
};
19
20
int walk_hmem_resources(struct device *host, walk_hmem_fn fn)
21
{
22
struct resource *res;
23
int rc = 0;
24
25
mutex_lock(&hmem_resource_lock);
26
for (res = hmem_active.child; res; res = res->sibling) {
27
rc = fn(host, (int) res->desc, res);
28
if (rc)
29
break;
30
}
31
mutex_unlock(&hmem_resource_lock);
32
return rc;
33
}
34
EXPORT_SYMBOL_GPL(walk_hmem_resources);
35
36
static void __hmem_register_resource(int target_nid, struct resource *res)
37
{
38
struct platform_device *pdev;
39
struct resource *new;
40
int rc;
41
42
new = __request_region(&hmem_active, res->start, resource_size(res), "",
43
0);
44
if (!new) {
45
pr_debug("hmem range %pr already active\n", res);
46
return;
47
}
48
49
new->desc = target_nid;
50
51
if (platform_initialized)
52
return;
53
54
pdev = platform_device_alloc("hmem_platform", 0);
55
if (!pdev) {
56
pr_err_once("failed to register device-dax hmem_platform device\n");
57
return;
58
}
59
60
rc = platform_device_add(pdev);
61
if (rc)
62
platform_device_put(pdev);
63
else
64
platform_initialized = true;
65
}
66
67
void hmem_register_resource(int target_nid, struct resource *res)
68
{
69
if (nohmem)
70
return;
71
72
mutex_lock(&hmem_resource_lock);
73
__hmem_register_resource(target_nid, res);
74
mutex_unlock(&hmem_resource_lock);
75
}
76
77
static __init int hmem_register_one(struct resource *res, void *data)
78
{
79
hmem_register_resource(phys_to_target_node(res->start), res);
80
81
return 0;
82
}
83
84
static __init int hmem_init(void)
85
{
86
walk_iomem_res_desc(IORES_DESC_SOFT_RESERVED,
87
IORESOURCE_MEM, 0, -1, NULL, hmem_register_one);
88
return 0;
89
}
90
91
/*
92
* As this is a fallback for address ranges unclaimed by the ACPI HMAT
93
* parsing it must be at an initcall level greater than hmat_init().
94
*/
95
device_initcall(hmem_init);
96
97