Skip to content

Commit 8e4c411

Browse files
djbwdavejiang
authored andcommitted
cxl: Introduce 'struct cxl_dpa_partition' and 'struct cxl_range_info'
The pending efforts to add CXL Accelerator (type-2) device [1], and Dynamic Capacity (DCD) support [2], tripped on the no-longer-fit-for-purpose design in the CXL subsystem for tracking device-physical-address (DPA) metadata. Trip hazards include: - CXL Memory Devices need to consider a PMEM partition, but Accelerator devices with CXL.mem likely do not in the common case. - CXL Memory Devices enumerate DPA through Memory Device mailbox commands like Partition Info, Accelerators devices do not. - CXL Memory Devices that support DCD support more than 2 partitions. Some of the driver algorithms are awkward to expand to > 2 partition cases. - DPA performance data is a general capability that can be shared with accelerators, so tracking it in 'struct cxl_memdev_state' is no longer suitable. - Hardcoded assumptions around the PMEM partition always being index-1 if RAM is zero-sized or PMEM is zero sized. - 'enum cxl_decoder_mode' is sometimes a partition id and sometimes a memory property, it should be phased in favor of a partition id and the memory property comes from the partition info. Towards cleaning up those issues and allowing a smoother landing for the aforementioned pending efforts, introduce a 'struct cxl_dpa_partition' array to 'struct cxl_dev_state', and 'struct cxl_range_info' as a shared way for Memory Devices and Accelerators to initialize the DPA information in 'struct cxl_dev_state'. For now, split a new cxl_dpa_setup() from cxl_mem_create_range_info() to get the new data structure initialized, and cleanup some qos_class init. Follow on patches will go further to use the new data structure to cleanup algorithms that are better suited to loop over all possible partitions. cxl_dpa_setup() follows the locking expectations of mutating the device DPA map, and is suitable for Accelerator drivers to use. Accelerators likely only have one hardcoded 'ram' partition to convey to the cxl_core. Link: http://lore.kernel.org/20241230214445.27602-1-alejandro.lucero-palau@amd.com [1] Link: http://lore.kernel.org/20241210-dcd-type2-upstream-v8-0-812852504400@intel.com [2] Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Alejandro Lucero <alucerop@amd.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Tested-by: Alejandro Lucero <alucerop@amd.com> Link: https://patch.msgid.link/173864305827.668823.13978794102080021276.stgit@dwillia2-xfh.jf.intel.com Signed-off-by: Dave Jiang <dave.jiang@intel.com>
1 parent d77ca6c commit 8e4c411

File tree

8 files changed

+195
-100
lines changed

8 files changed

+195
-100
lines changed

drivers/cxl/core/cdat.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -261,27 +261,20 @@ static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds,
261261
struct device *dev = cxlds->dev;
262262
struct dsmas_entry *dent;
263263
unsigned long index;
264-
const struct resource *partition[] = {
265-
to_ram_res(cxlds),
266-
to_pmem_res(cxlds),
267-
};
268-
struct cxl_dpa_perf *perf[] = {
269-
to_ram_perf(cxlds),
270-
to_pmem_perf(cxlds),
271-
};
272264

