@@ -43,7 +43,8 @@ EXAMPLE
"memdev":"mem0",
"pmem_size":268435456,
"ram_size":0,
- "serial":0
+ "serial":0,
+ "host":"0000:35:00.0"
}
]
@@ -40,6 +40,7 @@ kernel, or to send data or trigger kernel operations for a given device.
struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx);
struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev);
struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev);
+const char *cxl_memdev_get_host(struct cxl_memdev *memdev)
#define cxl_memdev_foreach(ctx, memdev) \
for (memdev = cxl_memdev_get_first(ctx); \
@@ -54,6 +55,9 @@ memory device commands, see the port, decoder, and endpoint APIs to
determine what if any CXL Memory Resources are reachable given a
specific memdev.
+The host of a memdev is the PCIe Endpoint device that registered its CXL
+capabilities with the Linux CXL core.
+
=== MEMDEV: Attributes
----
int cxl_memdev_get_id(struct cxl_memdev *memdev);
@@ -219,6 +219,11 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
if (jobj)
json_object_object_add(jdev, "serial", jobj);
}
+
+ jobj = json_object_new_string(cxl_memdev_get_host(memdev));
+ if (jobj)
+ json_object_object_add(jdev, "host", jobj);
+
return jdev;
}
@@ -63,6 +63,7 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
free(memdev->firmware_version);
free(memdev->dev_buf);
free(memdev->dev_path);
+ free(memdev->host);
free(memdev);
}
@@ -297,6 +298,7 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
char *path = calloc(1, strlen(cxlmem_base) + 100);
struct cxl_ctx *ctx = parent;
struct cxl_memdev *memdev, *memdev_dup;
+ char *host, *rpath = NULL;
char buf[SYSFS_ATTR_SIZE];
struct stat st;
@@ -350,6 +352,22 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
if (!memdev->dev_path)
goto err_read;
+ rpath = realpath(cxlmem_base, NULL);
+ if (!rpath)
+ goto err_read;
+ host = strrchr(rpath, '/');
+ if (host) {
+ host[0] = '\0';
+ host = strrchr(rpath, '/');
+ }
+ if (!host)
+ goto err_read;
+ memdev->host = strdup(host + 1);
+ if (!memdev->host)
+ goto err_read;
+ free(rpath);
+ rpath = NULL;
+
sprintf(path, "%s/firmware_version", cxlmem_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
goto err_read;
@@ -381,6 +399,7 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
free(memdev->dev_buf);
free(memdev->dev_path);
free(memdev);
+ free(rpath);
err_dev:
free(path);
return NULL;
@@ -431,6 +450,11 @@ CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev)
return devpath_to_devname(memdev->dev_path);
}
+CXL_EXPORT const char *cxl_memdev_get_host(struct cxl_memdev *memdev)
+{
+ return memdev->host;
+}
+
CXL_EXPORT int cxl_memdev_get_major(struct cxl_memdev *memdev)
{
return memdev->major;
@@ -77,6 +77,7 @@ local:
LIBCXL_2 {
global:
cxl_memdev_get_serial;
+ cxl_memdev_get_host;
cxl_bus_get_first;
cxl_bus_get_next;
cxl_bus_get_provider;
@@ -22,6 +22,7 @@ struct cxl_memdev {
int id, major, minor;
void *dev_buf;
size_t buf_len;
+ char *host;
char *dev_path;
char *firmware_version;
struct cxl_ctx *ctx;
@@ -38,6 +38,7 @@ struct cxl_memdev *cxl_memdev_get_next(struct cxl_memdev *memdev);
int cxl_memdev_get_id(struct cxl_memdev *memdev);
unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev);
const char *cxl_memdev_get_devname(struct cxl_memdev *memdev);
+const char *cxl_memdev_get_host(struct cxl_memdev *memdev);
int cxl_memdev_get_major(struct cxl_memdev *memdev);
int cxl_memdev_get_minor(struct cxl_memdev *memdev);
struct cxl_ctx *cxl_memdev_get_ctx(struct cxl_memdev *memdev);
For debugging CXL port connectivity issues it will be useful to have the PCI device name for the memory expander in the 'memdev' listing. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- Documentation/cxl/cxl-list.txt | 3 ++- Documentation/cxl/lib/libcxl.txt | 4 ++++ cxl/json.c | 5 +++++ cxl/lib/libcxl.c | 24 ++++++++++++++++++++++++ cxl/lib/libcxl.sym | 1 + cxl/lib/private.h | 1 + cxl/libcxl.h | 1 + 7 files changed, 38 insertions(+), 1 deletion(-)