[PATCH 26/26] tools/testing/cxl: Add Dynamic Capacity events

Ira Weiny
2024-03-24T23:18:33Z

cxl_test provides a good way to ensure quick smoke and regression
testing. The complexity of DCD and the new sparse DAX regions required
to use them benefits greatly with a series of smoke tests.

The only part of the kernel stack which must be bypassed is the actual
irq of DCD events. However, the event processing itself can be tested
via cxl_test calling directly the event processing function directly.

In this way the rest of the stack; management of sparse regions, the
extent device lifetimes, and the dax device operations can be tested.

Add Dynamic Capacity Device tests for kernels which have DCD support in
cxl_test.

Add events on DCD extent injection. Directly call the event irq
callback to simulate irqs to process the test extents.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
---
Changes for v1
[iweiny: Adjust to new events]
---
tools/testing/cxl/test/mem.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)

diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 7d1d897d9f2b..e7efb1d3e20f 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -2122,6 +2122,49 @@ static bool new_extent_valid(struct device *dev, size_t new_start,
return true;
}

+struct cxl_test_dcd {
+ uuid_t id;
+ struct cxl_event_dcd rec;
+} __packed;
+
+struct cxl_test_dcd dcd_event_rec_template = {
+ .id = CXL_EVENT_DC_EVENT_UUID,
+ .rec = {
+ .hdr = {
+ .length = sizeof(struct cxl_test_dcd),
+ },
+ },
+};
+
+static int log_dc_event(struct cxl_mockmem_data *mdata, enum dc_event type,
+ u64 start, u64 length, const char *tag_str)
+{
+ struct device *dev = mdata->mds->cxlds.dev;
+ struct cxl_test_dcd *dcd_event;
+
+ dev_dbg(dev, "mock device log event %d\n", type);
+
+ dcd_event = devm_kmemdup(dev, &dcd_event_rec_template,
+ sizeof(*dcd_event), GFP_KERNEL);
+ if (!dcd_event)
+ return -ENOMEM;
+
+ dcd_event->rec.event_type = type;
+ dcd_event->rec.extent.start_dpa = cpu_to_le64(start);
+ dcd_event->rec.extent.length = cpu_to_le64(length);
+ memcpy(dcd_event->rec.extent.tag, tag_str,
+ min(sizeof(dcd_event->rec.extent.tag),
+ strlen(tag_str)));
+
+ mes_add_event(mdata, CXL_EVENT_TYPE_DCD,
+ (struct cxl_event_record_raw *)dcd_event);
+
+ /* Fake the irq */
+ cxl_mem_get_event_records(mdata->mds, CXLDEV_EVENT_STATUS_DCD);
+
+ return 0;
+}
+
/*
* Format <start>:<length>:<tag>
*
@@ -2134,6 +2177,7 @@ static ssize_t dc_inject_extent_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct cxl_mockmem_data *mdata = dev_get_drvdata(dev);
unsigned long long start, length;
char *len_str, *tag_str;
size_t buf_len = count;
@@ -2181,6 +2225,12 @@ static ssize_t dc_inject_extent_store(struct device *dev,
return rc;
}

+ rc = log_dc_event(mdata, DCD_ADD_CAPACITY, start, length, tag_str);
+ if (rc) {
+ dev_err(dev, "Failed to add event %d\n", rc);
+ return rc;
+ }
+
return count;
}
static DEVICE_ATTR_WO(dc_inject_extent);
@@ -2190,8 +2240,10 @@ static ssize_t __dc_del_extent_store(struct device *dev,
const char *buf, size_t count,
enum dc_event type)
{
+ struct cxl_mockmem_data *mdata = dev_get_drvdata(dev);
unsigned long long start, length;
char *len_str;
+ int rc;

char *start_str __free(kfree) = kstrdup(buf, GFP_KERNEL);
if (!start_str)
@@ -2221,6 +2273,12 @@ static ssize_t __dc_del_extent_store(struct device *dev,
dev_dbg(dev, "Forcing delete of extent %#llx len:%#llx\n",
start, length);

+ rc = log_dc_event(mdata, type, start, length, "");
+ if (rc) {
+ dev_err(dev, "Failed to add event %d\n", rc);
+ return rc;
+ }
+
return count;
}

--
2.44.0