|
|
e0018b |
From cd1aed6cefe8f4f2043349e1a614876f67743439 Mon Sep 17 00:00:00 2001
|
|
|
e0018b |
From: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
e0018b |
Date: Thu, 7 Oct 2021 02:21:33 -0600
|
|
|
e0018b |
Subject: [PATCH 040/217] libcxl: add representation for an nvdimm bridge
|
|
|
e0018b |
object
|
|
|
e0018b |
|
|
|
e0018b |
Add an nvdimm bridge object representation internal to libcxl. A bridge
|
|
|
e0018b |
object is tied to its parent memdev object, and this patch adds its
|
|
|
e0018b |
first interface, which checks whether a bridge is 'active' - i.e.
|
|
|
e0018b |
implying the label space on the memdev is owned by the kernel.
|
|
|
e0018b |
|
|
|
e0018b |
Cc: Dan Williams <dan.j.williams@intel.com>
|
|
|
e0018b |
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
|
|
e0018b |
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
|
|
e0018b |
---
|
|
|
e0018b |
cxl/lib/libcxl.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
e0018b |
cxl/lib/libcxl.sym | 1 +
|
|
|
e0018b |
cxl/lib/private.h | 8 +++++
|
|
|
e0018b |
cxl/libcxl.h | 1 +
|
|
|
e0018b |
4 files changed, 83 insertions(+)
|
|
|
e0018b |
|
|
|
e0018b |
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
|
|
e0018b |
index def3a97..60ed646 100644
|
|
|
e0018b |
--- a/cxl/lib/libcxl.c
|
|
|
e0018b |
+++ b/cxl/lib/libcxl.c
|
|
|
e0018b |
@@ -45,11 +45,19 @@ struct cxl_ctx {
|
|
|
e0018b |
void *private_data;
|
|
|
e0018b |
};
|
|
|
e0018b |
|
|
|
e0018b |
+static void free_bridge(struct cxl_nvdimm_bridge *bridge)
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ free(bridge->dev_buf);
|
|
|
e0018b |
+ free(bridge->dev_path);
|
|
|
e0018b |
+ free(bridge);
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
|
|
e0018b |
{
|
|
|
e0018b |
if (head)
|
|
|
e0018b |
list_del_from(head, &memdev->list);
|
|
|
e0018b |
kmod_module_unref(memdev->module);
|
|
|
e0018b |
+ free_bridge(memdev->bridge);
|
|
|
e0018b |
free(memdev->firmware_version);
|
|
|
e0018b |
free(memdev->dev_buf);
|
|
|
e0018b |
free(memdev->dev_path);
|
|
|
e0018b |
@@ -205,6 +213,40 @@ CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority)
|
|
|
e0018b |
ctx->ctx.log_priority = priority;
|
|
|
e0018b |
}
|
|
|
e0018b |
|
|
|
e0018b |
+static void *add_cxl_bridge(void *parent, int id, const char *br_base)
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ const char *devname = devpath_to_devname(br_base);
|
|
|
e0018b |
+ struct cxl_memdev *memdev = parent;
|
|
|
e0018b |
+ struct cxl_ctx *ctx = memdev->ctx;
|
|
|
e0018b |
+ struct cxl_nvdimm_bridge *bridge;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ dbg(ctx, "%s: bridge_base: \'%s\'\n", devname, br_base);
|
|
|
e0018b |
+
|
|
|
e0018b |
+ bridge = calloc(1, sizeof(*bridge));
|
|
|
e0018b |
+ if (!bridge)
|
|
|
e0018b |
+ goto err_dev;
|
|
|
e0018b |
+ bridge->id = id;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ bridge->dev_path = strdup(br_base);
|
|
|
e0018b |
+ if (!bridge->dev_path)
|
|
|
e0018b |
+ goto err_read;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ bridge->dev_buf = calloc(1, strlen(br_base) + 50);
|
|
|
e0018b |
+ if (!bridge->dev_buf)
|
|
|
e0018b |
+ goto err_read;
|
|
|
e0018b |
+ bridge->buf_len = strlen(br_base) + 50;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ memdev->bridge = bridge;
|
|
|
e0018b |
+ return bridge;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ err_read:
|
|
|
e0018b |
+ free(bridge->dev_buf);
|
|
|
e0018b |
+ free(bridge->dev_path);
|
|
|
e0018b |
+ free(bridge);
|
|
|
e0018b |
+ err_dev:
|
|
|
e0018b |
+ return NULL;
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
|
|
e0018b |
{
|
|
|
e0018b |
const char *devname = devpath_to_devname(cxlmem_base);
|
|
|
e0018b |
@@ -271,6 +313,8 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
|
|
e0018b |
goto err_read;
|
|
|
e0018b |
memdev->buf_len = strlen(cxlmem_base) + 50;
|
|
|
e0018b |
|
|
|
e0018b |
+ sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_bridge);
|
|
|
e0018b |
+
|
|
|
e0018b |
cxl_memdev_foreach(ctx, memdev_dup)
|
|
|
e0018b |
if (memdev_dup->id == memdev->id) {
|
|
|
e0018b |
free_memdev(memdev, NULL);
|
|
|
e0018b |
@@ -362,6 +406,35 @@ CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev)
|
|
|
e0018b |
return memdev->lsa_size;
|
|
|
e0018b |
}
|
|
|
e0018b |
|
|
|
e0018b |
+static int is_enabled(const char *drvpath)
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ struct stat st;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ if (lstat(drvpath, &st) < 0 || !S_ISLNK(st.st_mode))
|
|
|
e0018b |
+ return 0;
|
|
|
e0018b |
+ else
|
|
|
e0018b |
+ return 1;
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
+CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
|
|
e0018b |
+{
|
|
|
e0018b |
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
|
|
e0018b |
+ struct cxl_nvdimm_bridge *bridge = memdev->bridge;
|
|
|
e0018b |
+ char *path = bridge->dev_buf;
|
|
|
e0018b |
+ int len = bridge->buf_len;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ if (!bridge)
|
|
|
e0018b |
+ return 0;
|
|
|
e0018b |
+
|
|
|
e0018b |
+ if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) {
|
|
|
e0018b |
+ err(ctx, "%s: nvdimm bridge buffer too small!\n",
|
|
|
e0018b |
+ cxl_memdev_get_devname(memdev));
|
|
|
e0018b |
+ return 0;
|
|
|
e0018b |
+ }
|
|
|
e0018b |
+
|
|
|
e0018b |
+ return is_enabled(path);
|
|
|
e0018b |
+}
|
|
|
e0018b |
+
|
|
|
e0018b |
CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
|
|
|
e0018b |
{
|
|
|
e0018b |
if (!cmd)
|
|
|
e0018b |
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
|
|
e0018b |
index 858e953..f3b0c63 100644
|
|
|
e0018b |
--- a/cxl/lib/libcxl.sym
|
|
|
e0018b |
+++ b/cxl/lib/libcxl.sym
|
|
|
e0018b |
@@ -65,6 +65,7 @@ global:
|
|
|
e0018b |
cxl_cmd_new_read_label;
|
|
|
e0018b |
cxl_cmd_read_label_get_payload;
|
|
|
e0018b |
cxl_memdev_get_label_size;
|
|
|
e0018b |
+ cxl_memdev_nvdimm_bridge_active;
|
|
|
e0018b |
local:
|
|
|
e0018b |
*;
|
|
|
e0018b |
};
|
|
|
e0018b |
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
|
|
e0018b |
index c4ed741..525c41e 100644
|
|
|
e0018b |
--- a/cxl/lib/private.h
|
|
|
e0018b |
+++ b/cxl/lib/private.h
|
|
|
e0018b |
@@ -10,6 +10,13 @@
|
|
|
e0018b |
|
|
|
e0018b |
#define CXL_EXPORT __attribute__ ((visibility("default")))
|
|
|
e0018b |
|
|
|
e0018b |
+struct cxl_nvdimm_bridge {
|
|
|
e0018b |
+ int id;
|
|
|
e0018b |
+ void *dev_buf;
|
|
|
e0018b |
+ size_t buf_len;
|
|
|
e0018b |
+ char *dev_path;
|
|
|
e0018b |
+};
|
|
|
e0018b |
+
|
|
|
e0018b |
struct cxl_memdev {
|
|
|
e0018b |
int id, major, minor;
|
|
|
e0018b |
void *dev_buf;
|
|
|
e0018b |
@@ -23,6 +30,7 @@ struct cxl_memdev {
|
|
|
e0018b |
int payload_max;
|
|
|
e0018b |
size_t lsa_size;
|
|
|
e0018b |
struct kmod_module *module;
|
|
|
e0018b |
+ struct cxl_nvdimm_bridge *bridge;
|
|
|
e0018b |
};
|
|
|
e0018b |
|
|
|
e0018b |
enum cxl_cmd_query_status {
|
|
|
e0018b |
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
|
|
e0018b |
index d3b97a1..535e349 100644
|
|
|
e0018b |
--- a/cxl/libcxl.h
|
|
|
e0018b |
+++ b/cxl/libcxl.h
|
|
|
e0018b |
@@ -43,6 +43,7 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev);
|
|
|
e0018b |
unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
|
|
|
e0018b |
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
|
|
e0018b |
size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
|
|
e0018b |
+int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
|
|
e0018b |
|
|
|
e0018b |
#define cxl_memdev_foreach(ctx, memdev) \
|
|
|
e0018b |
for (memdev = cxl_memdev_get_first(ctx); \
|
|
|
e0018b |
--
|
|
|
e0018b |
2.27.0
|
|
|
e0018b |
|