mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
The current probe time ownership check for Soft Reserved memory based solely on CXL window intersection is insufficient. dax_hmem probing is not always guaranteed to run after CXL enumeration and region assembly, which can lead to incorrect ownership decisions before the CXL stack has finished publishing windows and assembling committed regions. Introduce deferred ownership handling for Soft Reserved ranges that intersect CXL windows. When such a range is encountered during the initial dax_hmem probe, schedule deferred work to wait for the CXL stack to complete enumeration and region assembly before deciding ownership. Once the deferred work runs, evaluate each Soft Reserved range individually: if a CXL region fully contains the range, skip it and let dax_cxl bind. Otherwise, register it with dax_hmem. This per-range ownership model avoids the need for CXL region teardown and alloc_dax_region() resource exclusion prevents double claiming. Introduce a boolean flag dax_hmem_initial_probe to live inside device.c so it survives module reload. Ensure dax_cxl defers driver registration until dax_hmem has completed ownership resolution. dax_cxl calls dax_hmem_flush_work() before cxl_driver_register(), which both waits for the deferred work to complete and creates a module symbol dependency that forces dax_hmem.ko to load before dax_cxl. Co-developed-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Link: https://patch.msgid.link/20260322195343.206900-9-Smita.KoralahalliChannabasappa@amd.com Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com>
76 lines
1.9 KiB
C
76 lines
1.9 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/* Copyright(c) 2023 Intel Corporation. All rights reserved. */
|
|
#include <linux/module.h>
|
|
#include <linux/dax.h>
|
|
|
|
#include "../cxl/cxl.h"
|
|
#include "bus.h"
|
|
|
|
static int cxl_dax_region_probe(struct device *dev)
|
|
{
|
|
struct cxl_dax_region *cxlr_dax = to_cxl_dax_region(dev);
|
|
int nid = phys_to_target_node(cxlr_dax->hpa_range.start);
|
|
struct cxl_region *cxlr = cxlr_dax->cxlr;
|
|
struct dax_region *dax_region;
|
|
struct dev_dax_data data;
|
|
|
|
if (nid == NUMA_NO_NODE)
|
|
nid = memory_add_physaddr_to_nid(cxlr_dax->hpa_range.start);
|
|
|
|
dax_region = alloc_dax_region(dev, cxlr->id, &cxlr_dax->hpa_range, nid,
|
|
PMD_SIZE, IORESOURCE_DAX_KMEM);
|
|
if (!dax_region)
|
|
return -ENOMEM;
|
|
|
|
data = (struct dev_dax_data) {
|
|
.dax_region = dax_region,
|
|
.id = -1,
|
|
.size = range_len(&cxlr_dax->hpa_range),
|
|
.memmap_on_memory = true,
|
|
};
|
|
|
|
return PTR_ERR_OR_ZERO(devm_create_dev_dax(&data));
|
|
}
|
|
|
|
static struct cxl_driver cxl_dax_region_driver = {
|
|
.name = "cxl_dax_region",
|
|
.probe = cxl_dax_region_probe,
|
|
.id = CXL_DEVICE_DAX_REGION,
|
|
.drv = {
|
|
.suppress_bind_attrs = true,
|
|
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
|
},
|
|
};
|
|
|
|
static void cxl_dax_region_driver_register(struct work_struct *work)
|
|
{
|
|
dax_hmem_flush_work();
|
|
cxl_driver_register(&cxl_dax_region_driver);
|
|
}
|
|
|
|
static DECLARE_WORK(cxl_dax_region_driver_work, cxl_dax_region_driver_register);
|
|
|
|
static int __init cxl_dax_region_init(void)
|
|
{
|
|
/*
|
|
* Need to resolve a race with dax_hmem wanting to drive regions
|
|
* instead of CXL
|
|
*/
|
|
queue_work(system_long_wq, &cxl_dax_region_driver_work);
|
|
return 0;
|
|
}
|
|
module_init(cxl_dax_region_init);
|
|
|
|
static void __exit cxl_dax_region_exit(void)
|
|
{
|
|
flush_work(&cxl_dax_region_driver_work);
|
|
cxl_driver_unregister(&cxl_dax_region_driver);
|
|
}
|
|
module_exit(cxl_dax_region_exit);
|
|
|
|
MODULE_ALIAS_CXL(CXL_DEVICE_DAX_REGION);
|
|
MODULE_DESCRIPTION("CXL DAX: direct access to CXL regions");
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Intel Corporation");
|
|
MODULE_IMPORT_NS("CXL");
|