Merge branch 'for-79/disable-region-check' into pending
Add a check for memdev disable to see if there are active regions present
before disabling the device.
diff --git a/Documentation/cxl/cxl-create-region.txt b/Documentation/cxl/cxl-create-region.txt
index f11a412..b244af6 100644
--- a/Documentation/cxl/cxl-create-region.txt
+++ b/Documentation/cxl/cxl-create-region.txt
@@ -105,6 +105,12 @@
supplied, the first cross-host bridge (if available), decoder that
supports the largest interleave will be chosen.
+-Q::
+--enforce-qos::
+ Parameter to enforce qos_class mismatch failure. Region create operation
+ will fail of the qos_class of the root decoder and one of the memdev that
+ backs the region mismatches.
+
include::human-option.txt[]
include::debug-option.txt[]
diff --git a/Documentation/cxl/cxl-wait-sanitize.txt b/Documentation/cxl/cxl-wait-sanitize.txt
index 9047b74..e8f2044 100644
--- a/Documentation/cxl/cxl-wait-sanitize.txt
+++ b/Documentation/cxl/cxl-wait-sanitize.txt
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
cxl-wait-sanitize(1)
-======================
+====================
NAME
----
diff --git a/cxl/event_trace.c b/cxl/event_trace.c
index db8cc85..1b5aa09 100644
--- a/cxl/event_trace.c
+++ b/cxl/event_trace.c
@@ -109,7 +109,13 @@
struct tep_format_field *f = fields[i];
int len;
- if (f->flags & TEP_FIELD_IS_STRING) {
+ /*
+ * libtraceevent differentiates arrays and strings like this:
+ * array: TEP_FIELD_IS_[ARRAY | STRING]
+ * string: TEP_FIELD_IS_[ARRAY | STRING | DYNAMIC]
+ */
+ if ((f->flags & TEP_FIELD_IS_STRING) &&
+ ((f->flags & TEP_FIELD_IS_DYNAMIC))) {
char *str;
str = tep_get_field_raw(NULL, event, f->name, record, &len, 0);
diff --git a/cxl/json.c b/cxl/json.c
index 33800c6..0c27aba 100644
--- a/cxl/json.c
+++ b/cxl/json.c
@@ -578,6 +578,7 @@
struct json_object *jdev, *jobj;
unsigned long long serial, size;
int numa_node;
+ int qos_class;
jdev = json_object_new_object();
if (!jdev)
@@ -592,6 +593,13 @@
jobj = util_json_object_size(size, flags);
if (jobj)
json_object_object_add(jdev, "pmem_size", jobj);
+
+ qos_class = cxl_memdev_get_pmem_qos_class(memdev);
+ if (qos_class != CXL_QOS_CLASS_NONE) {
+ jobj = json_object_new_int(qos_class);
+ if (jobj)
+ json_object_object_add(jdev, "pmem_qos_class", jobj);
+ }
}
size = cxl_memdev_get_ram_size(memdev);
@@ -599,6 +607,13 @@
jobj = util_json_object_size(size, flags);
if (jobj)
json_object_object_add(jdev, "ram_size", jobj);
+
+ qos_class = cxl_memdev_get_ram_qos_class(memdev);
+ if (qos_class != CXL_QOS_CLASS_NONE) {
+ jobj = json_object_new_int(qos_class);
+ if (jobj)
+ json_object_object_add(jdev, "ram_qos_class", jobj);
+ }
}
if (flags & UTIL_JSON_HEALTH) {
@@ -857,6 +872,16 @@
jobj);
}
+ if (cxl_port_is_root(port)) {
+ int qos_class = cxl_root_decoder_get_qos_class(decoder);
+
+ if (qos_class != CXL_QOS_CLASS_NONE) {
+ jobj = json_object_new_int(qos_class);
+ if (jobj)
+ json_object_object_add(jdecoder, "qos_class", jobj);
+ }
+ }
+
json_object_set_userdata(jdecoder, decoder, NULL);
return jdecoder;
}
@@ -1002,6 +1027,12 @@
}
}
+ if (cxl_region_qos_class_mismatch(region)) {
+ jobj = json_object_new_boolean(true);
+ if (jobj)
+ json_object_object_add(jregion, "qos_class_mismatch", jobj);
+ }
+
json_object_set_userdata(jregion, region, NULL);
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index 0240e21..91725ac 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -414,6 +414,35 @@
return is_enabled(path);
}
+CXL_EXPORT bool cxl_region_qos_class_mismatch(struct cxl_region *region)
+{
+ struct cxl_decoder *root_decoder = cxl_region_get_decoder(region);
+ struct cxl_memdev_mapping *mapping;
+
+ cxl_mapping_foreach(region, mapping) {
+ struct cxl_decoder *decoder;
+ struct cxl_memdev *memdev;
+
+ decoder = cxl_mapping_get_decoder(mapping);
+ if (!decoder)
+ continue;
+
+ memdev = cxl_decoder_get_memdev(decoder);
+ if (!memdev)
+ continue;
+
+ if (region->mode == CXL_DECODER_MODE_RAM) {
+ if (root_decoder->qos_class != memdev->ram_qos_class)
+ return true;
+ } else if (region->mode == CXL_DECODER_MODE_PMEM) {
+ if (root_decoder->qos_class != memdev->pmem_qos_class)
+ return true;
+ }
+ }
+
+ return false;
+}
+
CXL_EXPORT int cxl_region_disable(struct cxl_region *region)
{
const char *devname = cxl_region_get_devname(region);
@@ -1260,6 +1289,18 @@
goto err_read;
memdev->ram_size = strtoull(buf, NULL, 0);
+ sprintf(path, "%s/pmem/qos_class", cxlmem_base);
+ if (sysfs_read_attr(ctx, path, buf) < 0)
+ memdev->pmem_qos_class = CXL_QOS_CLASS_NONE;
+ else
+ memdev->pmem_qos_class = atoi(buf);
+
+ sprintf(path, "%s/ram/qos_class", cxlmem_base);
+ if (sysfs_read_attr(ctx, path, buf) < 0)
+ memdev->ram_qos_class = CXL_QOS_CLASS_NONE;
+ else
+ memdev->ram_qos_class = atoi(buf);
+
sprintf(path, "%s/payload_max", cxlmem_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
goto err_read;
@@ -1483,6 +1524,16 @@
return memdev->ram_size;
}
+CXL_EXPORT int cxl_memdev_get_pmem_qos_class(struct cxl_memdev *memdev)
+{
+ return memdev->pmem_qos_class;
+}
+
+CXL_EXPORT int cxl_memdev_get_ram_qos_class(struct cxl_memdev *memdev)
+{
+ return memdev->ram_qos_class;
+}
+
CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev)
{
return memdev->firmware_version;
@@ -2186,6 +2237,12 @@
else
decoder->interleave_ways = strtoul(buf, NULL, 0);
+ sprintf(path, "%s/qos_class", cxldecoder_base);
+ if (sysfs_read_attr(ctx, path, buf) < 0)
+ decoder->qos_class = CXL_QOS_CLASS_NONE;
+ else
+ decoder->qos_class = atoi(buf);
+
switch (port->type) {
case CXL_PORT_ENDPOINT:
sprintf(path, "%s/dpa_resource", cxldecoder_base);
@@ -2380,6 +2437,14 @@
return decoder->size;
}
+CXL_EXPORT int cxl_root_decoder_get_qos_class(struct cxl_decoder *decoder)
+{
+ if (!cxl_port_is_root(decoder->port))
+ return -EINVAL;
+
+ return decoder->qos_class;
+}
+
CXL_EXPORT unsigned long long
cxl_decoder_get_dpa_resource(struct cxl_decoder *decoder)
{
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index 936484a..304d7fa 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -276,5 +276,9 @@
cxl_cmd_alert_config_set_enable_alert_actions;
cxl_cmd_new_set_alert_config;
cxl_memdev_wait_sanitize;
+ cxl_root_decoder_get_qos_class;
+ cxl_memdev_get_pmem_qos_class;
+ cxl_memdev_get_ram_qos_class;
+ cxl_region_qos_class_mismatch;
cxl_port_decoders_committed;
} LIBCXL_6;
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
index 30c8989..b6cd910 100644
--- a/cxl/lib/private.h
+++ b/cxl/lib/private.h
@@ -47,6 +47,8 @@
struct list_node list;
unsigned long long pmem_size;
unsigned long long ram_size;
+ int ram_qos_class;
+ int pmem_qos_class;
int payload_max;
size_t lsa_size;
struct kmod_module *module;
@@ -145,6 +147,7 @@
struct list_head targets;
struct list_head regions;
struct list_head stale_regions;
+ int qos_class;
};
enum cxl_decode_state {
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index ec0b1ce..fc6dd00 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -72,6 +72,8 @@
struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev);
unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev);
unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
+int cxl_memdev_get_pmem_qos_class(struct cxl_memdev *memdev);
+int cxl_memdev_get_ram_qos_class(struct cxl_memdev *memdev);
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
bool cxl_memdev_fw_update_in_progress(struct cxl_memdev *memdev);
size_t cxl_memdev_fw_update_get_remaining(struct cxl_memdev *memdev);
@@ -174,6 +176,8 @@
for (dport = cxl_dport_get_first(port); dport != NULL; \
dport = cxl_dport_get_next(dport))
+#define CXL_QOS_CLASS_NONE -1
+
struct cxl_decoder;
struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port);
struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder);
@@ -185,6 +189,7 @@
unsigned long long cxl_decoder_get_dpa_size(struct cxl_decoder *decoder);
unsigned long long
cxl_decoder_get_max_available_extent(struct cxl_decoder *decoder);
+int cxl_root_decoder_get_qos_class(struct cxl_decoder *decoder);
enum cxl_decoder_mode {
CXL_DECODER_MODE_NONE,
@@ -331,6 +336,7 @@
int cxl_region_clear_all_targets(struct cxl_region *region);
int cxl_region_decode_commit(struct cxl_region *region);
int cxl_region_decode_reset(struct cxl_region *region);
+bool cxl_region_qos_class_mismatch(struct cxl_region *region);
#define cxl_region_foreach(decoder, region) \
for (region = cxl_region_get_first(decoder); region != NULL; \
diff --git a/cxl/region.c b/cxl/region.c
index 3a762db..96aa593 100644
--- a/cxl/region.c
+++ b/cxl/region.c
@@ -32,6 +32,7 @@
bool force;
bool human;
bool debug;
+ bool enforce_qos;
} param = {
.ways = INT_MAX,
.granularity = INT_MAX,
@@ -49,6 +50,7 @@
const char **argv;
struct cxl_decoder *root_decoder;
enum cxl_decoder_mode mode;
+ bool enforce_qos;
};
enum region_actions {
@@ -81,7 +83,8 @@
"region uuid", "uuid for the new region (default: autogenerate)"), \
OPT_BOOLEAN('m', "memdevs", ¶m.memdevs, \
"non-option arguments are memdevs"), \
-OPT_BOOLEAN('u', "human", ¶m.human, "use human friendly number formats")
+OPT_BOOLEAN('u', "human", ¶m.human, "use human friendly number formats"), \
+OPT_BOOLEAN('Q', "enforce-qos", ¶m.enforce_qos, "enforce qos_class match")
static const struct option create_options[] = {
BASE_OPTIONS(),
@@ -360,6 +363,8 @@
}
}
+ p->enforce_qos = param.enforce_qos;
+
return 0;
err:
@@ -423,10 +428,52 @@
}
}
+static int create_region_validate_qos_class(struct parsed_params *p)
+{
+ int root_qos_class;
+ int qos_class;
+ int i;
+
+ if (!p->enforce_qos)
+ return 0;
+
+ root_qos_class = cxl_root_decoder_get_qos_class(p->root_decoder);
+ if (root_qos_class == CXL_QOS_CLASS_NONE)
+ return 0;
+
+ for (i = 0; i < p->ways; i++) {
+ struct json_object *jobj =
+ json_object_array_get_idx(p->memdevs, i);
+ struct cxl_memdev *memdev = json_object_get_userdata(jobj);
+
+ if (p->mode == CXL_DECODER_MODE_RAM)
+ qos_class = cxl_memdev_get_ram_qos_class(memdev);
+ else
+ qos_class = cxl_memdev_get_pmem_qos_class(memdev);
+
+ /* No qos_class entries. Possibly no kernel support */
+ if (qos_class == CXL_QOS_CLASS_NONE)
+ break;
+
+ if (qos_class != root_qos_class) {
+ if (p->enforce_qos) {
+ log_err(&rl, "%s qos_class mismatch %s\n",
+ cxl_decoder_get_devname(p->root_decoder),
+ cxl_memdev_get_devname(memdev));
+
+ return -ENXIO;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int validate_decoder(struct cxl_decoder *decoder,
struct parsed_params *p)
{
const char *devname = cxl_decoder_get_devname(decoder);
+ int rc;
switch(p->mode) {
case CXL_DECODER_MODE_RAM:
@@ -446,6 +493,10 @@
return -EINVAL;
}
+ rc = create_region_validate_qos_class(p);
+ if (rc)
+ return rc;
+
/* TODO check if the interleave config is possible under this decoder */
return 0;
diff --git a/test/common b/test/common
index f1023ef..75ff1a6 100644
--- a/test/common
+++ b/test/common
@@ -150,3 +150,6 @@
grep -q "Call Trace" <<< $log && err $1
true
}
+
+# CXL COMMON
+CXL_TEST_QOS_CLASS=42
diff --git a/test/cxl-qos-class.sh b/test/cxl-qos-class.sh
new file mode 100755
index 0000000..a31df13
--- /dev/null
+++ b/test/cxl-qos-class.sh
@@ -0,0 +1,100 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2024 Intel Corporation. All rights reserved.
+
+. $(dirname $0)/common
+
+rc=77
+
+set -ex
+
+trap 'err $LINENO' ERR
+
+check_prereq "jq"
+
+modprobe -r cxl_test
+modprobe cxl_test
+rc=1
+
+check_qos_decoders () {
+ # check root decoders have expected fake qos_class
+ # also make sure the number of root decoders equal to the number
+ # with qos_class found
+ json=$($CXL list -b cxl_test -D -d root)
+ num_decoders=$(echo "$json" | jq length)
+ count=0
+ while read -r qos_class; do
+ if [[ "$qos_class" != "$CXL_TEST_QOS_CLASS" ]]; then
+ err "$LINENO"
+ fi
+ count=$((count+1))
+ done <<< "$(echo "$json" | jq -r '.[] | .qos_class')"
+
+ if [[ "$count" != "$num_decoders" ]]; then
+ err "$LINENO"
+ fi
+}
+
+check_qos_memdevs () {
+ # Check that memdevs that expose ram_qos_class or pmem_qos_class have
+ # expected fake value programmed.
+ json=$($CXL list -b cxl_test -M)
+ num_memdevs=$(echo "$json" | jq length)
+
+ for (( i = 0; i < num_memdevs; i++ )); do
+ ram_size="$(jq ".[$i] | .ram_size" <<< "$json")"
+ ram_qos_class="$(jq ".[$i] | .ram_qos_class" <<< "$json")"
+ pmem_size="$(jq ".[$i] | .pmem_size" <<< "$json")"
+ pmem_qos_class="$(jq ".[$i] | .pmem_qos_class" <<< "$json")"
+
+ if [[ "$ram_size" != null ]] && ((ram_qos_class != CXL_TEST_QOS_CLASS)); then
+ err "$LINENO"
+ fi
+
+ if [[ "$pmem_size" != null ]] && ((pmem_qos_class != CXL_TEST_QOS_CLASS)); then
+ err "$LINENO"
+ fi
+ done
+}
+
+# Based on cxl-create-region.sh create_single()
+destroy_regions()
+{
+ if [[ "$*" ]]; then
+ $CXL destroy-region -f -b cxl_test "$@"
+ else
+ $CXL destroy-region -f -b cxl_test all
+ fi
+}
+
+create_region_check_qos()
+{
+ # Find an x1 decoder
+ decoder=$($CXL list -b cxl_test -D -d root | jq -r "[ .[] |
+ select(.max_available_extent > 0) |
+ select(.pmem_capable == true) |
+ select(.nr_targets == 1) ] |
+ .[0].decoder")
+
+ # Find a memdev for this host-bridge
+ port_dev0="$("$CXL" list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 0) | .target")"
+ mem0="$("$CXL" list -M -p "$port_dev0" | jq -r ".[0].memdev")"
+ memdevs="$mem0"
+
+ # Send create-region with -Q to enforce qos_class matching
+ region="$("$CXL" create-region -Q -d "$decoder" -m "$memdevs" | jq -r ".region")"
+ if [[ ! $region ]]; then
+ echo "failed to create region"
+ err "$LINENO"
+ fi
+
+ destroy_regions "$region"
+}
+
+check_qos_decoders
+check_qos_memdevs
+create_region_check_qos
+check_dmesg "$LINEO"
+
+modprobe -r cxl_test
diff --git a/test/cxl-xor-region.sh b/test/cxl-xor-region.sh
index 117e7a4..b9e1d79 100644
--- a/test/cxl-xor-region.sh
+++ b/test/cxl-xor-region.sh
@@ -23,7 +23,8 @@
create_and_destroy_region()
{
- region=$($CXL create-region -d $decoder -m $memdevs | jq -r ".region")
+ region=$($CXL create-region -d "$decoder" -m "$memdevs" |
+ jq -r ".region")
if [[ ! $region ]]; then
echo "create-region failed for $decoder"
@@ -35,55 +36,81 @@
setup_x1()
{
- # Find an x1 decoder
- decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
- select(.pmem_capable == true) |
- select(.nr_targets == 1) |
- .decoder")
+ # Find an x1 decoder
+ decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
+ select(.pmem_capable == true) |
+ select(.nr_targets == 1) |
+ .decoder")
- # Find a memdev for this host-bridge
- port_dev0=$($CXL list -T -d $decoder | jq -r ".[] |
- .targets | .[] | select(.position == 0) | .target")
- mem0=$($CXL list -M -p $port_dev0 | jq -r ".[0].memdev")
- memdevs="$mem0"
+ # Find a memdev for this host-bridge
+ port_dev0=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 0) | .target")
+ mem0=$($CXL list -M -p "$port_dev0" | jq -r ".[0].memdev")
+ memdevs="$mem0"
}
setup_x2()
{
- # Find an x2 decoder
- decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
- select(.pmem_capable == true) |
- select(.nr_targets == 2) |
- .decoder")
+ # Find an x2 decoder
+ decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
+ select(.pmem_capable == true) |
+ select(.nr_targets == 2) |
+ .decoder")
- # Find a memdev for each host-bridge interleave position
- port_dev0=$($CXL list -T -d $decoder | jq -r ".[] |
- .targets | .[] | select(.position == 0) | .target")
- port_dev1=$($CXL list -T -d $decoder | jq -r ".[] |
- .targets | .[] | select(.position == 1) | .target")
- mem0=$($CXL list -M -p $port_dev0 | jq -r ".[0].memdev")
- mem1=$($CXL list -M -p $port_dev1 | jq -r ".[0].memdev")
- memdevs="$mem0 $mem1"
+ # Find a memdev for each host-bridge interleave position
+ port_dev0=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 0) | .target")
+ port_dev1=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 1) | .target")
+ mem0=$($CXL list -M -p "$port_dev0" | jq -r ".[0].memdev")
+ mem1=$($CXL list -M -p "$port_dev1" | jq -r ".[0].memdev")
+ memdevs="$mem0 $mem1"
}
setup_x4()
{
- # find an x2 decoder
- decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
- select(.pmem_capable == true) |
- select(.nr_targets == 2) |
- .decoder")
+ # find an x2 decoder
+ decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
+ select(.pmem_capable == true) |
+ select(.nr_targets == 2) |
+ .decoder")
- # Find a memdev for each host-bridge interleave position
- port_dev0=$($CXL list -T -d $decoder | jq -r ".[] |
- .targets | .[] | select(.position == 0) | .target")
- port_dev1=$($CXL list -T -d $decoder | jq -r ".[] |
- .targets | .[] | select(.position == 1) | .target")
- mem0=$($CXL list -M -p $port_dev0 | jq -r ".[0].memdev")
- mem1=$($CXL list -M -p $port_dev1 | jq -r ".[0].memdev")
- mem2=$($CXL list -M -p $port_dev0 | jq -r ".[1].memdev")
- mem3=$($CXL list -M -p $port_dev1 | jq -r ".[1].memdev")
- memdevs="$mem0 $mem1 $mem2 $mem3"
+ # Find a memdev for each host-bridge interleave position
+ port_dev0=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 0) | .target")
+ port_dev1=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 1) | .target")
+ mem0=$($CXL list -M -p "$port_dev0" | jq -r ".[0].memdev")
+ mem1=$($CXL list -M -p "$port_dev1" | jq -r ".[0].memdev")
+ mem2=$($CXL list -M -p "$port_dev0" | jq -r ".[1].memdev")
+ mem3=$($CXL list -M -p "$port_dev1" | jq -r ".[1].memdev")
+ memdevs="$mem0 $mem1 $mem2 $mem3"
+}
+
+setup_x3()
+{
+ # find an x3 decoder
+ decoder=$($CXL list -b cxl_test -D -d root | jq -r ".[] |
+ select(.pmem_capable == true) |
+ select(.nr_targets == 3) |
+ .decoder")
+
+ if [[ ! $decoder ]]; then
+ echo "no x3 decoder found, skipping xor-x3 test"
+ return
+ fi
+
+ # Find a memdev for each host-bridge interleave position
+ port_dev0=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 0) | .target")
+ port_dev1=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 1) | .target")
+ port_dev2=$($CXL list -T -d "$decoder" | jq -r ".[] |
+ .targets | .[] | select(.position == 2) | .target")
+ mem0=$($CXL list -M -p "$port_dev0" | jq -r ".[0].memdev")
+ mem1=$($CXL list -M -p "$port_dev1" | jq -r ".[0].memdev")
+ mem2=$($CXL list -M -p "$port_dev2" | jq -r ".[0].memdev")
+ memdevs="$mem0 $mem1 $mem2"
}
setup_x1
@@ -92,5 +119,12 @@
create_and_destroy_region
setup_x4
create_and_destroy_region
+# x3 decoder may not be available in cxl/test topo yet
+setup_x3
+if [[ $decoder ]]; then
+ create_and_destroy_region
+fi
+
+check_dmesg "$LINENO"
modprobe -r cxl_test
diff --git a/test/meson.build b/test/meson.build
index 65db049..a965a79 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -159,6 +159,7 @@
cxl_events = find_program('cxl-events.sh')
cxl_sanitize = find_program('cxl-sanitize.sh')
cxl_destroy_region = find_program('cxl-destroy-region.sh')
+cxl_qos_class = find_program('cxl-qos-class.sh')
tests = [
[ 'libndctl', libndctl, 'ndctl' ],
@@ -190,6 +191,7 @@
[ 'cxl-events.sh', cxl_events, 'cxl' ],
[ 'cxl-sanitize.sh', cxl_sanitize, 'cxl' ],
[ 'cxl-destroy-region.sh', cxl_destroy_region, 'cxl' ],
+ [ 'cxl-qos-class.sh', cxl_qos_class, 'cxl' ],
]
if get_option('destructive').enabled()
diff --git a/util/json.c b/util/json.c
index 1d5c6bc..ba9daa3 100644
--- a/util/json.c
+++ b/util/json.c
@@ -75,7 +75,7 @@
static int display_hex(struct json_object *jobj, struct printbuf *pbuf,
int level, int flags)
{
- unsigned long long val = json_object_get_int64(jobj);
+ unsigned long long val = util_json_get_u64(jobj);
static char buf[32];
snprintf(buf, sizeof(buf), "\"%#llx\"", val);
diff --git a/util/json.h b/util/json.h
index ea370df..560f845 100644
--- a/util/json.h
+++ b/util/json.h
@@ -34,10 +34,22 @@
{
return json_object_new_uint64(val);
}
+
+static inline unsigned long long util_json_get_u64(struct json_object *jobj)
+{
+ return json_object_get_uint64(jobj);
+}
+
#else /* fallback to signed */
static inline struct json_object *util_json_new_u64(unsigned long long val)
{
return json_object_new_int64(val);
}
+
+static inline unsigned long long util_json_get_u64(struct json_object *jobj)
+{
+ return json_object_get_int64(jobj);
+}
+
#endif /* HAVE_JSON_U64 */
#endif /* __UTIL_JSON_H__ */