Commit 7dab174e authored by Dan Williams's avatar Dan Williams

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: default avatarFan Ni <fan.ni@samsung.com>
Reviewed-by: default avatarDave Jiang <dave.jiang@intel.com>
Reviewed-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/167602002771.1924368.5653558226424530127.stgit@dwillia2-xfh.jf.intel.comSigned-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent fe098574
...@@ -718,7 +718,7 @@ static void hmat_register_target_devices(struct memory_target *target) ...@@ -718,7 +718,7 @@ static void hmat_register_target_devices(struct memory_target *target)
for (res = target->memregions.child; res; res = res->sibling) { for (res = target->memregions.child; res; res = res->sibling) {
int target_nid = pxm_to_node(target->memory_pxm); int target_nid = pxm_to_node(target->memory_pxm);
hmem_register_device(target_nid, res); hmem_register_resource(target_nid, res);
} }
} }
......
...@@ -46,7 +46,7 @@ config DEV_DAX_HMEM ...@@ -46,7 +46,7 @@ config DEV_DAX_HMEM
Say M if unsure. Say M if unsure.
config DEV_DAX_HMEM_DEVICES config DEV_DAX_HMEM_DEVICES
depends on DEV_DAX_HMEM && DAX=y depends on DEV_DAX_HMEM && DAX
def_bool y def_bool y
config DEV_DAX_KMEM config DEV_DAX_KMEM
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
static bool nohmem; static bool nohmem;
module_param_named(disable, nohmem, bool, 0444); module_param_named(disable, nohmem, bool, 0444);
static bool platform_initialized;
static DEFINE_MUTEX(hmem_resource_lock);
static struct resource hmem_active = { static struct resource hmem_active = {
.name = "HMEM devices", .name = "HMEM devices",
.start = 0, .start = 0,
...@@ -15,71 +17,66 @@ static struct resource hmem_active = { ...@@ -15,71 +17,66 @@ static struct resource hmem_active = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}; };
void hmem_register_device(int target_nid, struct resource *res) int walk_hmem_resources(struct device *host, walk_hmem_fn fn)
{
struct resource *res;
int rc = 0;
mutex_lock(&hmem_resource_lock);
for (res = hmem_active.child; res; res = res->sibling) {
rc = fn(host, (int) res->desc, res);
if (rc)
break;
}
mutex_unlock(&hmem_resource_lock);
return rc;
}
EXPORT_SYMBOL_GPL(walk_hmem_resources);
static void __hmem_register_resource(int target_nid, struct resource *res)
{ {
struct platform_device *pdev; struct platform_device *pdev;
struct memregion_info info; struct resource *new;
int rc, id; int rc;
if (nohmem) new = __request_region(&hmem_active, res->start, resource_size(res), "",
0);
if (!new) {
pr_debug("hmem range %pr already active\n", res);
return; return;
}
rc = region_intersects(res->start, resource_size(res), IORESOURCE_MEM, new->desc = target_nid;
IORES_DESC_SOFT_RESERVED);
if (rc != REGION_INTERSECTS)
return;
id = memregion_alloc(GFP_KERNEL); if (platform_initialized)
if (id < 0) {
pr_err("memregion allocation failure for %pr\n", res);
return; return;
}
pdev = platform_device_alloc("hmem", id); pdev = platform_device_alloc("hmem_platform", 0);
if (!pdev) { if (!pdev) {
pr_err("hmem device allocation failure for %pr\n", res); pr_err_once("failed to register device-dax hmem_platform device\n");
goto out_pdev; return;
}
if (!__request_region(&hmem_active, res->start, resource_size(res),
dev_name(&pdev->dev), 0)) {
dev_dbg(&pdev->dev, "hmem range %pr already active\n", res);
goto out_active;
}
pdev->dev.numa_node = numa_map_to_online_node(target_nid);
info = (struct memregion_info) {
.target_node = target_nid,
.range = {
.start = res->start,
.end = res->end,
},
};
rc = platform_device_add_data(pdev, &info, sizeof(info));
if (rc < 0) {
pr_err("hmem memregion_info allocation failure for %pr\n", res);
goto out_resource;
} }
rc = platform_device_add(pdev); rc = platform_device_add(pdev);
if (rc < 0) { if (rc)
dev_err(&pdev->dev, "device add failed for %pr\n", res); platform_device_put(pdev);
goto out_resource; else
} platform_initialized = true;
}
return; void hmem_register_resource(int target_nid, struct resource *res)
{
if (nohmem)
return;
out_resource: mutex_lock(&hmem_resource_lock);
__release_region(&hmem_active, res->start, resource_size(res)); __hmem_register_resource(target_nid, res);
out_active: mutex_unlock(&hmem_resource_lock);
platform_device_put(pdev);
out_pdev:
memregion_free(id);
} }
static __init int hmem_register_one(struct resource *res, void *data) static __init int hmem_register_one(struct resource *res, void *data)
{ {
hmem_register_device(phys_to_target_node(res->start), res); hmem_register_resource(phys_to_target_node(res->start), res);
return 0; return 0;
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/memregion.h> #include <linux/memregion.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/pfn_t.h> #include <linux/pfn_t.h>
#include <linux/dax.h>
#include "../bus.h" #include "../bus.h"
static bool region_idle; static bool region_idle;
...@@ -43,8 +44,110 @@ static struct platform_driver dax_hmem_driver = { ...@@ -43,8 +44,110 @@ static struct platform_driver dax_hmem_driver = {
}, },
}; };
module_platform_driver(dax_hmem_driver); static void release_memregion(void *data)
{
memregion_free((long) data);
}
static void release_hmem(void *pdev)
{
platform_device_unregister(pdev);
}
static int hmem_register_device(struct device *host, int target_nid,
const struct resource *res)
{
struct platform_device *pdev;
struct memregion_info info;
long id;
int rc;
rc = region_intersects(res->start, resource_size(res), IORESOURCE_MEM,
IORES_DESC_SOFT_RESERVED);
if (rc != REGION_INTERSECTS)
return 0;
id = memregion_alloc(GFP_KERNEL);
if (id < 0) {
dev_err(host, "memregion allocation failure for %pr\n", res);
return -ENOMEM;
}
rc = devm_add_action_or_reset(host, release_memregion, (void *) id);
if (rc)
return rc;
pdev = platform_device_alloc("hmem", id);
if (!pdev) {
dev_err(host, "device allocation failure for %pr\n", res);
return -ENOMEM;
}
pdev->dev.numa_node = numa_map_to_online_node(target_nid);
info = (struct memregion_info) {
.target_node = target_nid,
.range = {
.start = res->start,
.end = res->end,
},
};
rc = platform_device_add_data(pdev, &info, sizeof(info));
if (rc < 0) {
dev_err(host, "memregion_info allocation failure for %pr\n",
res);
goto out_put;
}
rc = platform_device_add(pdev);
if (rc < 0) {
dev_err(host, "%s add failed for %pr\n", dev_name(&pdev->dev),
res);
goto out_put;
}
return devm_add_action_or_reset(host, release_hmem, pdev);
out_put:
platform_device_put(pdev);
return rc;
}
static int dax_hmem_platform_probe(struct platform_device *pdev)
{
return walk_hmem_resources(&pdev->dev, hmem_register_device);
}
static struct platform_driver dax_hmem_platform_driver = {
.probe = dax_hmem_platform_probe,
.driver = {
.name = "hmem_platform",
},
};
static __init int dax_hmem_init(void)
{
int rc;
rc = platform_driver_register(&dax_hmem_platform_driver);
if (rc)
return rc;
rc = platform_driver_register(&dax_hmem_driver);
if (rc)
platform_driver_unregister(&dax_hmem_platform_driver);
return rc;
}
static __exit void dax_hmem_exit(void)
{
platform_driver_unregister(&dax_hmem_driver);
platform_driver_unregister(&dax_hmem_platform_driver);
}
module_init(dax_hmem_init);
module_exit(dax_hmem_exit);
MODULE_ALIAS("platform:hmem*"); MODULE_ALIAS("platform:hmem*");
MODULE_ALIAS("platform:hmem_platform*");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Intel Corporation"); MODULE_AUTHOR("Intel Corporation");
...@@ -262,11 +262,14 @@ static inline bool dax_mapping(struct address_space *mapping) ...@@ -262,11 +262,14 @@ static inline bool dax_mapping(struct address_space *mapping)
} }
#ifdef CONFIG_DEV_DAX_HMEM_DEVICES #ifdef CONFIG_DEV_DAX_HMEM_DEVICES
void hmem_register_device(int target_nid, struct resource *r); void hmem_register_resource(int target_nid, struct resource *r);
#else #else
static inline void hmem_register_device(int target_nid, struct resource *r) static inline void hmem_register_resource(int target_nid, struct resource *r)
{ {
} }
#endif #endif
typedef int (*walk_hmem_fn)(struct device *dev, int target_nid,
const struct resource *res);
int walk_hmem_resources(struct device *dev, walk_hmem_fn fn);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment