Skip to content

Commit 7dab174

Browse files
committed
dax/hmem: Move hmem device registration to dax_hmem.ko
In preparation for the CXL region driver to take over the responsibility of registering device-dax instances for CXL regions, move the registration of "hmem" devices to dax_hmem.ko. Previously the builtin component of this enabling (drivers/dax/hmem/device.o) would register platform devices for each address range and trigger the dax_hmem.ko module to load and attach device-dax instances to those devices. Now, the ranges are collected from the HMAT and EFI memory map walking, but the device creation is deferred. A new "hmem_platform" device is created which triggers dax_hmem.ko to load and register the platform devices. Tested-by: Fan Ni <[email protected]> Reviewed-by: Dave Jiang <[email protected]> Reviewed-by: Jonathan Cameron <[email protected]> Link: https://lore.kernel.org/r/167602002771.1924368.5653558226424530127.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent fe09857 commit 7dab174

File tree

5 files changed

+155
-52
lines changed

5 files changed

+155
-52
lines changed

drivers/acpi/numa/hmat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,7 @@ static void hmat_register_target_devices(struct memory_target *target)
718718
for (res = target->memregions.child; res; res = res->sibling) {
719719
int target_nid = pxm_to_node(target->memory_pxm);
720720

721-
hmem_register_device(target_nid, res);
721+
hmem_register_resource(target_nid, res);
722722
}
723723
}
724724

drivers/dax/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ config DEV_DAX_HMEM
4646
Say M if unsure.
4747

4848
config DEV_DAX_HMEM_DEVICES
49-
depends on DEV_DAX_HMEM && DAX=y
49+
depends on DEV_DAX_HMEM && DAX
5050
def_bool y
5151

5252
config DEV_DAX_KMEM

drivers/dax/hmem/device.c

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,78 +8,75 @@
88
static bool nohmem;
99
module_param_named(disable, nohmem, bool, 0444);
1010

11+
static bool platform_initialized;
12+
static DEFINE_MUTEX(hmem_resource_lock);
1113
static struct resource hmem_active = {
1214
.name = "HMEM devices",
1315
.start = 0,
1416
.end = -1,
1517
.flags = IORESOURCE_MEM,
1618
};
1719

18-
void hmem_register_device(int target_nid, struct resource *res)
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)
1937
{
2038
struct platform_device *pdev;
21-
struct memregion_info info;
22-
int rc, id;
39+
struct resource *new;
40+
int rc;
2341

24-
if (nohmem)
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);
2546
return;
47+
}
2648

27-
rc = region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
28-
IORES_DESC_SOFT_RESERVED);
29-
if (rc != REGION_INTERSECTS)
30-
return;
49+
new->desc = target_nid;
3150

32-
id = memregion_alloc(GFP_KERNEL);
33-
if (id < 0) {
34-
pr_err("memregion allocation failure for %pr\n", res);
51+
if (platform_initialized)
3552
return;
36-
}
3753

38-
pdev = platform_device_alloc("hmem", id);
54+
pdev = platform_device_alloc("hmem_platform", 0);
3955
if (!pdev) {
40-
pr_err("hmem device allocation failure for %pr\n", res);
41-
goto out_pdev;
42-
}
43-
44-
if (!__request_region(&hmem_active, res->start, resource_size(res),
45-
dev_name(&pdev->dev), 0)) {
46-
dev_dbg(&pdev->dev, "hmem range %pr already active\n", res);
47-
goto out_active;
48-
}
49-
50-
pdev->dev.numa_node = numa_map_to_online_node(target_nid);
51-
info = (struct memregion_info) {
52-
.target_node = target_nid,
53-
.range = {
54-
.start = res->start,
55-
.end = res->end,
56-
},
57-
};
58-
rc = platform_device_add_data(pdev, &info, sizeof(info));
59-
if (rc < 0) {
60-
pr_err("hmem memregion_info allocation failure for %pr\n", res);
61-
goto out_resource;
56+
pr_err_once("failed to register device-dax hmem_platform device\n");
57+
return;
6258
}
6359

6460
rc = platform_device_add(pdev);
65-
if (rc < 0) {
66-
dev_err(&pdev->dev, "device add failed for %pr\n", res);
67-
goto out_resource;
68-
}
61+
if (rc)
62+
platform_device_put(pdev);
63+
else
64+
platform_initialized = true;
65+
}
6966

70-
return;
67+
void hmem_register_resource(int target_nid, struct resource *res)
68+
{
69+
if (nohmem)
70+
return;
7171

72-
out_resource:
73-
__release_region(&hmem_active, res->start, resource_size(res));
74-
out_active:
75-
platform_device_put(pdev);
76-
out_pdev:
77-
memregion_free(id);
72+
mutex_lock(&hmem_resource_lock);
73+
__hmem_register_resource(target_nid, res);
74+
mutex_unlock(&hmem_resource_lock);
7875
}
7976

