|
8 | 8 | static bool nohmem; |
9 | 9 | module_param_named(disable, nohmem, bool, 0444); |
10 | 10 |
|
| 11 | +static bool platform_initialized; |
| 12 | +static DEFINE_MUTEX(hmem_resource_lock); |
11 | 13 | static struct resource hmem_active = { |
12 | 14 | .name = "HMEM devices", |
13 | 15 | .start = 0, |
14 | 16 | .end = -1, |
15 | 17 | .flags = IORESOURCE_MEM, |
16 | 18 | }; |
17 | 19 |
|
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) |
19 | 37 | { |
20 | 38 | struct platform_device *pdev; |
21 | | - struct memregion_info info; |
22 | | - int rc, id; |
| 39 | + struct resource *new; |
| 40 | + int rc; |
23 | 41 |
|
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); |
25 | 46 | return; |
| 47 | + } |
26 | 48 |
|
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; |
31 | 50 |
|
32 | | - id = memregion_alloc(GFP_KERNEL); |
33 | | - if (id < 0) { |
34 | | - pr_err("memregion allocation failure for %pr\n", res); |
| 51 | + if (platform_initialized) |
35 | 52 | return; |
36 | | - } |
37 | 53 |
|
38 | | - pdev = platform_device_alloc("hmem", id); |
| 54 | + pdev = platform_device_alloc("hmem_platform", 0); |
39 | 55 | 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; |
62 | 58 | } |
63 | 59 |
|
64 | 60 | 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 | +} |
69 | 66 |
|
70 | | - return; |
| 67 | +void hmem_register_resource(int target_nid, struct resource *res) |
| 68 | +{ |
| 69 | + if (nohmem) |
| 70 | + return; |
71 | 71 |
|
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); |
78 | 75 | } |
79 | 76 |
|
80 | 77 | static __init int hmem_register_one(struct resource *res, void *data) |
81 | 78 | { |
82 | | - hmem_register_device(phys_to_target_node(res->start), res); |
| 79 | + hmem_register_resource(phys_to_target_node(res->start), res); |
83 | 80 |
|
84 | 81 | return 0; |
85 | 82 | } |
|
0 commit comments