273265
xa_for_each(dsmas_xa, index, dent) {
274266
bool found = false;
275267

276-
for (int i = 0; i < ARRAY_SIZE(partition); i++) {
277-
const struct resource *res = partition[i];
268+
for (int i = 0; i < cxlds->nr_partitions; i++) {
269+
struct resource *res = &cxlds->part[i].res;
278270
struct range range = {
279271
.start = res->start,
280272
.end = res->end,
281273
};
282274

283275
if (range_contains(&range, &dent->dpa_range)) {
284-
update_perf_entry(dev, dent, perf[i]);
276+
update_perf_entry(dev, dent,
277+
&cxlds->part[i].perf);
285278
found = true;
286279
break;
287280
}

drivers/cxl/core/hdm.c

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,9 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
327327
cxled->dpa_res = res;
328328
cxled->skip = skipped;
329329

330-
if (resource_contains(to_pmem_res(cxlds), res))
330+
if (to_pmem_res(cxlds) && resource_contains(to_pmem_res(cxlds), res))
331331
cxled->mode = CXL_DECODER_PMEM;
332-
else if (resource_contains(to_ram_res(cxlds), res))
332+
else if (to_ram_res(cxlds) && resource_contains(to_ram_res(cxlds), res))
333333
cxled->mode = CXL_DECODER_RAM;
334334
else {
335335
dev_warn(dev, "decoder%d.%d: %pr does not map any partition\n",
@@ -342,6 +342,90 @@ static int __cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
342342
return 0;
343343
}
344344

345+
static int add_dpa_res(struct device *dev, struct resource *parent,
346+
struct resource *res, resource_size_t start,
347+
resource_size_t size, const char *type)
348+
{
349+
int rc;
350+
351+
*res = (struct resource) {
352+
.name = type,
353+
.start = start,
354+
.end = start + size - 1,
355+
.flags = IORESOURCE_MEM,
356+
};
357+
if (resource_size(res) == 0) {
358+
dev_dbg(dev, "DPA(%s): no capacity\n", res->name);
359+
return 0;
360+
}
361+
rc = request_resource(parent, res);
362+
if (rc) {
363+
dev_err(dev, "DPA(%s): failed to track %pr (%d)\n", res->name,
364+
res, rc);
365+
return rc;
366+
}
367+
368+
dev_dbg(dev, "DPA(%s): %pr\n", res->name, res);
369+
370+
return 0;
371+
}
372+
373+
static const char *cxl_mode_name(enum cxl_partition_mode mode)
374+
{
375+
switch (mode) {
376+
case CXL_PARTMODE_RAM:
377+
return "ram";
378+
case CXL_PARTMODE_PMEM:
379+
return "pmem";
380+
default:
381+
return "";
382+
};
383+
}
384+
385+
/* if this fails the caller must destroy @cxlds, there is no recovery */
386+
int cxl_dpa_setup(struct cxl_dev_state *cxlds, const struct cxl_dpa_info *info)
387+
{
388+
struct device *dev = cxlds->dev;
389+
390+
guard(rwsem_write)(&cxl_dpa_rwsem);
391+
392+
if (cxlds->nr_partitions)
393+
return -EBUSY;
394+
395+
if (!info->size || !info->nr_partitions) {
396+
cxlds->dpa_res = DEFINE_RES_MEM(0, 0);
397+
cxlds->nr_partitions = 0;
398+
return 0;
399+
}
400+
401+
cxlds->dpa_res = DEFINE_RES_MEM(0, info->size);
402+
403+
for (int i = 0; i < info->nr_partitions; i++) {
404+
const struct cxl_dpa_part_info *part = &info->part[i];
405+
int rc;
406+
407+
cxlds->part[i].perf.qos_class = CXL_QOS_CLASS_INVALID;
408+
cxlds->part[i].mode = part->mode;
409+
410+
/* Require ordered + contiguous partitions */
411+
if (i) {
412+
const struct cxl_dpa_part_info *prev = &info->part[i - 1];
413+
414+
if (prev->range.end + 1 != part->range.start)
415+
return -EINVAL;
416+
}
417+
rc = add_dpa_res(dev, &cxlds->dpa_res, &cxlds->part[i].res,
418+
part->range.start, range_len(&part->range),
419+
cxl_mode_name(part->mode));
420+
if (rc)
421+
return rc;
422+
cxlds->nr_partitions++;
423+
}
424+
425+
return 0;
426+
}
427+
EXPORT_SYMBOL_GPL(cxl_dpa_setup);
428+
345429
int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
346430
resource_size_t base, resource_size_t len,
347431
resource_size_t skipped)

drivers/cxl/core/mbox.c

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,57 +1241,39 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd)
12411241
return rc;
12421242
}
12431243

1244-
static int add_dpa_res(struct device *dev, struct resource *parent,
1245-
struct resource *res, resource_size_t start,
1246-
resource_size_t size, const char *type)
1244+
static void add_part(struct cxl_dpa_info *info, u64 start, u64 size, enum cxl_partition_mode mode)
12471245
{
1248-
int rc;
1246+
int i = info->nr_partitions;
12491247

1250-
res->name = type;
1251-
res->start = start;
1252-
res->end = start + size - 1;
1253-
res->flags = IORESOURCE_MEM;
1254-
if (resource_size(res) == 0) {
1255-
dev_dbg(dev, "DPA(%s): no capacity\n", res->name);
1256-
return 0;
1257-
}
1258-
rc = request_resource(parent, res);
1259-
if (rc) {
1260-
dev_err(dev, "DPA(%s): failed to track %pr (%d)\n", res->name,
1261-
res, rc);
1262-
return rc;
1263-
}
1264-
1265-
dev_dbg(dev, "DPA(%s): %pr\n", res->name, res);
1248+
if (size == 0)
1249+
return;
12661250

1267-
return 0;
1251+
info->part[i].range = (struct range) {
1252+
.start = start,
1253+
.end = start + size - 1,
1254+
};
1255+
info->part[i].mode = mode;
1256+
info->nr_partitions++;
12681257
}
12691258

1270-
int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
1259+
int cxl_mem_dpa_fetch(struct cxl_memdev_state *mds, struct cxl_dpa_info *info)
12711260
{
12721261
struct cxl_dev_state *cxlds = &mds->cxlds;
1273-
struct resource *ram_res = to_ram_res(cxlds);
1274-
struct resource *pmem_res = to_pmem_res(cxlds);
12751262
struct device *dev = cxlds->dev;
12761263
int rc;
12771264

12781265
if (!cxlds->media_ready) {
1279-
cxlds->dpa_res = DEFINE_RES_MEM(0, 0);
1280-
*ram_res = DEFINE_RES_MEM(0, 0);
1281-
*pmem_res = DEFINE_RES_MEM(0, 0);
1266+
info->size = 0;
12821267
return 0;
12831268
}
12841269

1285-
cxlds->dpa_res = DEFINE_RES_MEM(0, mds->total_bytes);
1270+
info->size = mds->total_bytes;
12861271

12871272
if (mds->partition_align_bytes == 0) {
1288-
rc = add_dpa_res(dev, &cxlds->dpa_res, ram_res, 0,
1289-
mds->volatile_only_bytes, "ram");
1290-
if (rc)
1291-
return rc;
1292-
return add_dpa_res(dev, &cxlds->dpa_res, pmem_res,
1293-
mds->volatile_only_bytes,
1294-
mds->persistent_only_bytes, "pmem");
1273+
add_part(info, 0, mds->volatile_only_bytes, CXL_PARTMODE_RAM);
1274+
add_part(info, mds->volatile_only_bytes,
1275+
mds->persistent_only_bytes, CXL_PARTMODE_PMEM);
1276+
return 0;
12951277
}
12961278

12971279
rc = cxl_mem_get_partition_info(mds);
@@ -1300,15 +1282,13 @@ int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
13001282
return rc;
13011283
}
13021284

1303-
rc = add_dpa_res(dev, &cxlds->dpa_res, ram_res, 0,
1304-
mds->active_volatile_bytes, "ram");
1305-
if (rc)
1306-
return rc;
1307-
return add_dpa_res(dev, &cxlds->dpa_res, pmem_res,
1308-
mds->active_volatile_bytes,
1309-
mds->active_persistent_bytes, "pmem");
1285+
add_part(info, 0, mds->active_volatile_bytes, CXL_PARTMODE_RAM);
1286+
add_part(info, mds->active_volatile_bytes, mds->active_persistent_bytes,
1287+
CXL_PARTMODE_PMEM);
1288+
1289+
return 0;
13101290
}
1311-
EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, "CXL");
1291+
EXPORT_SYMBOL_NS_GPL(cxl_mem_dpa_fetch, "CXL");
13121292

13131293
int cxl_set_timestamp(struct cxl_memdev_state *mds)
13141294
{
@@ -1452,8 +1432,6 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
14521432
mds->cxlds.reg_map.host = dev;
14531433
mds->cxlds.reg_map.resource = CXL_RESOURCE_NONE;
14541434
mds->cxlds.type = CXL_DEVTYPE_CLASSMEM;
1455-
to_ram_perf(&mds->cxlds)->qos_class = CXL_QOS_CLASS_INVALID;
1456-
to_pmem_perf(&mds->cxlds)->qos_class = CXL_QOS_CLASS_INVALID;
14571435

14581436
return mds;
14591437
}

drivers/cxl/core/memdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static ssize_t ram_size_show(struct device *dev, struct device_attribute *attr,
8080
{
8181
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
8282
struct cxl_dev_state *cxlds = cxlmd->cxlds;
83-
unsigned long long len = resource_size(to_ram_res(cxlds));
83+
unsigned long long len = cxl_ram_size(cxlds);
8484

8585
return sysfs_emit(buf, "%#llx\n", len);
8686
}

0 commit comments

Comments
 (0)