8077
static __init int hmem_register_one(struct resource *res, void *data)
8178
{
82-
hmem_register_device(phys_to_target_node(res->start), res);
79+
hmem_register_resource(phys_to_target_node(res->start), res);
8380

8481
return 0;
8582
}

drivers/dax/hmem/hmem.c

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <linux/memregion.h>
44
#include <linux/module.h>
55
#include <linux/pfn_t.h>
6+
#include <linux/dax.h>
67
#include "../bus.h"
78

89
static bool region_idle;
@@ -43,8 +44,110 @@ static struct platform_driver dax_hmem_driver = {
4344
},
4445
};
4546

46-
module_platform_driver(dax_hmem_driver);
47+
static void release_memregion(void *data)
48+
{
49+
memregion_free((long) data);
50+
}
51+
52+
static void release_hmem(void *pdev)
53+
{
54+
platform_device_unregister(pdev);
55+
}
56+
57+
static int hmem_register_device(struct device *host, int target_nid,
58+
const struct resource *res)
59+
{
60+
struct platform_device *pdev;
61+
struct memregion_info info;
62+
long id;
63+
int rc;
64+
65+
rc = region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
66+
IORES_DESC_SOFT_RESERVED);
67+
if (rc != REGION_INTERSECTS)
68+
return 0;
69+
70+
id = memregion_alloc(GFP_KERNEL);
71+
if (id < 0) {
72+
dev_err(host, "memregion allocation failure for %pr\n", res);
73+
return -ENOMEM;
74+
}
75+
rc = devm_add_action_or_reset(host, release_memregion, (void *) id);
76+
if (rc)
77+
return rc;
78+
79+
pdev = platform_device_alloc("hmem", id);
80+
if (!pdev) {
81+
dev_err(host, "device allocation failure for %pr\n", res);
82+
return -ENOMEM;
83+
}
84+
85+
pdev->dev.numa_node = numa_map_to_online_node(target_nid);
86+
info = (struct memregion_info) {
87+
.target_node = target_nid,
88+
.range = {
89+
.start = res->start,
90+
.end = res->end,
91+
},
92+
};
93+
rc = platform_device_add_data(pdev, &info, sizeof(info));
94+
if (rc < 0) {
95+
dev_err(host, "memregion_info allocation failure for %pr\n",
96+
res);
97+
goto out_put;
98+
}
99+
100+
rc = platform_device_add(pdev);
101+
if (rc < 0) {
102+
dev_err(host, "%s add failed for %pr\n", dev_name(&pdev->dev),
103+
res);
104+
goto out_put;
105+
}
106+
107+
return devm_add_action_or_reset(host, release_hmem, pdev);
108+
109+
out_put:
110+
platform_device_put(pdev);
111+
return rc;
112+
}
113+
114+
static int dax_hmem_platform_probe(struct platform_device *pdev)
115+
{
116+
return walk_hmem_resources(&pdev->dev, hmem_register_device);
117+
}
118+
119+
static struct platform_driver dax_hmem_platform_driver = {
120+
.probe = dax_hmem_platform_probe,
121+
.driver = {
122+
.name = "hmem_platform",
123+
},
124+
};
125+
126+
static __init int dax_hmem_init(void)
127+
{
128+
int rc;
129+
130+
rc = platform_driver_register(&dax_hmem_platform_driver);
131+
if (rc)
132+
return rc;
133+
134+
rc = platform_driver_register(&dax_hmem_driver);
135+
if (rc)
136+
platform_driver_unregister(&dax_hmem_platform_driver);
137+
138+
return rc;
139+
}
140+
141+
static __exit void dax_hmem_exit(void)
142+
{
143+
platform_driver_unregister(&dax_hmem_driver);
144+
platform_driver_unregister(&dax_hmem_platform_driver);
145+
}
146+
147+
module_init(dax_hmem_init);
148+
module_exit(dax_hmem_exit);
47149

48150
MODULE_ALIAS("platform:hmem*");
151+
MODULE_ALIAS("platform:hmem_platform*");
49152
MODULE_LICENSE("GPL v2");
50153
MODULE_AUTHOR("Intel Corporation");

include/linux/dax.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,14 @@ static inline bool dax_mapping(struct address_space *mapping)
262262
}
263263

264264
#ifdef CONFIG_DEV_DAX_HMEM_DEVICES
265-
void hmem_register_device(int target_nid, struct resource *r);
265+
void hmem_register_resource(int target_nid, struct resource *r);
266266
#else
267-
static inline void hmem_register_device(int target_nid, struct resource *r)
267+
static inline void hmem_register_resource(int target_nid, struct resource *r)
268268
{
269269
}
270270
#endif
271271

272+
typedef int (*walk_hmem_fn)(struct device *dev, int target_nid,
273+
const struct resource *res);
274+
int walk_hmem_resources(struct device *dev, walk_hmem_fn fn);
272275
#endif

0 commit comments

Comments
 (0)