Compare commits
No commits in common. "c8" and "c9" have entirely different histories.
1
.ndctl.metadata
Normal file
1
.ndctl.metadata
Normal file
@ -0,0 +1 @@
|
||||
f8266aca55afba19aad91626a6da60e88dba0577 SOURCES/ndctl-71.1.tar.gz
|
@ -0,0 +1,51 @@
|
||||
From ee7fabed859d07809dc3cfe6b23b7ad3b0c6cd73 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Tue, 12 Jan 2021 23:14:58 -0800
|
||||
Subject: [PATCH 003/217] ndctl/test: Fix btt expect table compile warning
|
||||
|
||||
../test/libndctl.c:989:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
|
||||
989 | unsigned long long expect_table[][2] = {
|
||||
| ^~~~~~~~
|
||||
|
||||
...just move the declaration a few lines up.
|
||||
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/161052209839.1804207.11951679046842122849.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
---
|
||||
test/libndctl.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/test/libndctl.c b/test/libndctl.c
|
||||
index 24d72b3..fc65149 100644
|
||||
--- a/test/libndctl.c
|
||||
+++ b/test/libndctl.c
|
||||
@@ -980,12 +980,6 @@ static int check_btt_size(struct ndctl_btt *btt)
|
||||
struct ndctl_ctx *ctx = ndctl_btt_get_ctx(btt);
|
||||
struct ndctl_test *test = ndctl_get_private_data(ctx);
|
||||
struct ndctl_namespace *ndns = ndctl_btt_get_namespace(btt);
|
||||
-
|
||||
- if (!ndns)
|
||||
- return -ENXIO;
|
||||
-
|
||||
- ns_size = ndctl_namespace_get_size(ndns);
|
||||
- sect_size = ndctl_btt_get_sector_size(btt);
|
||||
unsigned long long expect_table[][2] = {
|
||||
[0] = {
|
||||
[0] = 0x11b5400,
|
||||
@@ -1001,6 +995,12 @@ static int check_btt_size(struct ndctl_btt *btt)
|
||||
},
|
||||
};
|
||||
|
||||
+ if (!ndns)
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ ns_size = ndctl_namespace_get_size(ndns);
|
||||
+ sect_size = ndctl_btt_get_sector_size(btt);
|
||||
+
|
||||
if (sect_size >= SZ_4K)
|
||||
sect_select = 1;
|
||||
else if (sect_size >= 512)
|
||||
--
|
||||
2.27.0
|
||||
|
57
SOURCES/0004-ndctl-test-Cleanup-unnecessary-out-label.patch
Normal file
57
SOURCES/0004-ndctl-test-Cleanup-unnecessary-out-label.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From ff4030e88da2cdcaf52c0d7457cd30264ea8915b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Tue, 12 Jan 2021 23:15:03 -0800
|
||||
Subject: [PATCH 004/217] ndctl/test: Cleanup unnecessary out label
|
||||
|
||||
There are no cleanup actions to take in test_dax_remap(), and it is already
|
||||
inconsistent for having a single return point, so remove the out label.
|
||||
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/161052210395.1804207.7318263492906073721.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
---
|
||||
test/dax-pmd.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/test/dax-pmd.c b/test/dax-pmd.c
|
||||
index 401826d..b1251db 100644
|
||||
--- a/test/dax-pmd.c
|
||||
+++ b/test/dax-pmd.c
|
||||
@@ -83,20 +83,18 @@ int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, voi
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGBUS, &act, 0)) {
|
||||
perror("sigaction");
|
||||
- rc = EXIT_FAILURE;
|
||||
- goto out;
|
||||
+ return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* test fault after device-dax instance disabled */
|
||||
if (sigsetjmp(sj_env, 1)) {
|
||||
if (!fsdax && align > SZ_4K) {
|
||||
fprintf(stderr, "got expected SIGBUS after mremap() of device-dax\n");
|
||||
- rc = 0;
|
||||
+ return 0;
|
||||
} else {
|
||||
fprintf(stderr, "unpexpected SIGBUS after mremap()\n");
|
||||
- rc = -EIO;
|
||||
+ return -EIO;
|
||||
}
|
||||
- goto out;
|
||||
}
|
||||
|
||||
*(int *) anon = 0xAA;
|
||||
@@ -107,9 +105,7 @@ int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, voi
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
- rc = 0;
|
||||
-out:
|
||||
- return rc;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t offset)
|
||||
--
|
||||
2.27.0
|
||||
|
40
SOURCES/0005-ndctl-test-Fix-device-dax-mremap-test.patch
Normal file
40
SOURCES/0005-ndctl-test-Fix-device-dax-mremap-test.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 6694afe31dd67d186199a58d2252be5ea3472692 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Tue, 12 Jan 2021 23:15:09 -0800
|
||||
Subject: [PATCH 005/217] ndctl/test: Fix device-dax mremap() test
|
||||
|
||||
The test_dax_remap() test is a regression check for mishandling of mremap()
|
||||
in the presence of pmd_devmap(). My understanding is that it was a fuzzing
|
||||
condition not something an application would want to do in practice.
|
||||
|
||||
On recent kernels with commit 73d5e0629919 ("mremap: check if it's possible
|
||||
to split original vma"), the test fails for device-dax. That seems an
|
||||
equally acceptable result of attempting this remap, so update the test
|
||||
rather than ask the kernel to preserve the old behaviour.
|
||||
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/161052210936.1804207.17896246772670985157.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
---
|
||||
test/dax-pmd.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/test/dax-pmd.c b/test/dax-pmd.c
|
||||
index b1251db..7648e34 100644
|
||||
--- a/test/dax-pmd.c
|
||||
+++ b/test/dax-pmd.c
|
||||
@@ -69,6 +69,11 @@ int test_dax_remap(struct ndctl_test *test, int dax_fd, unsigned long align, voi
|
||||
|
||||
remap = mremap(addr, REMAP_SIZE, REMAP_SIZE, MREMAP_MAYMOVE|MREMAP_FIXED, anon);
|
||||
|
||||
+ if (remap == MAP_FAILED) {
|
||||
+ fprintf(stderr, "%s: mremap failed, that's ok too\n", __func__);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
if (remap != anon) {
|
||||
rc = -ENXIO;
|
||||
perror("mremap");
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,134 @@
|
||||
From 940acf65a61595e8c0db3aebe1c74307acbbef68 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Tue, 12 Jan 2021 23:15:14 -0800
|
||||
Subject: [PATCH 006/217] ndctl/test: Exercise soft_offline_page() corner cases
|
||||
|
||||
Test soft-offline injection into PMEM namespace metadata and user mapped
|
||||
space. Both attempts should fail on kernels with a pfn_to_online_page()
|
||||
implementation that considers subsection ZONE_DEVICE ranges.
|
||||
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/161052211455.1804207.13884321454837200896.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
---
|
||||
test/dax-poison.c | 19 +++++++++++++++++++
|
||||
test/device-dax.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 64 insertions(+)
|
||||
|
||||
diff --git a/test/dax-poison.c b/test/dax-poison.c
|
||||
index a4ef12e..4e09761 100644
|
||||
--- a/test/dax-poison.c
|
||||
+++ b/test/dax-poison.c
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/mman.h>
|
||||
+#include <linux/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -49,6 +50,7 @@ int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align,
|
||||
unsigned char *addr = MAP_FAILED;
|
||||
struct sigaction act;
|
||||
unsigned x = x;
|
||||
+ FILE *smaps;
|
||||
void *buf;
|
||||
int rc;
|
||||
|
||||
@@ -94,6 +96,9 @@ int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align,
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ fprintf(stderr, "%s: mmap got %p align: %ld offset: %zd\n",
|
||||
+ __func__, addr, align, offset);
|
||||
+
|
||||
if (sigsetjmp(sj_env, 1)) {
|
||||
if (sig_mcerr_ar) {
|
||||
fprintf(stderr, "madvise triggered 'action required' sigbus\n");
|
||||
@@ -104,6 +109,20 @@ int test_dax_poison(struct ndctl_test *test, int dax_fd, unsigned long align,
|
||||
}
|
||||
}
|
||||
|
||||
+ rc = madvise(addr + align / 2, 4096, MADV_SOFT_OFFLINE);
|
||||
+ if (rc == 0) {
|
||||
+ fprintf(stderr, "softoffline should always fail for dax\n");
|
||||
+ smaps = fopen("/proc/self/smaps", "r");
|
||||
+ do {
|
||||
+ rc = fread(buf, 1, 4096, smaps);
|
||||
+ fwrite(buf, 1, rc, stderr);
|
||||
+ } while (rc);
|
||||
+ fclose(smaps);
|
||||
+ fail();
|
||||
+ rc = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
rc = madvise(addr + align / 2, 4096, MADV_HWPOISON);
|
||||
if (rc) {
|
||||
fail();
|
||||
diff --git a/test/device-dax.c b/test/device-dax.c
|
||||
index 5f0da29..aad8fa5 100644
|
||||
--- a/test/device-dax.c
|
||||
+++ b/test/device-dax.c
|
||||
@@ -128,6 +128,44 @@ static int verify_data(struct daxctl_dev *dev, char *dax_buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int test_dax_soft_offline(struct ndctl_test *test, struct ndctl_namespace *ndns)
|
||||
+{
|
||||
+ unsigned long long resource = ndctl_namespace_get_resource(ndns);
|
||||
+ int fd, rc;
|
||||
+ char *buf;
|
||||
+
|
||||
+ if (resource == ULLONG_MAX) {
|
||||
+ fprintf(stderr, "failed to get resource: %s\n",
|
||||
+ ndctl_namespace_get_devname(ndns));
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ fd = open("/sys/devices/system/memory/soft_offline_page", O_WRONLY);
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "failed to open soft_offline_page\n");
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ rc = asprintf(&buf, "%#llx\n", resource);
|
||||
+ if (rc < 0) {
|
||||
+ fprintf(stderr, "failed to alloc resource\n");
|
||||
+ close(fd);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ fprintf(stderr, "%s: try to offline page @%#llx\n", __func__, resource);
|
||||
+ rc = write(fd, buf, rc);
|
||||
+ free(buf);
|
||||
+ close(fd);
|
||||
+
|
||||
+ if (rc >= 0) {
|
||||
+ fprintf(stderr, "%s: should have failed\n", __func__);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int __test_device_dax(unsigned long align, int loglevel,
|
||||
struct ndctl_test *test, struct ndctl_ctx *ctx)
|
||||
{
|
||||
@@ -278,6 +316,13 @@ static int __test_device_dax(unsigned long align, int loglevel,
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ rc = test_dax_soft_offline(test, ndns);
|
||||
+ if (rc) {
|
||||
+ fprintf(stderr, "%s: failed dax soft offline\n",
|
||||
+ ndctl_namespace_get_devname(ndns));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
rc = test_dax_poison(test, fd, align, NULL, 0, devdax);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: failed dax poison\n",
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,73 @@
|
||||
From 11357d68b77392e4360ae2824e75bf8397a84885 Mon Sep 17 00:00:00 2001
|
||||
From: Redhairer Li <redhairer.li@intel.com>
|
||||
Date: Sat, 9 Jan 2021 23:36:33 +0800
|
||||
Subject: [PATCH 007/217] msft: Add xlat_firmware_status for JEDEC Byte
|
||||
Addressable Energy Backed DSM
|
||||
|
||||
Translate the status codes of the result of JEDEC Byte Addressable Energy Backed
|
||||
DSM to generic errno style error codes.
|
||||
|
||||
Signed-off-by: Li Redhairer <redhairer.li@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210109153633.8493-1-redhairer.li@intel.com
|
||||
---
|
||||
ndctl/lib/msft.c | 22 ++++++++++++++++++++++
|
||||
ndctl/lib/msft.h | 6 ++++++
|
||||
2 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/ndctl/lib/msft.c b/ndctl/lib/msft.c
|
||||
index 145872c..3112799 100644
|
||||
--- a/ndctl/lib/msft.c
|
||||
+++ b/ndctl/lib/msft.c
|
||||
@@ -149,10 +149,32 @@ static unsigned int msft_cmd_smart_get_life_used(struct ndctl_cmd *cmd)
|
||||
return 100 - CMD_MSFT_SMART(cmd)->nvm_lifetime;
|
||||
}
|
||||
|
||||
+static int msft_cmd_xlat_firmware_status(struct ndctl_cmd *cmd)
|
||||
+{
|
||||
+ unsigned int status;
|
||||
+
|
||||
+ status = cmd->get_firmware_status(cmd) & NDN_MSFT_STATUS_MASK;
|
||||
+
|
||||
+ /* Common statuses */
|
||||
+ switch (status) {
|
||||
+ case NDN_MSFT_STATUS_SUCCESS:
|
||||
+ return 0;
|
||||
+ case NDN_MSFT_STATUS_NOTSUPP:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ case NDN_MSFT_STATUS_INVALPARM:
|
||||
+ return -EINVAL;
|
||||
+ case NDN_MSFT_STATUS_I2CERR:
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ return -ENOMSG;
|
||||
+}
|
||||
+
|
||||
struct ndctl_dimm_ops * const msft_dimm_ops = &(struct ndctl_dimm_ops) {
|
||||
.new_smart = msft_dimm_cmd_new_smart,
|
||||
.smart_get_flags = msft_cmd_smart_get_flags,
|
||||
.smart_get_health = msft_cmd_smart_get_health,
|
||||
.smart_get_media_temperature = msft_cmd_smart_get_media_temperature,
|
||||
.smart_get_life_used = msft_cmd_smart_get_life_used,
|
||||
+ .xlat_firmware_status = msft_cmd_xlat_firmware_status,
|
||||
};
|
||||
diff --git a/ndctl/lib/msft.h b/ndctl/lib/msft.h
|
||||
index 7cfd26f..978cc11 100644
|
||||
--- a/ndctl/lib/msft.h
|
||||
+++ b/ndctl/lib/msft.h
|
||||
@@ -50,4 +50,10 @@ struct ndn_pkg_msft {
|
||||
union ndn_msft_cmd u;
|
||||
} __attribute__((packed));
|
||||
|
||||
+#define NDN_MSFT_STATUS_MASK 0xffff
|
||||
+#define NDN_MSFT_STATUS_SUCCESS 0
|
||||
+#define NDN_MSFT_STATUS_NOTSUPP 1
|
||||
+#define NDN_MSFT_STATUS_INVALPARM 2
|
||||
+#define NDN_MSFT_STATUS_I2CERR 3
|
||||
+
|
||||
#endif /* __NDCTL_MSFT_H__ */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,140 @@
|
||||
From fe626a8a8a1b1bc94ea95c693ec672109909e3dc Mon Sep 17 00:00:00 2001
|
||||
From: Redhairer Li <redhairer.li@intel.com>
|
||||
Date: Thu, 28 Jan 2021 22:03:39 +0800
|
||||
Subject: [PATCH 008/217] ndctl/namespace: Fix disable-namespace accounting
|
||||
relative to seed devices
|
||||
|
||||
Seed namespaces are included in "ndctl disable-namespace all". However
|
||||
since the user never "creates" them it is surprising to see
|
||||
"disable-namespace" report 1 more namespace relative to the number that
|
||||
have been created. Catch attempts to disable a zero-sized namespace:
|
||||
|
||||
Before:
|
||||
{
|
||||
"dev":"namespace1.0",
|
||||
"size":"492.00 MiB (515.90 MB)",
|
||||
"blockdev":"pmem1"
|
||||
}
|
||||
{
|
||||
"dev":"namespace1.1",
|
||||
"size":"492.00 MiB (515.90 MB)",
|
||||
"blockdev":"pmem1.1"
|
||||
}
|
||||
{
|
||||
"dev":"namespace1.2",
|
||||
"size":"492.00 MiB (515.90 MB)",
|
||||
"blockdev":"pmem1.2"
|
||||
}
|
||||
disabled 4 namespaces
|
||||
|
||||
After:
|
||||
{
|
||||
"dev":"namespace1.0",
|
||||
"size":"492.00 MiB (515.90 MB)",
|
||||
"blockdev":"pmem1"
|
||||
}
|
||||
{
|
||||
"dev":"namespace1.3",
|
||||
"size":"492.00 MiB (515.90 MB)",
|
||||
"blockdev":"pmem1.3"
|
||||
}
|
||||
{
|
||||
"dev":"namespace1.1",
|
||||
"size":"492.00 MiB (515.90 MB)",
|
||||
"blockdev":"pmem1.1"
|
||||
}
|
||||
disabled 3 namespaces
|
||||
|
||||
Signed-off-by: Redhairer Li <redhairer.li@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/linux-nvdimm/20210128140339.3080-1-redhairer.li@intel.com/
|
||||
---
|
||||
ndctl/lib/libndctl.c | 10 ++++++++--
|
||||
ndctl/namespace.c | 8 ++++----
|
||||
ndctl/region.c | 2 +-
|
||||
3 files changed, 13 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 36fb6fe..2f6d806 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -4602,6 +4602,7 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns)
|
||||
const char *bdev = NULL;
|
||||
char path[50];
|
||||
int fd;
|
||||
+ unsigned long long size = ndctl_namespace_get_size(ndns);
|
||||
|
||||
if (pfn && ndctl_pfn_is_enabled(pfn))
|
||||
bdev = ndctl_pfn_get_block_device(pfn);
|
||||
@@ -4631,8 +4632,13 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns)
|
||||
devname, bdev, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
- } else
|
||||
- ndctl_namespace_disable_invalidate(ndns);
|
||||
+ } else {
|
||||
+ if (size == 0)
|
||||
+ /* No disable necessary due to no capacity allocated */
|
||||
+ return 1;
|
||||
+ else
|
||||
+ ndctl_namespace_disable_invalidate(ndns);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
|
||||
index 0c8df9f..1feb74d 100644
|
||||
--- a/ndctl/namespace.c
|
||||
+++ b/ndctl/namespace.c
|
||||
@@ -1125,7 +1125,7 @@ static int namespace_prep_reconfig(struct ndctl_region *region,
|
||||
}
|
||||
|
||||
rc = ndctl_namespace_disable_safe(ndns);
|
||||
- if (rc)
|
||||
+ if (rc < 0)
|
||||
return rc;
|
||||
|
||||
ndctl_namespace_set_enforce_mode(ndns, NDCTL_NS_MODE_RAW);
|
||||
@@ -1431,7 +1431,7 @@ static int dax_clear_badblocks(struct ndctl_dax *dax)
|
||||
return -ENXIO;
|
||||
|
||||
rc = ndctl_namespace_disable_safe(ndns);
|
||||
- if (rc) {
|
||||
+ if (rc < 0) {
|
||||
error("%s: unable to disable namespace: %s\n", devname,
|
||||
strerror(-rc));
|
||||
return rc;
|
||||
@@ -1455,7 +1455,7 @@ static int pfn_clear_badblocks(struct ndctl_pfn *pfn)
|
||||
return -ENXIO;
|
||||
|
||||
rc = ndctl_namespace_disable_safe(ndns);
|
||||
- if (rc) {
|
||||
+ if (rc < 0) {
|
||||
error("%s: unable to disable namespace: %s\n", devname,
|
||||
strerror(-rc));
|
||||
return rc;
|
||||
@@ -1478,7 +1478,7 @@ static int raw_clear_badblocks(struct ndctl_namespace *ndns)
|
||||
return -ENXIO;
|
||||
|
||||
rc = ndctl_namespace_disable_safe(ndns);
|
||||
- if (rc) {
|
||||
+ if (rc < 0) {
|
||||
error("%s: unable to disable namespace: %s\n", devname,
|
||||
strerror(-rc));
|
||||
return rc;
|
||||
diff --git a/ndctl/region.c b/ndctl/region.c
|
||||
index 3edb9b3..4552c4a 100644
|
||||
--- a/ndctl/region.c
|
||||
+++ b/ndctl/region.c
|
||||
@@ -70,7 +70,7 @@ static int region_action(struct ndctl_region *region, enum device_action mode)
|
||||
case ACTION_DISABLE:
|
||||
ndctl_namespace_foreach(region, ndns) {
|
||||
rc = ndctl_namespace_disable_safe(ndns);
|
||||
- if (rc)
|
||||
+ if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
rc = ndctl_region_disable_invalidate(region);
|
||||
--
|
||||
2.27.0
|
||||
|
50
SOURCES/0009-zero_info_block-skip-seed-devices.patch
Normal file
50
SOURCES/0009-zero_info_block-skip-seed-devices.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From fb13dfb8d84c4f0a749665c8f07179450b199f3e Mon Sep 17 00:00:00 2001
|
||||
From: Jeff Moyer <jmoyer@redhat.com>
|
||||
Date: Tue, 9 Feb 2021 16:51:53 -0500
|
||||
Subject: [PATCH 009/217] zero_info_block: skip seed devices
|
||||
|
||||
Currently, ndctl destroy-namespace -f all will output errors of the
|
||||
form:
|
||||
|
||||
Error: destroy namespace: namespace0.0 failed to enable for zeroing, continuing
|
||||
|
||||
for any zero-sized namespace. That particular namespace looks like this:
|
||||
|
||||
{
|
||||
"dev":"namespace0.0",
|
||||
"mode":"raw",
|
||||
"size":0,
|
||||
"uuid":"00000000-0000-0000-0000-000000000000",
|
||||
"sector_size":512,
|
||||
"state":"disabled"
|
||||
}
|
||||
|
||||
This patch skips over namespaces with size=0 when zeroing out info
|
||||
blocks.
|
||||
|
||||
Fixes: 46654c2d60b70 ("ndctl/namespace: Always zero info-blocks")
|
||||
Reported-by: Zhang Yi <yizhan@redhat.com>
|
||||
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/x49r1lohpty.fsf@segfault.boston.devel.redhat.com
|
||||
---
|
||||
ndctl/namespace.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
|
||||
index 1feb74d..1e8a2cd 100644
|
||||
--- a/ndctl/namespace.c
|
||||
+++ b/ndctl/namespace.c
|
||||
@@ -1052,6 +1052,9 @@ static int zero_info_block(struct ndctl_namespace *ndns)
|
||||
void *buf = NULL, *read_buf = NULL;
|
||||
char path[50];
|
||||
|
||||
+ if (ndctl_namespace_get_size(ndns) == 0)
|
||||
+ return 1;
|
||||
+
|
||||
ndctl_namespace_set_raw_mode(ndns, 1);
|
||||
rc = ndctl_namespace_enable(ndns);
|
||||
if (rc < 0) {
|
||||
--
|
||||
2.27.0
|
||||
|
51
SOURCES/0010-ndctl-update-.gitignore.patch
Normal file
51
SOURCES/0010-ndctl-update-.gitignore.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 5d0d4dc5ae1de82de92212c98297b24fbba09227 Mon Sep 17 00:00:00 2001
|
||||
From: QI Fuli <qi.fuli@fujitsu.com>
|
||||
Date: Tue, 2 Feb 2021 22:02:06 +0900
|
||||
Subject: [PATCH 010/217] ndctl: update .gitignore
|
||||
|
||||
Add Documentation/ndctl/attrs.adoc and *.lo to .gitignore.
|
||||
|
||||
Signed-off-by: QI Fuli <qi.fuli@fujitsu.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210202130206.3761-1-qi.fuli@fujitsu.com
|
||||
---
|
||||
.gitignore | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index 3ef9ff7..53512b2 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -1,4 +1,5 @@
|
||||
*.o
|
||||
+*.lo
|
||||
*.xml
|
||||
.deps/
|
||||
.libs/
|
||||
@@ -15,13 +16,13 @@ Makefile.in
|
||||
*.1
|
||||
Documentation/daxctl/asciidoc.conf
|
||||
Documentation/ndctl/asciidoc.conf
|
||||
+Documentation/ndctl/attrs.adoc
|
||||
Documentation/daxctl/asciidoctor-extensions.rb
|
||||
Documentation/ndctl/asciidoctor-extensions.rb
|
||||
.dirstamp
|
||||
daxctl/config.h
|
||||
daxctl/daxctl
|
||||
daxctl/lib/libdaxctl.la
|
||||
-daxctl/lib/libdaxctl.lo
|
||||
daxctl/lib/libdaxctl.pc
|
||||
*.a
|
||||
ndctl/config.h
|
||||
@@ -29,8 +30,6 @@ ndctl/lib/libndctl.pc
|
||||
ndctl/ndctl
|
||||
rhel/
|
||||
sles/ndctl.spec
|
||||
-util/log.lo
|
||||
-util/sysfs.lo
|
||||
version.m4
|
||||
*.swp
|
||||
cscope.files
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,21 +1,27 @@
|
||||
ndctl/test: add checking the presence of jq command ahead
|
||||
From 7ce2fddfa3f108036a2d81de4d2e66ac29e4631e Mon Sep 17 00:00:00 2001
|
||||
From: QI Fuli <qi.fuli@fujitsu.com>
|
||||
Date: Wed, 3 Feb 2021 22:21:08 +0900
|
||||
Subject: [PATCH 011/217] ndctl/test: add checking the presence of jq command
|
||||
ahead
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141031
|
||||
Due to the lack of jq command, the result of the test will be 'fail'.
|
||||
This patch adds checking the presence of jq commmand ahead.
|
||||
If there is no jq command in the system, the test will be marked as 'skip'.
|
||||
|
||||
commit 7ce2fddfa3f108036a2d81de4d2e66ac29e4631e
|
||||
Author: QI Fuli <qi.fuli@fujitsu.com>
|
||||
Date: Wed Feb 3 22:21:08 2021 +0900
|
||||
|
||||
ndctl/test: add checking the presence of jq command ahead
|
||||
|
||||
Due to the lack of jq command, the result of the test will be 'fail'.
|
||||
This patch adds checking the presence of jq commmand ahead.
|
||||
If there is no jq command in the system, the test will be marked as 'skip'.
|
||||
|
||||
Signed-off-by: QI Fuli <qi.fuli@fujitsu.com>
|
||||
Link: https://github.com/pmem/ndctl/issues/141
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210203132108.6246-1-qi.fuli@fujitsu.com
|
||||
Signed-off-by: QI Fuli <qi.fuli@fujitsu.com>
|
||||
Link: https://github.com/pmem/ndctl/issues/141
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210203132108.6246-1-qi.fuli@fujitsu.com
|
||||
---
|
||||
test/daxdev-errors.sh | 1 +
|
||||
test/inject-error.sh | 2 ++
|
||||
test/inject-smart.sh | 1 +
|
||||
test/label-compat.sh | 1 +
|
||||
test/max_available_extent_ns.sh | 1 +
|
||||
test/monitor.sh | 2 ++
|
||||
test/multi-dax.sh | 1 +
|
||||
test/sector-mode.sh | 2 ++
|
||||
8 files changed, 11 insertions(+)
|
||||
|
||||
diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh
|
||||
index 6281f32..9547d78 100755
|
||||
@ -116,3 +122,6 @@ index dd7013e..54fa806 100755
|
||||
set -e
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,78 @@
|
||||
From c81fa15bafb1295aaa7d7f09500c3fbdd68b0011 Mon Sep 17 00:00:00 2001
|
||||
From: "Tsaur, Erwin" <erwin.tsaur@intel.com>
|
||||
Date: Thu, 4 Mar 2021 17:18:04 -0800
|
||||
Subject: [PATCH 012/217] Expose ndctl_bus_nfit_translate_spa as a public
|
||||
function.
|
||||
|
||||
The motivation is to allow access to ACPI defined NVDIMM Root Device
|
||||
_DSM Function Index 5(Translate SPA). The rest of the _DSM functions,
|
||||
which are mostly ARS related, are already public.
|
||||
|
||||
Basically move ndctl_bus_nfit_translate_spa declaration from private.h
|
||||
to libndctl.h.
|
||||
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: "Tsaur, Erwin" <erwin.tsaur@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210305011804.3573-1-erwin.tsaur@intel.com
|
||||
---
|
||||
ndctl/lib/libndctl.sym | 4 ++++
|
||||
ndctl/lib/nfit.c | 2 +-
|
||||
ndctl/lib/private.h | 2 --
|
||||
ndctl/libndctl.h | 2 ++
|
||||
4 files changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
|
||||
index 0a82616..58afb74 100644
|
||||
--- a/ndctl/lib/libndctl.sym
|
||||
+++ b/ndctl/lib/libndctl.sym
|
||||
@@ -451,3 +451,7 @@ LIBNDCTL_25 {
|
||||
ndctl_bus_clear_fw_activate_nosuspend;
|
||||
ndctl_bus_activate_firmware;
|
||||
} LIBNDCTL_24;
|
||||
+
|
||||
+LIBNDCTL_26 {
|
||||
+ ndctl_bus_nfit_translate_spa;
|
||||
+} LIBNDCTL_25;
|
||||
diff --git a/ndctl/lib/nfit.c b/ndctl/lib/nfit.c
|
||||
index 6f68fcf..d85682f 100644
|
||||
--- a/ndctl/lib/nfit.c
|
||||
+++ b/ndctl/lib/nfit.c
|
||||
@@ -114,7 +114,7 @@ static int is_valid_spa(struct ndctl_bus *bus, unsigned long long spa)
|
||||
*
|
||||
* If success, returns zero, store dimm's @handle, and @dpa.
|
||||
*/
|
||||
-int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus,
|
||||
+NDCTL_EXPORT int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus,
|
||||
unsigned long long address, unsigned int *handle, unsigned long long *dpa)
|
||||
{
|
||||
|
||||
diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h
|
||||
index ede1300..8f4510e 100644
|
||||
--- a/ndctl/lib/private.h
|
||||
+++ b/ndctl/lib/private.h
|
||||
@@ -370,8 +370,6 @@ static inline int check_kmod(struct kmod_ctx *kmod_ctx)
|
||||
return kmod_ctx ? 0 : -ENXIO;
|
||||
}
|
||||
|
||||
-int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, unsigned long long addr,
|
||||
- unsigned int *handle, unsigned long long *dpa);
|
||||
struct ndctl_cmd *ndctl_bus_cmd_new_err_inj(struct ndctl_bus *bus);
|
||||
struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_clr(struct ndctl_bus *bus);
|
||||
struct ndctl_cmd *ndctl_bus_cmd_new_err_inj_stat(struct ndctl_bus *bus,
|
||||
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
|
||||
index 60e1288..87d07b7 100644
|
||||
--- a/ndctl/libndctl.h
|
||||
+++ b/ndctl/libndctl.h
|
||||
@@ -152,6 +152,8 @@ int ndctl_bus_clear_fw_activate_noidle(struct ndctl_bus *bus);
|
||||
int ndctl_bus_set_fw_activate_nosuspend(struct ndctl_bus *bus);
|
||||
int ndctl_bus_clear_fw_activate_nosuspend(struct ndctl_bus *bus);
|
||||
int ndctl_bus_activate_firmware(struct ndctl_bus *bus, enum ndctl_fwa_method method);
|
||||
+int ndctl_bus_nfit_translate_spa(struct ndctl_bus *bus, unsigned long long addr,
|
||||
+ unsigned int *handle, unsigned long long *dpa);
|
||||
|
||||
struct ndctl_dimm;
|
||||
struct ndctl_dimm *ndctl_dimm_get_first(struct ndctl_bus *bus);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,72 @@
|
||||
From 43e48c0d2f271cba4237f6eefc3e4912a74c102b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Tue, 9 Mar 2021 22:09:49 -0800
|
||||
Subject: [PATCH 013/217] test/libndctl: Use ndctl_region_set_ro() to change
|
||||
disk read-only state
|
||||
|
||||
Kernel commit 52f019d43c22 ("block: add a hard-readonly flag to struct
|
||||
gendisk") broke the read-only management test, by fixing the broken
|
||||
behavior that BLKROSET could make a block device read-write even when the
|
||||
disk is read-only. The fix [1] propagates changes of the region
|
||||
read-only state to the underlying disk. Add ndctl_region_set_ro() ahead of
|
||||
BLKROSET so that BLKROSET does not conflict the block_device state with the
|
||||
disk state.
|
||||
|
||||
[1]: http://lore.kernel.org/r/161534060720.528671.2341213328968989192.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
|
||||
Reported-by: kernel test robot <lkp@intel.com>
|
||||
Reported-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/161535658913.530219.12194565167385663385.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
---
|
||||
test/libndctl.c | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/libndctl.c b/test/libndctl.c
|
||||
index fc65149..c42f785 100644
|
||||
--- a/test/libndctl.c
|
||||
+++ b/test/libndctl.c
|
||||
@@ -1541,6 +1541,7 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt,
|
||||
struct ndctl_pfn *pfn, struct ndctl_namespace *ndns,
|
||||
struct namespace *namespace, void *buf)
|
||||
{
|
||||
+ struct ndctl_region *region = ndctl_namespace_get_region(ndns);
|
||||
char bdevpath[50];
|
||||
int fd, rc, ro;
|
||||
|
||||
@@ -1578,6 +1579,13 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt,
|
||||
}
|
||||
|
||||
ro = 0;
|
||||
+ rc = ndctl_region_set_ro(region, ro);
|
||||
+ if (rc < 0) {
|
||||
+ fprintf(stderr, "%s: ndctl_region_set_ro failed\n", devname);
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
rc = ioctl(fd, BLKROSET, &ro);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "%s: BLKROSET failed\n",
|
||||
@@ -1605,8 +1613,16 @@ static int validate_bdev(const char *devname, struct ndctl_btt *btt,
|
||||
rc = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
+
|
||||
+ rc = ndctl_region_set_ro(region, namespace->ro);
|
||||
+ if (rc < 0) {
|
||||
+ fprintf(stderr, "%s: ndctl_region_set_ro reset failed\n", devname);
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
rc = 0;
|
||||
- out:
|
||||
+out:
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,221 @@
|
||||
From 99415dfc7c5167c49a5732f577836f68872645b2 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Wed, 24 Mar 2021 12:09:29 -0700
|
||||
Subject: [PATCH 014/217] daxctl: fail reconfigure-device based on kernel
|
||||
onlining policy
|
||||
|
||||
If the kernel has a policy set to auto-online any new memory blocks, we
|
||||
know that an attempt to reconfigure a device either in ZONE_MOVABLE, or
|
||||
with the --no-online is going to fail. While we detect this race after
|
||||
the fact, and print a warning, that is often insufficient as the user
|
||||
may be forced to reboot to get out of the situation, resulting in an
|
||||
unpleasant experience.
|
||||
|
||||
Detect whether the kernel policy is set to auto-online. If so, fail
|
||||
device reconfigure operations that we know can't be satisfied. Allow
|
||||
for overriding this safety check via the -f (--force) option. Update the
|
||||
man page to talk about this, and the unit test to test for an expected
|
||||
failure by enabling auto-onlining.
|
||||
|
||||
Cc: Dave Hansen <dave.hansen@intel.com>
|
||||
Reported-by: Chunye Xu <chunye.xu@intel.com>
|
||||
Reported-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.../daxctl/daxctl-reconfigure-device.txt | 12 ++++++-
|
||||
daxctl/device.c | 10 ++++++
|
||||
daxctl/lib/libdaxctl-private.h | 1 +
|
||||
daxctl/lib/libdaxctl.c | 21 +++++++++++
|
||||
daxctl/lib/libdaxctl.sym | 5 +++
|
||||
daxctl/libdaxctl.h | 1 +
|
||||
test/daxctl-devices.sh | 36 +++++++++++++++++++
|
||||
7 files changed, 85 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt
|
||||
index ad33eda..f112b3c 100644
|
||||
--- a/Documentation/daxctl/daxctl-reconfigure-device.txt
|
||||
+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt
|
||||
@@ -119,6 +119,10 @@ recommended to use the --no-online option described below. This will abridge
|
||||
the device reconfiguration operation to just hotplugging the memory, and
|
||||
refrain from then onlining it.
|
||||
|
||||
+In case daxctl detects that there is a kernel policy to auto-online blocks
|
||||
+(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to
|
||||
+system-ram will result in a failure. This can be overridden with '--force'.
|
||||
+
|
||||
OPTIONS
|
||||
-------
|
||||
include::region-option.txt[]
|
||||
@@ -162,12 +166,18 @@ include::movable-options.txt[]
|
||||
|
||||
-f::
|
||||
--force::
|
||||
- When converting from "system-ram" mode to "devdax", it is expected
|
||||
+ - When converting from "system-ram" mode to "devdax", it is expected
|
||||
that all the memory sections are first made offline. By default,
|
||||
daxctl won't touch online memory. However with this option, attempt
|
||||
to offline the memory on the NUMA node associated with the dax device
|
||||
before converting it back to "devdax" mode.
|
||||
|
||||
+ - Additionally, if a kernel policy to auto-online blocks is detected,
|
||||
+ reconfiguration to system-ram fails. With this option, the failure can
|
||||
+ be overridden to allow reconfiguration regardless of kernel policy.
|
||||
+ Doing this may result in a successful reconfiguration, but it may
|
||||
+ not be possible to subsequently offline the memory without a reboot.
|
||||
+
|
||||
|
||||
include::human-option.txt[]
|
||||
|
||||
diff --git a/daxctl/device.c b/daxctl/device.c
|
||||
index 0721a57..a427b7d 100644
|
||||
--- a/daxctl/device.c
|
||||
+++ b/daxctl/device.c
|
||||
@@ -541,8 +541,18 @@ static int disable_devdax_device(struct daxctl_dev *dev)
|
||||
|
||||
static int reconfig_mode_system_ram(struct daxctl_dev *dev)
|
||||
{
|
||||
+ const char *devname = daxctl_dev_get_devname(dev);
|
||||
int rc, skip_enable = 0;
|
||||
|
||||
+ if (param.no_online || !param.no_movable) {
|
||||
+ if (!param.force && daxctl_dev_will_auto_online_memory(dev)) {
|
||||
+ fprintf(stderr,
|
||||
+ "%s: error: kernel policy will auto-online memory, aborting\n",
|
||||
+ devname);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (daxctl_dev_is_enabled(dev)) {
|
||||
rc = disable_devdax_device(dev);
|
||||
if (rc < 0)
|
||||
diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h
|
||||
index af257fd..ae45311 100644
|
||||
--- a/daxctl/lib/libdaxctl-private.h
|
||||
+++ b/daxctl/lib/libdaxctl-private.h
|
||||
@@ -111,6 +111,7 @@ struct daxctl_memory {
|
||||
char *node_path;
|
||||
unsigned long block_size;
|
||||
enum memory_zones zone;
|
||||
+ bool auto_online;
|
||||
};
|
||||
|
||||
|
||||
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
|
||||
index 479e8f6..879f7e6 100644
|
||||
--- a/daxctl/lib/libdaxctl.c
|
||||
+++ b/daxctl/lib/libdaxctl.c
|
||||
@@ -1644,3 +1644,24 @@ DAXCTL_EXPORT int daxctl_memory_is_movable(struct daxctl_memory *mem)
|
||||
return rc;
|
||||
return (mem->zone == MEM_ZONE_MOVABLE) ? 1 : 0;
|
||||
}
|
||||
+
|
||||
+DAXCTL_EXPORT int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev)
|
||||
+{
|
||||
+ const char *auto_path = "/sys/devices/system/memory/auto_online_blocks";
|
||||
+ const char *devname = daxctl_dev_get_devname(dev);
|
||||
+ struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
|
||||
+ char buf[SYSFS_ATTR_SIZE];
|
||||
+
|
||||
+ /*
|
||||
+ * If we can't read the policy for some reason, don't fail yet. Assume
|
||||
+ * the auto-onlining policy is absent, and carry on. If onlining blocks
|
||||
+ * does result in the memory being in an inconsistent state, we have a
|
||||
+ * check and warning for it after the fact
|
||||
+ */
|
||||
+ if (sysfs_read_attr(ctx, auto_path, buf) != 0)
|
||||
+ err(ctx, "%s: Unable to determine auto-online policy: %s\n",
|
||||
+ devname, strerror(errno));
|
||||
+
|
||||
+ /* match both "online" and "online_movable" */
|
||||
+ return !strncmp(buf, "online", 6);
|
||||
+}
|
||||
diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
|
||||
index a4e1684..892e393 100644
|
||||
--- a/daxctl/lib/libdaxctl.sym
|
||||
+++ b/daxctl/lib/libdaxctl.sym
|
||||
@@ -91,3 +91,8 @@ global:
|
||||
daxctl_mapping_get_size;
|
||||
daxctl_dev_set_mapping;
|
||||
} LIBDAXCTL_7;
|
||||
+
|
||||
+LIBDAXCTL_9 {
|
||||
+global:
|
||||
+ daxctl_dev_will_auto_online_memory;
|
||||
+} LIBDAXCTL_8;
|
||||
diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
|
||||
index e82b274..30ab51a 100644
|
||||
--- a/daxctl/libdaxctl.h
|
||||
+++ b/daxctl/libdaxctl.h
|
||||
@@ -71,6 +71,7 @@ int daxctl_dev_disable(struct daxctl_dev *dev);
|
||||
int daxctl_dev_enable_devdax(struct daxctl_dev *dev);
|
||||
int daxctl_dev_enable_ram(struct daxctl_dev *dev);
|
||||
int daxctl_dev_get_target_node(struct daxctl_dev *dev);
|
||||
+int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev);
|
||||
|
||||
struct daxctl_memory;
|
||||
struct daxctl_memory *daxctl_dev_get_memory(struct daxctl_dev *dev);
|
||||
diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh
|
||||
index 496e4f2..eed5906 100755
|
||||
--- a/test/daxctl-devices.sh
|
||||
+++ b/test/daxctl-devices.sh
|
||||
@@ -64,6 +64,26 @@ daxctl_get_mode()
|
||||
"$DAXCTL" list -d "$1" | jq -er '.[].mode'
|
||||
}
|
||||
|
||||
+set_online_policy()
|
||||
+{
|
||||
+ echo "online" > /sys/devices/system/memory/auto_online_blocks
|
||||
+}
|
||||
+
|
||||
+unset_online_policy()
|
||||
+{
|
||||
+ echo "offline" > /sys/devices/system/memory/auto_online_blocks
|
||||
+}
|
||||
+
|
||||
+save_online_policy()
|
||||
+{
|
||||
+ saved_policy="$(cat /sys/devices/system/memory/auto_online_blocks)"
|
||||
+}
|
||||
+
|
||||
+restore_online_policy()
|
||||
+{
|
||||
+ echo "$saved_policy" > /sys/devices/system/memory/auto_online_blocks
|
||||
+}
|
||||
+
|
||||
daxctl_test()
|
||||
{
|
||||
local daxdev
|
||||
@@ -71,6 +91,9 @@ daxctl_test()
|
||||
daxdev=$(daxctl_get_dev "$testdev")
|
||||
test -n "$daxdev"
|
||||
|
||||
+ # these tests need to run with kernel onlining policy turned off
|
||||
+ save_online_policy
|
||||
+ unset_online_policy
|
||||
"$DAXCTL" reconfigure-device -N -m system-ram "$daxdev"
|
||||
[[ $(daxctl_get_mode "$daxdev") == "system-ram" ]]
|
||||
"$DAXCTL" online-memory "$daxdev"
|
||||
@@ -81,6 +104,19 @@ daxctl_test()
|
||||
[[ $(daxctl_get_mode "$daxdev") == "system-ram" ]]
|
||||
"$DAXCTL" reconfigure-device -f -m devdax "$daxdev"
|
||||
[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
|
||||
+
|
||||
+ # this tests for reconfiguration failure if an online-policy is set
|
||||
+ set_online_policy
|
||||
+ : "This command is expected to fail:"
|
||||
+ if ! "$DAXCTL" reconfigure-device -N -m system-ram "$daxdev"; then
|
||||
+ echo "reconfigure failed as expected"
|
||||
+ else
|
||||
+ echo "reconfigure succeded, expected failure"
|
||||
+ restore_online_policy
|
||||
+ return 1
|
||||
+ fi
|
||||
+
|
||||
+ restore_online_policy
|
||||
}
|
||||
|
||||
find_testdev
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,63 @@
|
||||
From e563e6a7c55e65c554e07db6215f8bcb2d411d3b Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Tue, 30 Mar 2021 20:50:37 -0600
|
||||
Subject: [PATCH 015/217] libdaxctl: add an API to check if a device is active
|
||||
|
||||
Add an API to check whether a daxctl device is active in system-ram
|
||||
mode. This would be used from libndctl during
|
||||
ndctl_namespace_disable_safe(), so that we don't disable/destroy an
|
||||
underlying namespace while the memory is active and online.
|
||||
|
||||
Reported-by: Chunye Xu <chunye.xu@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Cc: Dave Hansen <dave.hansen@linux.intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
daxctl/lib/libdaxctl.c | 10 ++++++++++
|
||||
daxctl/lib/libdaxctl.sym | 1 +
|
||||
daxctl/libdaxctl.h | 1 +
|
||||
3 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
|
||||
index 879f7e6..860bd9c 100644
|
||||
--- a/daxctl/lib/libdaxctl.c
|
||||
+++ b/daxctl/lib/libdaxctl.c
|
||||
@@ -1665,3 +1665,13 @@ DAXCTL_EXPORT int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev)
|
||||
/* match both "online" and "online_movable" */
|
||||
return !strncmp(buf, "online", 6);
|
||||
}
|
||||
+
|
||||
+DAXCTL_EXPORT int daxctl_dev_has_online_memory(struct daxctl_dev *dev)
|
||||
+{
|
||||
+ struct daxctl_memory *mem = daxctl_dev_get_memory(dev);
|
||||
+
|
||||
+ if (mem)
|
||||
+ return daxctl_memory_is_online(mem);
|
||||
+ else
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
|
||||
index 892e393..a13e93d 100644
|
||||
--- a/daxctl/lib/libdaxctl.sym
|
||||
+++ b/daxctl/lib/libdaxctl.sym
|
||||
@@ -95,4 +95,5 @@ global:
|
||||
LIBDAXCTL_9 {
|
||||
global:
|
||||
daxctl_dev_will_auto_online_memory;
|
||||
+ daxctl_dev_has_online_memory;
|
||||
} LIBDAXCTL_8;
|
||||
diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
|
||||
index 30ab51a..683ae9c 100644
|
||||
--- a/daxctl/libdaxctl.h
|
||||
+++ b/daxctl/libdaxctl.h
|
||||
@@ -72,6 +72,7 @@ int daxctl_dev_enable_devdax(struct daxctl_dev *dev);
|
||||
int daxctl_dev_enable_ram(struct daxctl_dev *dev);
|
||||
int daxctl_dev_get_target_node(struct daxctl_dev *dev);
|
||||
int daxctl_dev_will_auto_online_memory(struct daxctl_dev *dev);
|
||||
+int daxctl_dev_has_online_memory(struct daxctl_dev *dev);
|
||||
|
||||
struct daxctl_memory;
|
||||
struct daxctl_memory *daxctl_dev_get_memory(struct daxctl_dev *dev);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,113 @@
|
||||
From 573f0d46cff15fff2804b3fb444d1e34f482e788 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Tue, 30 Mar 2021 20:54:55 -0600
|
||||
Subject: [PATCH 016/217] libndctl: check for active system-ram before
|
||||
disabling daxctl devices
|
||||
|
||||
Teach ndctl_namespace_disable_safe() to look at the state of a
|
||||
daxctl_dev with respect to whether it is active in 'system-ram' mode
|
||||
before disabling it. This is similar to checking whether a filesystem is
|
||||
actively mounted on a namespace before disabling it.
|
||||
|
||||
Without this, libndctl would happily disable a devdax namespace while the
|
||||
device was active in system-ram mode. If the namespace was subsequently
|
||||
also destroyed, this would leave the memory without any sort of a
|
||||
'handle' to perform any subsequent operation on it, and the system would
|
||||
have to be rebooted to get out of this situation.
|
||||
|
||||
Reported-by: Chunye Xu <chunye.xu@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Cc: Dave Hansen <dave.hansen@linux.intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 25 ++++++++++++++++++++++++-
|
||||
test/daxctl-devices.sh | 16 ++++++++++++++++
|
||||
2 files changed, 40 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 2f6d806..2eda56c 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -4593,21 +4593,40 @@ NDCTL_EXPORT int ndctl_namespace_disable_invalidate(struct ndctl_namespace *ndns
|
||||
return ndctl_namespace_disable(ndns);
|
||||
}
|
||||
|
||||
+static int ndctl_dax_has_active_memory(struct ndctl_dax *dax)
|
||||
+{
|
||||
+ struct daxctl_region *dax_region;
|
||||
+ struct daxctl_dev *dax_dev;
|
||||
+
|
||||
+ dax_region = ndctl_dax_get_daxctl_region(dax);
|
||||
+ if (!dax_region)
|
||||
+ return 0;
|
||||
+
|
||||
+ daxctl_dev_foreach(dax_region, dax_dev)
|
||||
+ if (daxctl_dev_has_online_memory(dax_dev))
|
||||
+ return 1;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns)
|
||||
{
|
||||
const char *devname = ndctl_namespace_get_devname(ndns);
|
||||
struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
|
||||
struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns);
|
||||
struct ndctl_btt *btt = ndctl_namespace_get_btt(ndns);
|
||||
+ struct ndctl_dax *dax = ndctl_namespace_get_dax(ndns);
|
||||
const char *bdev = NULL;
|
||||
+ int fd, active = 0;
|
||||
char path[50];
|
||||
- int fd;
|
||||
unsigned long long size = ndctl_namespace_get_size(ndns);
|
||||
|
||||
if (pfn && ndctl_pfn_is_enabled(pfn))
|
||||
bdev = ndctl_pfn_get_block_device(pfn);
|
||||
else if (btt && ndctl_btt_is_enabled(btt))
|
||||
bdev = ndctl_btt_get_block_device(btt);
|
||||
+ else if (dax && ndctl_dax_is_enabled(dax))
|
||||
+ active = ndctl_dax_has_active_memory(dax);
|
||||
else if (ndctl_namespace_is_enabled(ndns))
|
||||
bdev = ndctl_namespace_get_block_device(ndns);
|
||||
|
||||
@@ -4632,6 +4651,10 @@ NDCTL_EXPORT int ndctl_namespace_disable_safe(struct ndctl_namespace *ndns)
|
||||
devname, bdev, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
+ } else if (active) {
|
||||
+ dbg(ctx, "%s: active as system-ram, refusing to disable\n",
|
||||
+ devname);
|
||||
+ return -EBUSY;
|
||||
} else {
|
||||
if (size == 0)
|
||||
/* No disable necessary due to no capacity allocated */
|
||||
diff --git a/test/daxctl-devices.sh b/test/daxctl-devices.sh
|
||||
index eed5906..56c9691 100755
|
||||
--- a/test/daxctl-devices.sh
|
||||
+++ b/test/daxctl-devices.sh
|
||||
@@ -105,6 +105,22 @@ daxctl_test()
|
||||
"$DAXCTL" reconfigure-device -f -m devdax "$daxdev"
|
||||
[[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
|
||||
|
||||
+ # fail 'ndctl-disable-namespace' while the devdax namespace is active
|
||||
+ # as system-ram. If this test fails, a reboot will be required to
|
||||
+ # recover from the resulting state.
|
||||
+ test -n "$testdev"
|
||||
+ "$DAXCTL" reconfigure-device -m system-ram "$daxdev"
|
||||
+ [[ $(daxctl_get_mode "$daxdev") == "system-ram" ]]
|
||||
+ if ! "$NDCTL" disable-namespace "$testdev"; then
|
||||
+ echo "disable-namespace failed as expected"
|
||||
+ else
|
||||
+ echo "disable-namespace succeded, expected failure"
|
||||
+ echo "reboot required to recover from this state"
|
||||
+ return 1
|
||||
+ fi
|
||||
+ "$DAXCTL" reconfigure-device -f -m devdax "$daxdev"
|
||||
+ [[ $(daxctl_get_mode "$daxdev") == "devdax" ]]
|
||||
+
|
||||
# this tests for reconfiguration failure if an online-policy is set
|
||||
set_online_policy
|
||||
: "This command is expected to fail:"
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,49 @@
|
||||
From e81f890c7ae1c940c7f52b8984e8728706489728 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Wed, 31 Mar 2021 13:51:35 -0600
|
||||
Subject: [PATCH 017/217] daxctl: emit counts of total and online memblocks
|
||||
|
||||
Fir daxctl device listings, if in 'system-ram' mode, it is useful to
|
||||
know whether the memory associated with the device is online or not.
|
||||
Since the memory is comprised of a number of 'memblocks', and it is
|
||||
possible (albeit rare) to have a subset of them online, and the rest
|
||||
offline, we can't just use a boolean online-or-offline flag for the
|
||||
state.
|
||||
|
||||
Add a couple of counts, one for the total number of memblocks associated
|
||||
with the device, and another for the ones that are online.
|
||||
|
||||
Link: https://github.com/pmem/ndctl/issues/139
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Cc: Dave Hansen <dave.hansen@linux.intel.com>
|
||||
Reported-by: Steve Scargall <steve.scargall@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
util/json.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/util/json.c b/util/json.c
|
||||
index ca0167b..a8d2412 100644
|
||||
--- a/util/json.c
|
||||
+++ b/util/json.c
|
||||
@@ -482,6 +482,17 @@ struct json_object *util_daxctl_dev_to_json(struct daxctl_dev *dev,
|
||||
json_object_object_add(jdev, "mode", jobj);
|
||||
|
||||
if (mem && daxctl_dev_get_resource(dev) != 0) {
|
||||
+ int num_sections = daxctl_memory_num_sections(mem);
|
||||
+ int num_online = daxctl_memory_is_online(mem);
|
||||
+
|
||||
+ jobj = json_object_new_int(num_online);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdev, "online_memblocks", jobj);
|
||||
+
|
||||
+ jobj = json_object_new_int(num_sections);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdev, "total_memblocks", jobj);
|
||||
+
|
||||
movable = daxctl_memory_is_movable(mem);
|
||||
if (movable == 1)
|
||||
jobj = json_object_new_boolean(true);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,24 +1,22 @@
|
||||
libndctl: Unify adding dimms for papr and nfit families
|
||||
From daef3a386a9c45105a2c045ddee46600e265939f Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu, 13 May 2021 11:42:15 +0530
|
||||
Subject: [PATCH 018/217] libndctl: Unify adding dimms for papr and nfit
|
||||
families
|
||||
|
||||
BZ:
|
||||
Brew:
|
||||
In preparation for enabling tests on non-nfit devices, unify both, already very
|
||||
similar, functions into one. This will help in adding all attributes needed for
|
||||
the unit tests. Since the function doesn't fail if some of the dimm attributes
|
||||
are missing, this will work fine on PAPR platforms though only part of the DIMM
|
||||
attributes are provided (This doesn't mean that all of the DIMM attributes can
|
||||
be missing).
|
||||
|
||||
commit daef3a386a9c45105a2c045ddee46600e265939f
|
||||
Author: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu May 13 11:42:15 2021 +0530
|
||||
|
||||
libndctl: Unify adding dimms for papr and nfit families
|
||||
|
||||
In preparation for enabling tests on non-nfit devices, unify both, already very
|
||||
similar, functions into one. This will help in adding all attributes needed for
|
||||
the unit tests. Since the function doesn't fail if some of the dimm attributes
|
||||
are missing, this will work fine on PAPR platforms though only part of the DIMM
|
||||
attributes are provided (This doesn't mean that all of the DIMM attributes can
|
||||
be missing).
|
||||
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-1-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-1-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 103 ++++++++++++++++---------------------------
|
||||
1 file changed, 38 insertions(+), 65 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 2f6d806..e45353f 100644
|
||||
@ -217,3 +215,6 @@ index 2f6d806..e45353f 100644
|
||||
|
||||
sprintf(path, "%s/read_only", region_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,19 +1,26 @@
|
||||
test: Don't skip tests if nfit modules are missing
|
||||
From 1649ad9c3e2c6e9c47870c8d3b54f10b24177bc7 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu, 13 May 2021 11:42:16 +0530
|
||||
Subject: [PATCH 019/217] test: Don't skip tests if nfit modules are missing
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141031
|
||||
For NFIT to be available ACPI is a must, so don't fail when nfit modules
|
||||
are missing on a platform that doesn't support ACPI.
|
||||
|
||||
commit 1649ad9c3e2c6e9c47870c8d3b54f10b24177bc7
|
||||
Author: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu May 13 11:42:16 2021 +0530
|
||||
|
||||
test: Don't skip tests if nfit modules are missing
|
||||
|
||||
For NFIT to be available ACPI is a must, so don't fail when nfit modules
|
||||
are missing on a platform that doesn't support ACPI.
|
||||
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-2-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-2-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test.h | 2 +-
|
||||
test/ack-shutdown-count-set.c | 2 +-
|
||||
test/blk_namespaces.c | 2 +-
|
||||
test/core.c | 28 ++++++++++++++++++++++++++--
|
||||
test/dpa-alloc.c | 2 +-
|
||||
test/dsm-fail.c | 2 +-
|
||||
test/libndctl.c | 2 +-
|
||||
test/multi-pmem.c | 2 +-
|
||||
test/parent-uuid.c | 2 +-
|
||||
test/pmem_namespaces.c | 2 +-
|
||||
10 files changed, 35 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/test.h b/test.h
|
||||
index cba8d41..7de13fe 100644
|
||||
@ -199,3 +206,6 @@ index f0f2edd..a4db1ae 100644
|
||||
ndctl_invalidate(ctx);
|
||||
bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0");
|
||||
if (rc < 0 || !bus) {
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,20 +1,17 @@
|
||||
papr: Add support to parse save_fail flag for dimm
|
||||
From f081f302505209430df46908775a3cffb875a5c7 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu, 13 May 2021 11:42:17 +0530
|
||||
Subject: [PATCH 020/217] papr: Add support to parse save_fail flag for dimm
|
||||
|
||||
BZ:
|
||||
Brew:
|
||||
This will help in getting the dimm fail tests to run on papr family too.
|
||||
Also add nvdimm_test compatibility string for recognizing the test module.
|
||||
|
||||
commit f081f302505209430df46908775a3cffb875a5c7
|
||||
Author: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu May 13 11:42:17 2021 +0530
|
||||
|
||||
papr: Add support to parse save_fail flag for dimm
|
||||
|
||||
This will help in getting the dimm fail tests to run on papr family too.
|
||||
Also add nvdimm_test compatibility string for recognizing the test module.
|
||||
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-3-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-3-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index e45353f..a8b99ea 100644
|
||||
@ -39,3 +36,6 @@ index e45353f..a8b99ea 100644
|
||||
}
|
||||
|
||||
/**
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,26 +1,26 @@
|
||||
Use page size as alignment value
|
||||
From fe831b526b88f6ca7a27fdb149b8a7d2ecddbc55 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu, 13 May 2021 11:42:18 +0530
|
||||
Subject: [PATCH 021/217] Use page size as alignment value
|
||||
|
||||
BZ:
|
||||
Brew:
|
||||
The alignment sizes passed to ndctl in the tests are all hardcoded to 4k,
|
||||
the default page size on x86. Change those to the default page size on that
|
||||
architecture (sysconf/getconf). No functional changes otherwise.
|
||||
|
||||
commit fe831b526b88f6ca7a27fdb149b8a7d2ecddbc55
|
||||
Author: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Thu May 13 11:42:18 2021 +0530
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-4-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/dpa-alloc.c | 15 ++++++++-------
|
||||
test/multi-dax.sh | 6 ++++--
|
||||
test/sector-mode.sh | 4 +++-
|
||||
3 files changed, 15 insertions(+), 10 deletions(-)
|
||||
|
||||
Use page size as alignment value
|
||||
|
||||
The alignment sizes passed to ndctl in the tests are all hardcoded to 4k,
|
||||
the default page size on x86. Change those to the default page size on that
|
||||
architecture (sysconf/getconf). No functional changes otherwise.
|
||||
|
||||
Link: https://lore.kernel.org/r/20210513061218.760322-4-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
|
||||
diff -up ndctl-71.1/test/dpa-alloc.c.orig ndctl-71.1/test/dpa-alloc.c
|
||||
--- ndctl-71.1/test/dpa-alloc.c.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/test/dpa-alloc.c 2022-06-06 17:13:12.045108349 -0400
|
||||
@@ -38,12 +38,13 @@ static int do_test(struct ndctl_ctx *ctx
|
||||
diff --git a/test/dpa-alloc.c b/test/dpa-alloc.c
|
||||
index 0b3bb7a..59185cf 100644
|
||||
--- a/test/dpa-alloc.c
|
||||
+++ b/test/dpa-alloc.c
|
||||
@@ -38,12 +38,13 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
struct ndctl_region *region, *blk_region = NULL;
|
||||
struct ndctl_namespace *ndns;
|
||||
struct ndctl_dimm *dimm;
|
||||
@ -35,7 +35,7 @@ diff -up ndctl-71.1/test/dpa-alloc.c.orig ndctl-71.1/test/dpa-alloc.c
|
||||
/* disable nfit_test.1, not used in this test */
|
||||
bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER1);
|
||||
if (!bus)
|
||||
@@ -124,11 +125,11 @@ static int do_test(struct ndctl_ctx *ctx
|
||||
@@ -124,11 +125,11 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
return rc;
|
||||
}
|
||||
ndctl_namespace_disable_invalidate(ndns);
|
||||
@ -50,7 +50,7 @@ diff -up ndctl-71.1/test/dpa-alloc.c.orig ndctl-71.1/test/dpa-alloc.c
|
||||
return rc;
|
||||
}
|
||||
namespaces[i].ndns = ndns;
|
||||
@@ -150,7 +151,7 @@ static int do_test(struct ndctl_ctx *ctx
|
||||
@@ -150,7 +151,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
ndns = namespaces[i % ARRAY_SIZE(namespaces)].ndns;
|
||||
if (i % ARRAY_SIZE(namespaces) == 0)
|
||||
round++;
|
||||
@ -59,7 +59,7 @@ diff -up ndctl-71.1/test/dpa-alloc.c.orig ndctl-71.1/test/dpa-alloc.c
|
||||
rc = ndctl_namespace_set_size(ndns, size);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: set_size: %lx failed: %d\n",
|
||||
@@ -166,7 +167,7 @@ static int do_test(struct ndctl_ctx *ctx
|
||||
@@ -166,7 +167,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
i--;
|
||||
round++;
|
||||
ndns = namespaces[i % ARRAY_SIZE(namespaces)].ndns;
|
||||
@ -68,7 +68,7 @@ diff -up ndctl-71.1/test/dpa-alloc.c.orig ndctl-71.1/test/dpa-alloc.c
|
||||
rc = ndctl_namespace_set_size(ndns, size);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s failed to update while labels full\n",
|
||||
@@ -175,7 +176,7 @@ static int do_test(struct ndctl_ctx *ctx
|
||||
@@ -175,7 +176,7 @@ static int do_test(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
}
|
||||
|
||||
round--;
|
||||
@ -77,10 +77,11 @@ diff -up ndctl-71.1/test/dpa-alloc.c.orig ndctl-71.1/test/dpa-alloc.c
|
||||
rc = ndctl_namespace_set_size(ndns, size);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s failed to reduce size while labels full\n",
|
||||
diff -up ndctl-71.1/test/multi-dax.sh.orig ndctl-71.1/test/multi-dax.sh
|
||||
--- ndctl-71.1/test/multi-dax.sh.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/test/multi-dax.sh 2022-06-06 17:13:12.046108353 -0400
|
||||
@@ -12,6 +12,8 @@ check_min_kver "4.13" || do_skip "may la
|
||||
diff --git a/test/multi-dax.sh b/test/multi-dax.sh
|
||||
index 8496619..b343a38 100755
|
||||
--- a/test/multi-dax.sh
|
||||
+++ b/test/multi-dax.sh
|
||||
@@ -13,6 +13,8 @@ check_prereq "jq"
|
||||
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
@ -89,7 +90,7 @@ diff -up ndctl-71.1/test/multi-dax.sh.orig ndctl-71.1/test/multi-dax.sh
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
@@ -22,9 +24,9 @@ rc=1
|
||||
@@ -23,9 +25,9 @@ rc=1
|
||||
query=". | sort_by(.available_size) | reverse | .[0].dev"
|
||||
region=$($NDCTL list -b $NFIT_TEST_BUS0 -t pmem -Ri | jq -r "$query")
|
||||
|
||||
@ -101,10 +102,11 @@ diff -up ndctl-71.1/test/multi-dax.sh.orig ndctl-71.1/test/multi-dax.sh
|
||||
chardev2=$(echo $json | jq ". | select(.mode == \"devdax\") | .daxregion.devices[0].chardev")
|
||||
|
||||
_cleanup
|
||||
diff -up ndctl-71.1/test/sector-mode.sh.orig ndctl-71.1/test/sector-mode.sh
|
||||
--- ndctl-71.1/test/sector-mode.sh.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/test/sector-mode.sh 2022-06-06 17:13:12.046108353 -0400
|
||||
@@ -9,6 +9,8 @@ rc=77
|
||||
diff --git a/test/sector-mode.sh b/test/sector-mode.sh
|
||||
index 54fa806..7a2faea 100755
|
||||
--- a/test/sector-mode.sh
|
||||
+++ b/test/sector-mode.sh
|
||||
@@ -11,6 +11,8 @@ check_prereq "jq"
|
||||
set -e
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
@ -113,7 +115,7 @@ diff -up ndctl-71.1/test/sector-mode.sh.orig ndctl-71.1/test/sector-mode.sh
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
@@ -25,7 +27,7 @@ NAMESPACE=$($NDCTL list -b $NFIT_TEST_BU
|
||||
@@ -27,7 +29,7 @@ NAMESPACE=$($NDCTL list -b $NFIT_TEST_BUS1 -N | jq -r "$query")
|
||||
REGION=$($NDCTL list -R --namespace=$NAMESPACE | jq -r "(.[]) | .dev")
|
||||
echo 0 > /sys/bus/nd/devices/$REGION/read_only
|
||||
$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K
|
||||
@ -122,3 +124,6 @@ diff -up ndctl-71.1/test/sector-mode.sh.orig ndctl-71.1/test/sector-mode.sh
|
||||
$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K
|
||||
|
||||
_cleanup
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 561af4f919b3f1b3d1a213137f1d024420996d56 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Sun, 28 Mar 2021 05:43:51 +0530
|
||||
Subject: [PATCH 022/217] libndctl: Remove redundant checks and assignments
|
||||
|
||||
check_udev already checks for udev allocation failure, remove the redundant
|
||||
check.
|
||||
|
||||
Link: https://lore.kernel.org/r/20210328001351.2245032-1-santosh@fossix.org
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index bf0968c..3a496ed 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -323,12 +323,9 @@ NDCTL_EXPORT int ndctl_new(struct ndctl_ctx **ctx)
|
||||
dbg(c, "timeout = %ld\n", tmo);
|
||||
}
|
||||
|
||||
- if (udev) {
|
||||
- c->udev = udev;
|
||||
- c->udev_queue = udev_queue_new(udev);
|
||||
- if (!c->udev_queue)
|
||||
- err(c, "failed to retrieve udev queue\n");
|
||||
- }
|
||||
+ c->udev_queue = udev_queue_new(udev);
|
||||
+ if (!c->udev_queue)
|
||||
+ err(c, "failed to retrieve udev queue\n");
|
||||
|
||||
c->kmod_ctx = kmod_ctx;
|
||||
c->daxctl_ctx = daxctl_ctx;
|
||||
--
|
||||
2.27.0
|
||||
|
56
SOURCES/0023-ndctl-Update-nvdimm-mailing-list-address.patch
Normal file
56
SOURCES/0023-ndctl-Update-nvdimm-mailing-list-address.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 063af7c447d257397a925df81897da2c71e31653 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Tue, 18 May 2021 16:25:27 -0600
|
||||
Subject: [PATCH 023/217] ndctl: Update nvdimm mailing list address
|
||||
|
||||
The 'nvdimm' mailing list has moved from lists.01.org to
|
||||
lists.linux.dev. Update CONTRIBUTING.md and configure.ac to reflect
|
||||
this.
|
||||
|
||||
Link: https://lore.kernel.org/r/20210518222527.550730-1-vishal.l.verma@intel.com
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
CONTRIBUTING.md | 7 ++++---
|
||||
configure.ac | 2 +-
|
||||
2 files changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
|
||||
index 4c29d31..4f4865d 100644
|
||||
--- a/CONTRIBUTING.md
|
||||
+++ b/CONTRIBUTING.md
|
||||
@@ -6,13 +6,14 @@ The following is a set of guidelines that we adhere to, and request that
|
||||
contributors follow.
|
||||
|
||||
1. The libnvdimm (kernel subsystem) and ndctl developers primarily use
|
||||
- the [linux-nvdimm](https://lists.01.org/postorius/lists/linux-nvdimm.lists.01.org/)
|
||||
+ the [nvdimm](https://subspace.kernel.org/lists.linux.dev.html)
|
||||
mailing list for everything. It is recommended to send patches to
|
||||
- **```linux-nvdimm@lists.01.org```**
|
||||
+ **```nvdimm@lists.linux.dev```**
|
||||
+ An archive is available on [lore](https://lore.kernel.org/nvdimm/)
|
||||
|
||||
1. Github [issues](https://github.com/pmem/ndctl/issues) are an acceptable
|
||||
way to report a problem, but if you just have a question,
|
||||
- [email](mailto:linux-nvdimm@lists.01.org) the above list.
|
||||
+ [email](mailto:nvdimm@lists.linux.dev) the above list.
|
||||
|
||||
1. We follow the Linux Kernel [Coding Style Guide][cs] as applicable.
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 5ec8d2f..dc39dbe 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -2,7 +2,7 @@ AC_PREREQ(2.60)
|
||||
m4_include([version.m4])
|
||||
AC_INIT([ndctl],
|
||||
GIT_VERSION,
|
||||
- [linux-nvdimm@lists.01.org],
|
||||
+ [nvdimm@lists.linux.dev],
|
||||
[ndctl],
|
||||
[https://github.com/pmem/ndctl])
|
||||
AC_CONFIG_SRCDIR([ndctl/lib/libndctl.c])
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,122 @@
|
||||
From e086106b4d81a2079141c848db7695451c04e877 Mon Sep 17 00:00:00 2001
|
||||
From: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Date: Mon, 17 May 2021 21:18:24 +0530
|
||||
Subject: [PATCH 024/217] libndctl/papr: Fix probe for papr-scm compatible
|
||||
nvdimms
|
||||
|
||||
With recent changes introduced for unification of PAPR and NFIT
|
||||
families the probe for papr-scm nvdimms is broken since they don't
|
||||
expose 'handle' or 'phys_id' sysfs attributes. These attributes are
|
||||
only exposed by NFIT and 'nvdimm_test' nvdimms. Since 'unable to read'
|
||||
these sysfs attributes is a non-recoverable error hence this prevents
|
||||
probing of 'PAPR-SCM' nvdimms and ndctl reports following error:
|
||||
|
||||
$ sudo NDCTL_LOG=debug ndctl list -DH
|
||||
libndctl: ndctl_new: ctx 0x10015342c70 created
|
||||
libndctl: add_dimm: nmem1: probe failed: Operation not permitted
|
||||
libndctl: __sysfs_device_parse: nmem1: add_dev() failed
|
||||
libndctl: add_dimm: nmem0: probe failed: Operation not permitted
|
||||
libndctl: __sysfs_device_parse: nmem0: add_dev() failed
|
||||
|
||||
Fixing this bug is complicated by the fact these attributes are needed
|
||||
for by the 'nvdimm_test' nvdimms which also uses the
|
||||
NVDIMM_FAMILY_PAPR. Adding a two way comparison for these two
|
||||
attributes in populate_dimm_attributes() to distinguish between
|
||||
'nvdimm_test' and papr-scm nvdimms will be clunky and make future
|
||||
updates to populate_dimm_attributes() error prone.
|
||||
|
||||
So, this patch proposes to fix the issue by re-introducing
|
||||
add_papr_dimm() to probe both papr-scm and 'nvdimm_test' nvdimms. The
|
||||
'compatible' sysfs attribute associated with the PAPR device is used
|
||||
to distinguish between the two nvdimm types and in case an
|
||||
'nvdimm_test' device is detected then forward its probe to
|
||||
populate_dimm_attributes().
|
||||
|
||||
families")
|
||||
|
||||
Link: https://lore.kernel.org/r/20210517154824.142237-1-vaibhav@linux.ibm.com
|
||||
Fixes: daef3a386a9c("libndctl: Unify adding dimms for papr and nfit
|
||||
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 57 ++++++++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 55 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 3a496ed..aa36a3c 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -1754,6 +1754,58 @@ static int populate_dimm_attributes(struct ndctl_dimm *dimm,
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int add_papr_dimm(struct ndctl_dimm *dimm, const char *dimm_base)
|
||||
+{
|
||||
+ int rc = -ENODEV;
|
||||
+ char buf[SYSFS_ATTR_SIZE];
|
||||
+ struct ndctl_ctx *ctx = dimm->bus->ctx;
|
||||
+ char *path = calloc(1, strlen(dimm_base) + 100);
|
||||
+ const char * const devname = ndctl_dimm_get_devname(dimm);
|
||||
+
|
||||
+ dbg(ctx, "%s: Probing of_pmem dimm at %s\n", devname, dimm_base);
|
||||
+
|
||||
+ if (!path)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* Check the compatibility of the probed nvdimm */
|
||||
+ sprintf(path, "%s/../of_node/compatible", dimm_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) < 0) {
|
||||
+ dbg(ctx, "%s: Unable to read compatible field\n", devname);
|
||||
+ rc = -ENODEV;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ dbg(ctx, "%s:Compatible of_pmem = '%s'\n", devname, buf);
|
||||
+
|
||||
+ /* Probe for papr-scm memory */
|
||||
+ if (strcmp(buf, "ibm,pmemory") == 0) {
|
||||
+ /* Read the dimm flags file */
|
||||
+ sprintf(path, "%s/papr/flags", dimm_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) < 0) {
|
||||
+ rc = -errno;
|
||||
+ err(ctx, "%s: Unable to read dimm-flags\n", devname);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ dbg(ctx, "%s: Adding papr-scm dimm flags:\"%s\"\n", devname, buf);
|
||||
+ dimm->cmd_family = NVDIMM_FAMILY_PAPR;
|
||||
+
|
||||
+ /* Parse dimm flags */
|
||||
+ parse_papr_flags(dimm, buf);
|
||||
+
|
||||
+ /* Allocate monitor mode fd */
|
||||
+ dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC);
|
||||
+ rc = 0;
|
||||
+
|
||||
+ } else if (strcmp(buf, "nvdimm_test") == 0) {
|
||||
+ /* probe via common populate_dimm_attributes() */
|
||||
+ rc = populate_dimm_attributes(dimm, dimm_base, "papr");
|
||||
+ }
|
||||
+out:
|
||||
+ free(path);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
static void *add_dimm(void *parent, int id, const char *dimm_base)
|
||||
{
|
||||
int formats, i, rc = -ENODEV;
|
||||
@@ -1845,8 +1897,9 @@ static void *add_dimm(void *parent, int id, const char *dimm_base)
|
||||
/* Check if the given dimm supports nfit */
|
||||
if (ndctl_bus_has_nfit(bus)) {
|
||||
rc = populate_dimm_attributes(dimm, dimm_base, "nfit");
|
||||
- } else if (ndctl_bus_has_of_node(bus))
|
||||
- rc = populate_dimm_attributes(dimm, dimm_base, "papr");
|
||||
+ } else if (ndctl_bus_has_of_node(bus)) {
|
||||
+ rc = add_papr_dimm(dimm, dimm_base);
|
||||
+ }
|
||||
|
||||
if (rc == -ENODEV) {
|
||||
/* Unprobed dimm with no family */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,38 @@
|
||||
From c52109355b715bbe21e284090435bee7563863cc Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 26 May 2021 16:33:04 -0700
|
||||
Subject: [PATCH 025/217] ndctl/scrub: Stop translating return values
|
||||
|
||||
In preparation for triggering a poll loop within ndctl_bus_start_scrub(),
|
||||
stop translating return values into -EOPNOTSUPP.
|
||||
|
||||
Link: https://lore.kernel.org/r/162207198482.3715490.5994844104395495686.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 8 +-------
|
||||
1 file changed, 1 insertion(+), 7 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index aa36a3c..e5641fe 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -1354,14 +1354,8 @@ static int __ndctl_bus_get_scrub_state(struct ndctl_bus *bus,
|
||||
NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus)
|
||||
{
|
||||
struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
|
||||
- int rc;
|
||||
|
||||
- rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n");
|
||||
- if (rc == -EBUSY)
|
||||
- return rc;
|
||||
- else if (rc < 0)
|
||||
- return -EOPNOTSUPP;
|
||||
- return 0;
|
||||
+ return sysfs_write_attr(ctx, bus->scrub_path, "1\n");
|
||||
}
|
||||
|
||||
NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus)
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,48 @@
|
||||
From 4e646fa490ba4b782afa188dd8818b94c419924e Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 26 May 2021 16:33:10 -0700
|
||||
Subject: [PATCH 026/217] ndctl/scrub: Reread scrub-engine status at start
|
||||
|
||||
Given that the kernel has exponential backoff to cover the lack of
|
||||
interrupts for scrub completion status there is a reasonable likelihood
|
||||
that 'ndctl start-scrub' is issued while the hardware/platform scrub-state
|
||||
is idle, but the kernel engine poll timer has not fired.
|
||||
|
||||
Trigger at least one poll cycle for the kernel to re-read the scrub-state
|
||||
before reporting that ARS is busy.
|
||||
|
||||
Link: https://lore.kernel.org/r/162207199057.3715490.2469820075085914776.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Reported-by: Krzysztof Rusocki <krzysztof.rusocki@intel.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 12 +++++++++++-
|
||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index e5641fe..536e142 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -1354,8 +1354,18 @@ static int __ndctl_bus_get_scrub_state(struct ndctl_bus *bus,
|
||||
NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus)
|
||||
{
|
||||
struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n");
|
||||
|
||||
- return sysfs_write_attr(ctx, bus->scrub_path, "1\n");
|
||||
+ /*
|
||||
+ * Try at least 1 poll cycle before reporting busy in case this
|
||||
+ * request hits the kernel's exponential backoff while the
|
||||
+ * hardware/platform scrub state is idle.
|
||||
+ */
|
||||
+ if (rc == -EBUSY && ndctl_bus_poll_scrub_completion(bus, 1, 1) == 0)
|
||||
+ return sysfs_write_attr(ctx, bus->scrub_path, "1\n");
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus)
|
||||
--
|
||||
2.27.0
|
||||
|
167
SOURCES/0027-ndctl-dimm-Fix-label-index-block-calculations.patch
Normal file
167
SOURCES/0027-ndctl-dimm-Fix-label-index-block-calculations.patch
Normal file
@ -0,0 +1,167 @@
|
||||
From 7e98977c10ad5f4baf5e3bc4d5b4b2fd733a8b7e Mon Sep 17 00:00:00 2001
|
||||
From: Jingqi Liu <jingqi.liu@intel.com>
|
||||
Date: Thu, 8 Jul 2021 16:14:46 +0800
|
||||
Subject: [PATCH 027/217] ndctl/dimm: Fix label index block calculations
|
||||
|
||||
The following bug is caused by setting the size of Label Index Block
|
||||
to a fixed 256 bytes.
|
||||
|
||||
Use the following Qemu command to start a Guest with 2MB label-size:
|
||||
-object memory-backend-file,id=mem1,share=on,mem-path=/dev/dax1.1,size=14G,align=2M
|
||||
-device nvdimm,memdev=mem1,id=nv1,label-size=2M
|
||||
|
||||
There is a namespace in the Guest as follows:
|
||||
$ ndctl list
|
||||
[
|
||||
{
|
||||
"dev":"namespace0.0",
|
||||
"mode":"devdax",
|
||||
"map":"dev",
|
||||
"size":14780727296,
|
||||
"uuid":"58ad5282-5a16-404f-b8ee-e28b4c784eb8",
|
||||
"chardev":"dax0.0",
|
||||
"align":2097152,
|
||||
"name":"namespace0.0"
|
||||
}
|
||||
]
|
||||
|
||||
Fail to read labels. The result is as follows:
|
||||
$ ndctl read-labels -u nmem0
|
||||
[
|
||||
]
|
||||
read 0 nmem
|
||||
|
||||
If using the following Qemu command to start the Guest with 128K
|
||||
label-size, this label can be read correctly.
|
||||
-object memory-backend-file,id=mem1,share=on,mem-path=/dev/dax1.1,size=14G,align=2M
|
||||
-device nvdimm,memdev=mem1,id=nv1,label-size=128K
|
||||
|
||||
The size of a Label Index Block depends on how many label slots fit into
|
||||
the label storage area. The minimum size of an index block is 256 bytes
|
||||
and the size must be a multiple of 256 bytes. For a storage area of 128KB,
|
||||
the corresponding Label Index Block size is 256 bytes. But if the label
|
||||
storage area is not 128KB, the Label Index Block size should not be 256 bytes.
|
||||
|
||||
Namespace Label Index Block appears twice at the top of the label storage area.
|
||||
Following the two index blocks, an array for storing labels takes up the
|
||||
remainder of the label storage area.
|
||||
|
||||
For obtaining the size of Namespace Index Block, we also cannot rely on
|
||||
the field of 'mysize' in this index block since it might be corrupted.
|
||||
Similar to the linux kernel, we use sizeof_namespace_index() to get the size
|
||||
of Namespace Index Block. Then we can also correctly calculate the starting
|
||||
offset of the following namespace labels.
|
||||
|
||||
Link: https://lore.kernel.org/r/20210708081446.14323-1-jingqi.liu@intel.com
|
||||
Suggested-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Signed-off-by: Jingqi Liu <jingqi.liu@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/dimm.c | 19 +++++++++++++++----
|
||||
ndctl/lib/dimm.c | 5 +++++
|
||||
ndctl/lib/libndctl.sym | 1 +
|
||||
ndctl/libndctl.h | 1 +
|
||||
4 files changed, 22 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/ndctl/dimm.c b/ndctl/dimm.c
|
||||
index 09ce49e..1d2d9a2 100644
|
||||
--- a/ndctl/dimm.c
|
||||
+++ b/ndctl/dimm.c
|
||||
@@ -94,13 +94,18 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
|
||||
struct json_object *jarray = json_object_new_array();
|
||||
struct json_object *jlabel = NULL;
|
||||
struct namespace_label nslabel;
|
||||
+ unsigned int nsindex_size;
|
||||
unsigned int slot = -1;
|
||||
ssize_t offset;
|
||||
|
||||
if (!jarray)
|
||||
return NULL;
|
||||
|
||||
- for (offset = NSINDEX_ALIGN * 2; offset < size;
|
||||
+ nsindex_size = ndctl_dimm_sizeof_namespace_index(dimm);
|
||||
+ if (nsindex_size == 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (offset = nsindex_size * 2; offset < size;
|
||||
offset += ndctl_dimm_sizeof_namespace_label(dimm)) {
|
||||
ssize_t len = min_t(ssize_t,
|
||||
ndctl_dimm_sizeof_namespace_label(dimm),
|
||||
@@ -204,17 +209,23 @@ static struct json_object *dump_label_json(struct ndctl_dimm *dimm,
|
||||
return jarray;
|
||||
}
|
||||
|
||||
-static struct json_object *dump_index_json(struct ndctl_cmd *cmd_read, ssize_t size)
|
||||
+static struct json_object *dump_index_json(struct ndctl_dimm *dimm,
|
||||
+ struct ndctl_cmd *cmd_read, ssize_t size)
|
||||
{
|
||||
struct json_object *jarray = json_object_new_array();
|
||||
struct json_object *jindex = NULL;
|
||||
struct namespace_index nsindex;
|
||||
+ unsigned int nsindex_size;
|
||||
ssize_t offset;
|
||||
|
||||
if (!jarray)
|
||||
return NULL;
|
||||
|
||||
- for (offset = 0; offset < NSINDEX_ALIGN * 2; offset += NSINDEX_ALIGN) {
|
||||
+ nsindex_size = ndctl_dimm_sizeof_namespace_index(dimm);
|
||||
+ if (nsindex_size == 0)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (offset = 0; offset < nsindex_size * 2; offset += nsindex_size) {
|
||||
ssize_t len = min_t(ssize_t, sizeof(nsindex), size - offset);
|
||||
struct json_object *jobj;
|
||||
|
||||
@@ -288,7 +299,7 @@ static struct json_object *dump_json(struct ndctl_dimm *dimm,
|
||||
goto err;
|
||||
json_object_object_add(jdimm, "dev", jobj);
|
||||
|
||||
- jindex = dump_index_json(cmd_read, size);
|
||||
+ jindex = dump_index_json(dimm, cmd_read, size);
|
||||
if (!jindex)
|
||||
goto err;
|
||||
json_object_object_add(jdimm, "index", jindex);
|
||||
diff --git a/ndctl/lib/dimm.c b/ndctl/lib/dimm.c
|
||||
index c045cbe..9e36e28 100644
|
||||
--- a/ndctl/lib/dimm.c
|
||||
+++ b/ndctl/lib/dimm.c
|
||||
@@ -256,6 +256,11 @@ static int __label_validate(struct nvdimm_data *ndd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+NDCTL_EXPORT unsigned int ndctl_dimm_sizeof_namespace_index(struct ndctl_dimm *dimm)
|
||||
+{
|
||||
+ return sizeof_namespace_index(&dimm->ndd);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* If the dimm labels have not been previously validated this routine
|
||||
* will make up a default size. Otherwise, it will pick the size based
|
||||
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
|
||||
index 58afb74..5ee73b7 100644
|
||||
--- a/ndctl/lib/libndctl.sym
|
||||
+++ b/ndctl/lib/libndctl.sym
|
||||
@@ -454,4 +454,5 @@ LIBNDCTL_25 {
|
||||
|
||||
LIBNDCTL_26 {
|
||||
ndctl_bus_nfit_translate_spa;
|
||||
+ ndctl_dimm_sizeof_namespace_index;
|
||||
} LIBNDCTL_25;
|
||||
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
|
||||
index 87d07b7..df109bb 100644
|
||||
--- a/ndctl/libndctl.h
|
||||
+++ b/ndctl/libndctl.h
|
||||
@@ -337,6 +337,7 @@ int ndctl_dimm_init_labels(struct ndctl_dimm *dimm,
|
||||
enum ndctl_namespace_version v);
|
||||
unsigned long ndctl_dimm_get_available_labels(struct ndctl_dimm *dimm);
|
||||
unsigned int ndctl_dimm_sizeof_namespace_label(struct ndctl_dimm *dimm);
|
||||
+unsigned int ndctl_dimm_sizeof_namespace_index(struct ndctl_dimm *dimm);
|
||||
unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size);
|
||||
ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read, void *buf,
|
||||
unsigned int len, unsigned int offset);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 9bd2994f91bb77604521cbe09a76a51d092c2cfd Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <msuchanek@suse.de>
|
||||
Date: Wed, 6 Jan 2021 14:17:40 +0100
|
||||
Subject: [PATCH 028/217] ndctl/namespace: Skip seed namespaces when processing
|
||||
all namespaces.
|
||||
|
||||
The seed namespaces are exposed by the kernel but most operations are
|
||||
not valid on seed namespaces.
|
||||
|
||||
When processing all namespaces the user gets confusing errors from ndctl
|
||||
trying to process seed namespaces. The kernel does not provide any way
|
||||
to tell that a namspace is seed namespace but skipping namespaces with
|
||||
zero size and UUID is a good heuristic.
|
||||
|
||||
The user can still specify the namespace by name directly in case
|
||||
processing it is desirable.
|
||||
|
||||
Link: https://patchwork.kernel.org/patch/11473645/
|
||||
Link: https://lore.kernel.org/r/e55ae2c17b8b9c3288491efe6214338118e8c5ae.1609938610.git.msuchanek@suse.de
|
||||
Fixes: #41
|
||||
Tested-by: Harish Sriram <harish@linux.ibm.com>
|
||||
Reviewed-by: Santosh S <santosh@fossix.org>
|
||||
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/namespace.c | 16 +++++++++++++---
|
||||
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
|
||||
index 1e8a2cd..5e65ed5 100644
|
||||
--- a/ndctl/namespace.c
|
||||
+++ b/ndctl/namespace.c
|
||||
@@ -2210,9 +2210,19 @@ static int do_xaction_namespace(const char *namespace,
|
||||
ndctl_namespace_foreach_safe(region, ndns, _n) {
|
||||
ndns_name = ndctl_namespace_get_devname(ndns);
|
||||
|
||||
- if (strcmp(namespace, "all") != 0
|
||||
- && strcmp(namespace, ndns_name) != 0)
|
||||
- continue;
|
||||
+ if (strcmp(namespace, "all") == 0) {
|
||||
+ static const uuid_t zero_uuid;
|
||||
+ uuid_t uuid;
|
||||
+
|
||||
+ ndctl_namespace_get_uuid(ndns, uuid);
|
||||
+ if (!ndctl_namespace_get_size(ndns) &&
|
||||
+ !memcmp(uuid, zero_uuid, sizeof(uuid_t)))
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ if (strcmp(namespace, ndns_name) != 0)
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
switch (action) {
|
||||
case ACTION_DISABLE:
|
||||
rc = ndctl_namespace_disable_safe(ndns);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,82 @@
|
||||
From 07011a334fd1e4b641cdbfaf5de7500f7bdc941d Mon Sep 17 00:00:00 2001
|
||||
From: Michal Suchanek <msuchanek@suse.de>
|
||||
Date: Wed, 6 Jan 2021 14:17:41 +0100
|
||||
Subject: [PATCH 029/217] ndctl/namespace: Suppress -ENXIO when processing all
|
||||
namespaces.
|
||||
|
||||
When processing all namespaces and no namespaces exist user gets the
|
||||
default -ENXIO. Set default rc to 0 when processing all namespaces.
|
||||
This avoids confusing error message printed in addition to the message
|
||||
saying 0 namespaces were affected.
|
||||
|
||||
Before:
|
||||
|
||||
# ndctl check-namespace all
|
||||
namespace0.0: namespace_check: namespace0.0: check aborted, namespace online
|
||||
error checking namespaces: Device or resource busy
|
||||
checked 0 namespaces
|
||||
# ndctl disable-namespace all
|
||||
disabled 1 namespace
|
||||
# ndctl check-namespace all
|
||||
namespace0.0: namespace_check: Unable to recover any BTT info blocks
|
||||
error checking namespaces: No such device or address
|
||||
checked 0 namespaces
|
||||
# ndctl destroy-namespace all
|
||||
destroyed 1 namespace
|
||||
# ndctl check-namespace all
|
||||
error checking namespaces: No such device or address
|
||||
checked 0 namespaces
|
||||
# ndctl destroy-namespace all
|
||||
error destroying namespaces: No such device or address
|
||||
destroyed 0 namespaces
|
||||
|
||||
After:
|
||||
|
||||
# ndctl check-namespace all
|
||||
namespace0.0: namespace_check: namespace0.0: check aborted, namespace online
|
||||
error checking namespaces: Device or resource busy
|
||||
checked 0 namespaces
|
||||
# ndctl disable-namespace namespace0.0
|
||||
disabled 1 namespace
|
||||
# ndctl check-namespace all
|
||||
namespace0.0: namespace_check: Unable to recover any BTT info blocks
|
||||
error checking namespaces: No such device or address
|
||||
checked 0 namespaces
|
||||
# ndctl destroy-namespace all
|
||||
destroyed 1 namespace
|
||||
# ndctl check-namespace all
|
||||
checked 0 namespaces
|
||||
# ndctl destroy-namespace all
|
||||
destroyed 0 namespaces
|
||||
# ndctl destroy-namespace all
|
||||
destroyed 0 namespaces
|
||||
|
||||
Note: this does change the return value from -ENXIO to 0 in the cases
|
||||
when no namespaces exist and processing all namespaces was requested.
|
||||
|
||||
Link: https://patchwork.kernel.org/patch/11681431/
|
||||
Link: https://lore.kernel.org/r/32c8cd8d2716f5e52aebea4e4d303eeb4e0550f9.1609938610.git.msuchanek@suse.de
|
||||
Reviewed-by: Santosh S <santosh@fossix.org>
|
||||
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/namespace.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
|
||||
index 5e65ed5..cd822b3 100644
|
||||
--- a/ndctl/namespace.c
|
||||
+++ b/ndctl/namespace.c
|
||||
@@ -2151,6 +2151,9 @@ static int do_xaction_namespace(const char *namespace,
|
||||
if (!namespace && action != ACTION_CREATE)
|
||||
return rc;
|
||||
|
||||
+ if (namespace && (strcmp(namespace, "all") == 0))
|
||||
+ rc = 0;
|
||||
+
|
||||
if (verbose)
|
||||
ndctl_set_log_priority(ctx, LOG_DEBUG);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,31 +1,29 @@
|
||||
namespace-action: Drop zero namespace checks.
|
||||
From 80e0d88c3098bd419e26146a8cb3b693fdd06417 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Wed, 6 Jan 2021 14:17:42 +0100
|
||||
Subject: [PATCH 030/217] namespace-action: Drop zero namespace checks.
|
||||
|
||||
BZ:
|
||||
Brew:
|
||||
With seed namespaces catched early on these checks for sizes in enable
|
||||
and destroy namespace code path are not needed.
|
||||
|
||||
commit 80e0d88c3098bd419e26146a8cb3b693fdd06417
|
||||
Author: Santosh Sivaraj <santosh@fossix.org>
|
||||
Date: Wed Jan 6 14:17:42 2021 +0100
|
||||
Reverts commit b9cb03f6d5a8 ("ndctl/namespace: Fix enable-namespace
|
||||
error for seed namespaces")
|
||||
|
||||
namespace-action: Drop zero namespace checks.
|
||||
|
||||
With seed namespaces catched early on these checks for sizes in enable
|
||||
and destroy namespace code path are not needed.
|
||||
|
||||
Reverts commit b9cb03f6d5a8 ("ndctl/namespace: Fix enable-namespace
|
||||
error for seed namespaces")
|
||||
|
||||
Reverts commit e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace
|
||||
accounting relative to seed devices")
|
||||
|
||||
Link: https://patchwork.kernel.org/patch/11739975/
|
||||
Link: https://lore.kernel.org/r/eb4bc7885708fa13e3d37286bc4a4219b1e4e5b6.1609938610.git.msuchanek@suse.de
|
||||
Fixes: b9cb03f6d5a8 ("ndctl/namespace: Fix enable-namespace error for seed namespaces")
|
||||
Fixes: e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace accounting relative to seed devices")
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
[rebased on top of the previous patches]
|
||||
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Reverts commit e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace
|
||||
accounting relative to seed devices")
|
||||
|
||||
Link: https://patchwork.kernel.org/patch/11739975/
|
||||
Link: https://lore.kernel.org/r/eb4bc7885708fa13e3d37286bc4a4219b1e4e5b6.1609938610.git.msuchanek@suse.de
|
||||
Fixes: b9cb03f6d5a8 ("ndctl/namespace: Fix enable-namespace error for seed namespaces")
|
||||
Fixes: e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace accounting relative to seed devices")
|
||||
Signed-off-by: Santosh Sivaraj <santosh@fossix.org>
|
||||
[rebased on top of the previous patches]
|
||||
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 5 -----
|
||||
ndctl/namespace.c | 10 ----------
|
||||
2 files changed, 15 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 536e142..87f60b9 100644
|
||||
@ -82,3 +80,6 @@ index cd822b3..c67c086 100644
|
||||
return rc;
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
187
SOURCES/0031-ndctl-add-.clang-format.patch
Normal file
187
SOURCES/0031-ndctl-add-.clang-format.patch
Normal file
@ -0,0 +1,187 @@
|
||||
From dc712e47c39f4dbc5f089831fd50dd1a2752c8fc Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:23 -0600
|
||||
Subject: [PATCH 031/217] ndctl: add .clang-format
|
||||
|
||||
Copy the Linux kernel's .clang-format and modify it for ndctl. Only the
|
||||
'ForEachMacros' section has been modified from the original kernel copy.
|
||||
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reported-by: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.clang-format | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 161 insertions(+)
|
||||
create mode 100644 .clang-format
|
||||
|
||||
diff --git a/.clang-format b/.clang-format
|
||||
new file mode 100644
|
||||
index 0000000..4e00fff
|
||||
--- /dev/null
|
||||
+++ b/.clang-format
|
||||
@@ -0,0 +1,161 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+#
|
||||
+# clang-format configuration file. Intended for clang-format >= 4.
|
||||
+# Copied from Linux's .clang-format
|
||||
+#
|
||||
+# For more information, see:
|
||||
+#
|
||||
+# https://clang.llvm.org/docs/ClangFormat.html
|
||||
+# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||
+#
|
||||
+---
|
||||
+AccessModifierOffset: -4
|
||||
+AlignAfterOpenBracket: Align
|
||||
+AlignConsecutiveAssignments: false
|
||||
+AlignConsecutiveDeclarations: false
|
||||
+#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
|
||||
+AlignOperands: true
|
||||
+AlignTrailingComments: false
|
||||
+AllowAllParametersOfDeclarationOnNextLine: false
|
||||
+AllowShortBlocksOnASingleLine: false
|
||||
+AllowShortCaseLabelsOnASingleLine: false
|
||||
+AllowShortFunctionsOnASingleLine: None
|
||||
+AllowShortIfStatementsOnASingleLine: false
|
||||
+AllowShortLoopsOnASingleLine: false
|
||||
+AlwaysBreakAfterDefinitionReturnType: None
|
||||
+AlwaysBreakAfterReturnType: None
|
||||
+AlwaysBreakBeforeMultilineStrings: false
|
||||
+AlwaysBreakTemplateDeclarations: false
|
||||
+BinPackArguments: true
|
||||
+BinPackParameters: true
|
||||
+BraceWrapping:
|
||||
+ AfterClass: false
|
||||
+ AfterControlStatement: false
|
||||
+ AfterEnum: false
|
||||
+ AfterFunction: true
|
||||
+ AfterNamespace: true
|
||||
+ AfterObjCDeclaration: false
|
||||
+ AfterStruct: false
|
||||
+ AfterUnion: false
|
||||
+ #AfterExternBlock: false # Unknown to clang-format-5.0
|
||||
+ BeforeCatch: false
|
||||
+ BeforeElse: false
|
||||
+ IndentBraces: false
|
||||
+ #SplitEmptyFunction: true # Unknown to clang-format-4.0
|
||||
+ #SplitEmptyRecord: true # Unknown to clang-format-4.0
|
||||
+ #SplitEmptyNamespace: true # Unknown to clang-format-4.0
|
||||
+BreakBeforeBinaryOperators: None
|
||||
+BreakBeforeBraces: Custom
|
||||
+#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
|
||||
+BreakBeforeTernaryOperators: false
|
||||
+BreakConstructorInitializersBeforeComma: false
|
||||
+#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
|
||||
+BreakAfterJavaFieldAnnotations: false
|
||||
+BreakStringLiterals: false
|
||||
+ColumnLimit: 80
|
||||
+CommentPragmas: '^ IWYU pragma:'
|
||||
+#CompactNamespaces: false # Unknown to clang-format-4.0
|
||||
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
+ConstructorInitializerIndentWidth: 8
|
||||
+ContinuationIndentWidth: 8
|
||||
+Cpp11BracedListStyle: false
|
||||
+DerivePointerAlignment: false
|
||||
+DisableFormat: false
|
||||
+ExperimentalAutoDetectBinPacking: false
|
||||
+#FixNamespaceComments: false # Unknown to clang-format-4.0
|
||||
+
|
||||
+# Taken from:
|
||||
+# while read -r sym; do
|
||||
+# printf " - '%s'\n" "$sym";
|
||||
+# done < \
|
||||
+# <(cscope -dL6 "foreach|for_each" \
|
||||
+# | awk '{ print $4 $5 }' | grep -E 'foreach|for_each' \
|
||||
+# | sed -e 's/#define//' \
|
||||
+# -e 's/*//' \
|
||||
+# -e 's/://' \
|
||||
+# -e 's/\(.*for_each.*\)(.*/\1/' \
|
||||
+# -e 's/\(.*foreach.*\)(.*/\1/' \
|
||||
+# | sort -u)
|
||||
+ForEachMacros:
|
||||
+ - 'daxctl_dev_foreach'
|
||||
+ - 'daxctl_mapping_foreach'
|
||||
+ - 'daxctl_region_foreach'
|
||||
+ - 'kmod_list_foreach'
|
||||
+ - 'kmod_list_foreach_reverse'
|
||||
+ - 'list_for_each'
|
||||
+ - 'list_for_each_off'
|
||||
+ - 'list_for_each_rev'
|
||||
+ - 'list_for_each_safe'
|
||||
+ - 'list_for_each_safe_off'
|
||||
+ - 'ndctl_btt_foreach'
|
||||
+ - 'ndctl_btt_foreach_safe'
|
||||
+ - 'ndctl_bus_foreach'
|
||||
+ - 'ndctl_dax_foreach'
|
||||
+ - 'ndctl_dax_foreach_safe'
|
||||
+ - 'ndctl_dimm_foreach'
|
||||
+ - 'ndctl_dimm_foreach_in_interleave_set'
|
||||
+ - 'ndctl_dimm_foreach_in_region'
|
||||
+ - 'ndctl_interleave_set_foreach'
|
||||
+ - 'ndctl_mapping_foreach'
|
||||
+ - 'ndctl_namespace_badblock_foreach'
|
||||
+ - 'ndctl_namespace_bb_foreach'
|
||||
+ - 'ndctl_namespace_foreach'
|
||||
+ - 'ndctl_namespace_foreach_safe'
|
||||
+ - 'ndctl_pfn_foreach'
|
||||
+ - 'ndctl_pfn_foreach_safe'
|
||||
+ - 'ndctl_region_badblock_foreach'
|
||||
+ - 'ndctl_region_foreach'
|
||||
+ - 'udev_list_entry_foreach'
|
||||
+
|
||||
+#IncludeBlocks: Preserve # Unknown to clang-format-5.0
|
||||
+IncludeCategories:
|
||||
+ - Regex: '.*'
|
||||
+ Priority: 1
|
||||
+IncludeIsMainRegex: '(Test)?$'
|
||||
+IndentCaseLabels: false
|
||||
+#IndentPPDirectives: None # Unknown to clang-format-5.0
|
||||
+IndentWidth: 8
|
||||
+IndentWrappedFunctionNames: false
|
||||
+JavaScriptQuotes: Leave
|
||||
+JavaScriptWrapImports: true
|
||||
+KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
+MacroBlockBegin: ''
|
||||
+MacroBlockEnd: ''
|
||||
+MaxEmptyLinesToKeep: 1
|
||||
+NamespaceIndentation: None
|
||||
+#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
|
||||
+ObjCBlockIndentWidth: 8
|
||||
+ObjCSpaceAfterProperty: true
|
||||
+ObjCSpaceBeforeProtocolList: true
|
||||
+
|
||||
+# Taken from git's rules
|
||||
+#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
|
||||
+PenaltyBreakBeforeFirstCallParameter: 30
|
||||
+PenaltyBreakComment: 10
|
||||
+PenaltyBreakFirstLessLess: 0
|
||||
+PenaltyBreakString: 10
|
||||
+PenaltyExcessCharacter: 100
|
||||
+PenaltyReturnTypeOnItsOwnLine: 60
|
||||
+
|
||||
+PointerAlignment: Right
|
||||
+ReflowComments: false
|
||||
+SortIncludes: false
|
||||
+#SortUsingDeclarations: false # Unknown to clang-format-4.0
|
||||
+SpaceAfterCStyleCast: false
|
||||
+SpaceAfterTemplateKeyword: true
|
||||
+SpaceBeforeAssignmentOperators: true
|
||||
+#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
|
||||
+#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
|
||||
+SpaceBeforeParens: ControlStatements
|
||||
+#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
|
||||
+SpaceInEmptyParentheses: false
|
||||
+SpacesBeforeTrailingComments: 1
|
||||
+SpacesInAngles: false
|
||||
+SpacesInContainerLiterals: false
|
||||
+SpacesInCStyleCastParentheses: false
|
||||
+SpacesInParentheses: false
|
||||
+SpacesInSquareBrackets: false
|
||||
+Standard: Cpp03
|
||||
+TabWidth: 8
|
||||
+UseTab: Always
|
||||
+...
|
||||
--
|
||||
2.27.0
|
||||
|
1277
SOURCES/0032-cxl-add-a-cxl-utility-and-libcxl-library.patch
Normal file
1277
SOURCES/0032-cxl-add-a-cxl-utility-and-libcxl-library.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,256 @@
|
||||
From 894fb9b2b59364f7f5683ea68c8bd765223a4ca8 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:25 -0600
|
||||
Subject: [PATCH 033/217] cxl: add a local copy of the cxl_mem UAPI header
|
||||
|
||||
While CXL functionality is under development, it is useful to have a
|
||||
local copy of the UAPI header for cxl_mem definitions. This allows
|
||||
building cxl and libcxl on systems where the appropriate kernel headers
|
||||
are not installed in the usual locations.
|
||||
|
||||
Cc: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Makefile.am | 3 +-
|
||||
Makefile.am.in | 1 +
|
||||
cxl/cxl_mem.h | 189 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/Makefile.am | 2 +-
|
||||
4 files changed, 193 insertions(+), 2 deletions(-)
|
||||
create mode 100644 cxl/cxl_mem.h
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 428fd40..4904ee7 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -89,4 +89,5 @@ libutil_a_SOURCES = \
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
daxctl/libdaxctl.h \
|
||||
- cxl/libcxl.h
|
||||
+ cxl/libcxl.h \
|
||||
+ cxl/cxl_mem.h
|
||||
diff --git a/Makefile.am.in b/Makefile.am.in
|
||||
index aaeee53..a748128 100644
|
||||
--- a/Makefile.am.in
|
||||
+++ b/Makefile.am.in
|
||||
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \
|
||||
-DNDCTL_MAN_PATH=\""$(mandir)"\" \
|
||||
-I${top_srcdir}/ndctl/lib \
|
||||
-I${top_srcdir}/ndctl \
|
||||
+ -I${top_srcdir}/cxl \
|
||||
-I${top_srcdir}/ \
|
||||
$(KMOD_CFLAGS) \
|
||||
$(UDEV_CFLAGS) \
|
||||
diff --git a/cxl/cxl_mem.h b/cxl/cxl_mem.h
|
||||
new file mode 100644
|
||||
index 0000000..d38cc9c
|
||||
--- /dev/null
|
||||
+++ b/cxl/cxl_mem.h
|
||||
@@ -0,0 +1,189 @@
|
||||
+/* SPDX-License-Identifier: LGPL-2.1 */
|
||||
+/* Copyright (C) 2020-2021, Intel Corporation. All rights reserved. */
|
||||
+/*
|
||||
+ * CXL IOCTLs for Memory Devices
|
||||
+ */
|
||||
+
|
||||
+#ifndef _UAPI_CXL_MEM_H_
|
||||
+#define _UAPI_CXL_MEM_H_
|
||||
+
|
||||
+#include <linux/types.h>
|
||||
+#include <sys/user.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#define __user
|
||||
+
|
||||
+/**
|
||||
+ * DOC: UAPI
|
||||
+ *
|
||||
+ * Not all of all commands that the driver supports are always available for use
|
||||
+ * by userspace. Userspace must check the results from the QUERY command in
|
||||
+ * order to determine the live set of commands.
|
||||
+ */
|
||||
+
|
||||
+#define CXL_MEM_QUERY_COMMANDS _IOR(0xCE, 1, struct cxl_mem_query_commands)
|
||||
+#define CXL_MEM_SEND_COMMAND _IOWR(0xCE, 2, struct cxl_send_command)
|
||||
+
|
||||
+#define CXL_CMDS \
|
||||
+ ___C(INVALID, "Invalid Command"), \
|
||||
+ ___C(IDENTIFY, "Identify Command"), \
|
||||
+ ___C(RAW, "Raw device command"), \
|
||||
+ ___C(GET_SUPPORTED_LOGS, "Get Supported Logs"), \
|
||||
+ ___C(GET_FW_INFO, "Get FW Info"), \
|
||||
+ ___C(GET_PARTITION_INFO, "Get Partition Information"), \
|
||||
+ ___C(GET_LSA, "Get Label Storage Area"), \
|
||||
+ ___C(GET_HEALTH_INFO, "Get Health Info"), \
|
||||
+ ___C(GET_LOG, "Get Log"), \
|
||||
+ ___C(SET_PARTITION_INFO, "Set Partition Information"), \
|
||||
+ ___C(SET_LSA, "Set Label Storage Area"), \
|
||||
+ ___C(GET_ALERT_CONFIG, "Get Alert Configuration"), \
|
||||
+ ___C(SET_ALERT_CONFIG, "Set Alert Configuration"), \
|
||||
+ ___C(GET_SHUTDOWN_STATE, "Get Shutdown State"), \
|
||||
+ ___C(SET_SHUTDOWN_STATE, "Set Shutdown State"), \
|
||||
+ ___C(GET_POISON, "Get Poison List"), \
|
||||
+ ___C(INJECT_POISON, "Inject Poison"), \
|
||||
+ ___C(CLEAR_POISON, "Clear Poison"), \
|
||||
+ ___C(GET_SCAN_MEDIA_CAPS, "Get Scan Media Capabilities"), \
|
||||
+ ___C(SCAN_MEDIA, "Scan Media"), \
|
||||
+ ___C(GET_SCAN_MEDIA, "Get Scan Media Results"), \
|
||||
+ ___C(MAX, "invalid / last command")
|
||||
+
|
||||
+#define ___C(a, b) CXL_MEM_COMMAND_ID_##a
|
||||
+enum { CXL_CMDS };
|
||||
+
|
||||
+#undef ___C
|
||||
+#define ___C(a, b) { b }
|
||||
+static const struct {
|
||||
+ const char *name;
|
||||
+} cxl_command_names[] = { CXL_CMDS };
|
||||
+
|
||||
+/*
|
||||
+ * Here's how this actually breaks out:
|
||||
+ * cxl_command_names[] = {
|
||||
+ * [CXL_MEM_COMMAND_ID_INVALID] = { "Invalid Command" },
|
||||
+ * [CXL_MEM_COMMAND_ID_IDENTIFY] = { "Identify Command" },
|
||||
+ * ...
|
||||
+ * [CXL_MEM_COMMAND_ID_MAX] = { "invalid / last command" },
|
||||
+ * };
|
||||
+ */
|
||||
+
|
||||
+#undef ___C
|
||||
+
|
||||
+/**
|
||||
+ * struct cxl_command_info - Command information returned from a query.
|
||||
+ * @id: ID number for the command.
|
||||
+ * @flags: Flags that specify command behavior.
|
||||
+ * @size_in: Expected input size, or -1 if variable length.
|
||||
+ * @size_out: Expected output size, or -1 if variable length.
|
||||
+ *
|
||||
+ * Represents a single command that is supported by both the driver and the
|
||||
+ * hardware. This is returned as part of an array from the query ioctl. The
|
||||
+ * following would be a command that takes a variable length input and returns 0
|
||||
+ * bytes of output.
|
||||
+ *
|
||||
+ * - @id = 10
|
||||
+ * - @flags = 0
|
||||
+ * - @size_in = -1
|
||||
+ * - @size_out = 0
|
||||
+ *
|
||||
+ * See struct cxl_mem_query_commands.
|
||||
+ */
|
||||
+struct cxl_command_info {
|
||||
+ __u32 id;
|
||||
+
|
||||
+ __u32 flags;
|
||||
+#define CXL_MEM_COMMAND_FLAG_MASK GENMASK(0, 0)
|
||||
+
|
||||
+ __s32 size_in;
|
||||
+ __s32 size_out;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct cxl_mem_query_commands - Query supported commands.
|
||||
+ * @n_commands: In/out parameter. When @n_commands is > 0, the driver will
|
||||
+ * return min(num_support_commands, n_commands). When @n_commands
|
||||
+ * is 0, driver will return the number of total supported commands.
|
||||
+ * @rsvd: Reserved for future use.
|
||||
+ * @commands: Output array of supported commands. This array must be allocated
|
||||
+ * by userspace to be at least min(num_support_commands, @n_commands)
|
||||
+ *
|
||||
+ * Allow userspace to query the available commands supported by both the driver,
|
||||
+ * and the hardware. Commands that aren't supported by either the driver, or the
|
||||
+ * hardware are not returned in the query.
|
||||
+ *
|
||||
+ * Examples:
|
||||
+ *
|
||||
+ * - { .n_commands = 0 } // Get number of supported commands
|
||||
+ * - { .n_commands = 15, .commands = buf } // Return first 15 (or less)
|
||||
+ * supported commands
|
||||
+ *
|
||||
+ * See struct cxl_command_info.
|
||||
+ */
|
||||
+struct cxl_mem_query_commands {
|
||||
+ /*
|
||||
+ * Input: Number of commands to return (space allocated by user)
|
||||
+ * Output: Number of commands supported by the driver/hardware
|
||||
+ *
|
||||
+ * If n_commands is 0, kernel will only return number of commands and
|
||||
+ * not try to populate commands[], thus allowing userspace to know how
|
||||
+ * much space to allocate
|
||||
+ */
|
||||
+ __u32 n_commands;
|
||||
+ __u32 rsvd;
|
||||
+
|
||||
+ struct cxl_command_info __user commands[]; /* out: supported commands */
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct cxl_send_command - Send a command to a memory device.
|
||||
+ * @id: The command to send to the memory device. This must be one of the
|
||||
+ * commands returned by the query command.
|
||||
+ * @flags: Flags for the command (input).
|
||||
+ * @raw: Special fields for raw commands
|
||||
+ * @raw.opcode: Opcode passed to hardware when using the RAW command.
|
||||
+ * @raw.rsvd: Must be zero.
|
||||
+ * @rsvd: Must be zero.
|
||||
+ * @retval: Return value from the memory device (output).
|
||||
+ * @in: Parameters associated with input payload.
|
||||
+ * @in.size: Size of the payload to provide to the device (input).
|
||||
+ * @in.rsvd: Must be zero.
|
||||
+ * @in.payload: Pointer to memory for payload input, payload is little endian.
|
||||
+ * @out: Parameters associated with output payload.
|
||||
+ * @out.size: Size of the payload received from the device (input/output). This
|
||||
+ * field is filled in by userspace to let the driver know how much
|
||||
+ * space was allocated for output. It is populated by the driver to
|
||||
+ * let userspace know how large the output payload actually was.
|
||||
+ * @out.rsvd: Must be zero.
|
||||
+ * @out.payload: Pointer to memory for payload output, payload is little endian.
|
||||
+ *
|
||||
+ * Mechanism for userspace to send a command to the hardware for processing. The
|
||||
+ * driver will do basic validation on the command sizes. In some cases even the
|
||||
+ * payload may be introspected. Userspace is required to allocate large enough
|
||||
+ * buffers for size_out which can be variable length in certain situations.
|
||||
+ */
|
||||
+struct cxl_send_command {
|
||||
+ __u32 id;
|
||||
+ __u32 flags;
|
||||
+ union {
|
||||
+ struct {
|
||||
+ __u16 opcode;
|
||||
+ __u16 rsvd;
|
||||
+ } raw;
|
||||
+ __u32 rsvd;
|
||||
+ };
|
||||
+ __u32 retval;
|
||||
+
|
||||
+ struct {
|
||||
+ __s32 size;
|
||||
+ __u32 rsvd;
|
||||
+ __u64 payload;
|
||||
+ } in;
|
||||
+
|
||||
+ struct {
|
||||
+ __s32 size;
|
||||
+ __u32 rsvd;
|
||||
+ __u64 payload;
|
||||
+ } out;
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
diff --git a/cxl/lib/Makefile.am b/cxl/lib/Makefile.am
|
||||
index 277f0cd..72c9ccd 100644
|
||||
--- a/cxl/lib/Makefile.am
|
||||
+++ b/cxl/lib/Makefile.am
|
||||
@@ -3,7 +3,7 @@ include $(top_srcdir)/Makefile.am.in
|
||||
%.pc: %.pc.in Makefile
|
||||
$(SED_PROCESS)
|
||||
|
||||
-pkginclude_HEADERS = ../libcxl.h
|
||||
+pkginclude_HEADERS = ../libcxl.h ../cxl_mem.h
|
||||
lib_LTLIBRARIES = libcxl.la
|
||||
|
||||
libcxl_la_SOURCES =\
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,114 @@
|
||||
From 7aa7c7be6e803de267a165237e23577ab496e792 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:26 -0600
|
||||
Subject: [PATCH 034/217] util: add the struct_size() helper from the kernel
|
||||
|
||||
Add struct_size() from include/linux/overflow.h which calculates the
|
||||
size of a struct with a trailing variable length array.
|
||||
|
||||
Suggested-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
util/size.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
util/util.h | 6 ++++++
|
||||
2 files changed, 68 insertions(+)
|
||||
|
||||
diff --git a/util/size.h b/util/size.h
|
||||
index 646edae..a0f3593 100644
|
||||
--- a/util/size.h
|
||||
+++ b/util/size.h
|
||||
@@ -4,6 +4,8 @@
|
||||
#ifndef _NDCTL_SIZE_H_
|
||||
#define _NDCTL_SIZE_H_
|
||||
#include <stdbool.h>
|
||||
+#include <stdint.h>
|
||||
+#include <util/util.h>
|
||||
|
||||
#define SZ_1K 0x00000400
|
||||
#define SZ_4K 0x00001000
|
||||
@@ -30,4 +32,64 @@ static inline bool is_power_of_2(unsigned long long v)
|
||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
||||
#define HPAGE_SIZE (2 << 20)
|
||||
|
||||
+/*
|
||||
+ * Helpers for struct_size() copied from include/linux/overflow.h (GPL-2.0)
|
||||
+ *
|
||||
+ * For simplicity and code hygiene, the fallback code below insists on
|
||||
+ * a, b and *d having the same type (similar to the min() and max()
|
||||
+ * macros), whereas gcc's type-generic overflow checkers accept
|
||||
+ * different types. Hence we don't just make check_add_overflow an
|
||||
+ * alias for __builtin_add_overflow, but add type checks similar to
|
||||
+ * below.
|
||||
+ */
|
||||
+#define check_add_overflow(a, b, d) (({ \
|
||||
+ typeof(a) __a = (a); \
|
||||
+ typeof(b) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ __builtin_add_overflow(__a, __b, __d); \
|
||||
+}))
|
||||
+
|
||||
+#define check_mul_overflow(a, b, d) (({ \
|
||||
+ typeof(a) __a = (a); \
|
||||
+ typeof(b) __b = (b); \
|
||||
+ typeof(d) __d = (d); \
|
||||
+ (void) (&__a == &__b); \
|
||||
+ (void) (&__a == __d); \
|
||||
+ __builtin_mul_overflow(__a, __b, __d); \
|
||||
+}))
|
||||
+
|
||||
+/*
|
||||
+ * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for
|
||||
+ * struct_size() below.
|
||||
+ */
|
||||
+static inline size_t __ab_c_size(size_t a, size_t b, size_t c)
|
||||
+{
|
||||
+ size_t bytes;
|
||||
+
|
||||
+ if (check_mul_overflow(a, b, &bytes))
|
||||
+ return SIZE_MAX;
|
||||
+ if (check_add_overflow(bytes, c, &bytes))
|
||||
+ return SIZE_MAX;
|
||||
+
|
||||
+ return bytes;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * struct_size() - Calculate size of structure with trailing array.
|
||||
+ * @p: Pointer to the structure.
|
||||
+ * @member: Name of the array member.
|
||||
+ * @count: Number of elements in the array.
|
||||
+ *
|
||||
+ * Calculates size of memory needed for structure @p followed by an
|
||||
+ * array of @count number of @member elements.
|
||||
+ *
|
||||
+ * Return: number of bytes needed or SIZE_MAX on overflow.
|
||||
+ */
|
||||
+#define struct_size(p, member, count) \
|
||||
+ __ab_c_size(count, \
|
||||
+ sizeof(*(p)->member) + __must_be_array((p)->member),\
|
||||
+ sizeof(*(p)))
|
||||
+
|
||||
#endif /* _NDCTL_SIZE_H_ */
|
||||
diff --git a/util/util.h b/util/util.h
|
||||
index ae0e4e1..b2b4ae6 100644
|
||||
--- a/util/util.h
|
||||
+++ b/util/util.h
|
||||
@@ -63,6 +63,12 @@
|
||||
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
|
||||
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
|
||||
|
||||
+/* Are two types/vars the same type (ignoring qualifiers)? */
|
||||
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
|
||||
+
|
||||
+/* &a[0] degrades to a pointer: a different type from an array */
|
||||
+#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
|
||||
+
|
||||
enum {
|
||||
READ, WRITE,
|
||||
};
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,535 @@
|
||||
From 96afebd1b32ff839129f3bc0ba323ab5f04674ea Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:27 -0600
|
||||
Subject: [PATCH 035/217] libcxl: add support for command query and submission
|
||||
|
||||
Add a set of APIs around 'cxl_cmd' for querying the kernel for supported
|
||||
commands, allocating and validating command structures against the
|
||||
supported set, and submitting the commands.
|
||||
|
||||
'Query Commands' and 'Send Command' are implemented as IOCTLs in the
|
||||
kernel. 'Query Commands' returns information about each supported
|
||||
command, such as flags governing its use, or input and output payload
|
||||
sizes. This information is used to validate command support, as well as
|
||||
set up input and output buffers for command submission.
|
||||
|
||||
Cc: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 390 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 9 ++
|
||||
cxl/lib/private.h | 33 ++++
|
||||
cxl/libcxl.h | 11 ++
|
||||
4 files changed, 443 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index c15e987..727d599 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -9,14 +9,17 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
+#include <sys/ioctl.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
|
||||
#include <util/log.h>
|
||||
+#include <util/size.h>
|
||||
#include <util/sysfs.h>
|
||||
#include <util/bitmap.h>
|
||||
+#include <cxl/cxl_mem.h>
|
||||
#include <cxl/libcxl.h>
|
||||
#include "private.h"
|
||||
|
||||
@@ -343,3 +346,390 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev
|
||||
{
|
||||
return memdev->firmware_version;
|
||||
}
|
||||
+
|
||||
+CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ if (!cmd)
|
||||
+ return;
|
||||
+ if (--cmd->refcount == 0) {
|
||||
+ free(cmd->query_cmd);
|
||||
+ free(cmd->send_cmd);
|
||||
+ free(cmd->input_payload);
|
||||
+ free(cmd->output_payload);
|
||||
+ free(cmd);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT void cxl_cmd_ref(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd->refcount++;
|
||||
+}
|
||||
+
|
||||
+static int cxl_cmd_alloc_query(struct cxl_cmd *cmd, int num_cmds)
|
||||
+{
|
||||
+ size_t size;
|
||||
+
|
||||
+ if (!cmd)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (cmd->query_cmd != NULL)
|
||||
+ free(cmd->query_cmd);
|
||||
+
|
||||
+ size = struct_size(cmd->query_cmd, commands, num_cmds);
|
||||
+ if (size == SIZE_MAX)
|
||||
+ return -EOVERFLOW;
|
||||
+
|
||||
+ cmd->query_cmd = calloc(1, size);
|
||||
+ if (!cmd->query_cmd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cmd->query_cmd->n_commands = num_cmds;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct cxl_cmd *cxl_cmd_new(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_cmd *cmd;
|
||||
+ size_t size;
|
||||
+
|
||||
+ size = sizeof(*cmd);
|
||||
+ cmd = calloc(1, size);
|
||||
+ if (!cmd)
|
||||
+ return NULL;
|
||||
+
|
||||
+ cxl_cmd_ref(cmd);
|
||||
+ cmd->memdev = memdev;
|
||||
+
|
||||
+ return cmd;
|
||||
+}
|
||||
+
|
||||
+static int __do_cmd(struct cxl_cmd *cmd, int ioctl_cmd, int fd)
|
||||
+{
|
||||
+ void *cmd_buf;
|
||||
+ int rc;
|
||||
+
|
||||
+ switch (ioctl_cmd) {
|
||||
+ case CXL_MEM_QUERY_COMMANDS:
|
||||
+ cmd_buf = cmd->query_cmd;
|
||||
+ break;
|
||||
+ case CXL_MEM_SEND_COMMAND:
|
||||
+ cmd_buf = cmd->send_cmd;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ rc = ioctl(fd, ioctl_cmd, cmd_buf);
|
||||
+ if (rc < 0)
|
||||
+ rc = -errno;
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int do_cmd(struct cxl_cmd *cmd, int ioctl_cmd)
|
||||
+{
|
||||
+ char *path;
|
||||
+ struct stat st;
|
||||
+ unsigned int major, minor;
|
||||
+ int rc = 0, fd;
|
||||
+ struct cxl_memdev *memdev = cmd->memdev;
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+
|
||||
+ major = cxl_memdev_get_major(memdev);
|
||||
+ minor = cxl_memdev_get_minor(memdev);
|
||||
+
|
||||
+ if (asprintf(&path, "/dev/cxl/%s", devname) < 0)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ fd = open(path, O_RDWR);
|
||||
+ if (fd < 0) {
|
||||
+ err(ctx, "failed to open %s: %s\n", path, strerror(errno));
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (fstat(fd, &st) >= 0 && S_ISCHR(st.st_mode)
|
||||
+ && major(st.st_rdev) == major
|
||||
+ && minor(st.st_rdev) == minor) {
|
||||
+ rc = __do_cmd(cmd, ioctl_cmd, fd);
|
||||
+ } else {
|
||||
+ err(ctx, "failed to validate %s as a CXL memdev node\n", path);
|
||||
+ rc = -ENXIO;
|
||||
+ }
|
||||
+ close(fd);
|
||||
+out:
|
||||
+ free(path);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int alloc_do_query(struct cxl_cmd *cmd, int num_cmds)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(cmd->memdev);
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = cxl_cmd_alloc_query(cmd, num_cmds);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+
|
||||
+ rc = do_cmd(cmd, CXL_MEM_QUERY_COMMANDS);
|
||||
+ if (rc < 0)
|
||||
+ err(ctx, "%s: query commands failed: %s\n",
|
||||
+ cxl_memdev_get_devname(cmd->memdev),
|
||||
+ strerror(-rc));
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int cxl_cmd_do_query(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ struct cxl_memdev *memdev = cmd->memdev;
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ int rc, n_commands;
|
||||
+
|
||||
+ switch (cmd->query_status) {
|
||||
+ case CXL_CMD_QUERY_OK:
|
||||
+ return 0;
|
||||
+ case CXL_CMD_QUERY_UNSUPPORTED:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ case CXL_CMD_QUERY_NOT_RUN:
|
||||
+ break;
|
||||
+ default:
|
||||
+ err(ctx, "%s: Unknown query_status %d\n",
|
||||
+ devname, cmd->query_status);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ rc = alloc_do_query(cmd, 0);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+
|
||||
+ n_commands = cmd->query_cmd->n_commands;
|
||||
+ dbg(ctx, "%s: supports %d commands\n", devname, n_commands);
|
||||
+
|
||||
+ return alloc_do_query(cmd, n_commands);
|
||||
+}
|
||||
+
|
||||
+static int cxl_cmd_validate(struct cxl_cmd *cmd, u32 cmd_id)
|
||||
+{
|
||||
+ struct cxl_memdev *memdev = cmd->memdev;
|
||||
+ struct cxl_mem_query_commands *query = cmd->query_cmd;
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ u32 i;
|
||||
+
|
||||
+ for (i = 0; i < query->n_commands; i++) {
|
||||
+ struct cxl_command_info *cinfo = &query->commands[i];
|
||||
+ const char *cmd_name = cxl_command_names[cinfo->id].name;
|
||||
+
|
||||
+ if (cinfo->id != cmd_id)
|
||||
+ continue;
|
||||
+
|
||||
+ dbg(ctx, "%s: %s: in: %d, out %d, flags: %#08x\n",
|
||||
+ devname, cmd_name, cinfo->size_in,
|
||||
+ cinfo->size_out, cinfo->flags);
|
||||
+
|
||||
+ cmd->query_idx = i;
|
||||
+ cmd->query_status = CXL_CMD_QUERY_OK;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ cmd->query_status = CXL_CMD_QUERY_UNSUPPORTED;
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_set_input_payload(struct cxl_cmd *cmd, void *buf,
|
||||
+ int size)
|
||||
+{
|
||||
+ struct cxl_memdev *memdev = cmd->memdev;
|
||||
+
|
||||
+ if (size > memdev->payload_max || size < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!buf) {
|
||||
+
|
||||
+ /* If the user didn't supply a buffer, allocate it */
|
||||
+ cmd->input_payload = calloc(1, size);
|
||||
+ if (!cmd->input_payload)
|
||||
+ return -ENOMEM;
|
||||
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * Use user-buffer as is. If an automatic allocation was
|
||||
+ * previously made (based on a fixed size from query),
|
||||
+ * it will get freed during unref.
|
||||
+ */
|
||||
+ cmd->send_cmd->in.payload = (u64)buf;
|
||||
+ }
|
||||
+ cmd->send_cmd->in.size = size;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_set_output_payload(struct cxl_cmd *cmd, void *buf,
|
||||
+ int size)
|
||||
+{
|
||||
+ struct cxl_memdev *memdev = cmd->memdev;
|
||||
+
|
||||
+ if (size > memdev->payload_max || size < 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!buf) {
|
||||
+
|
||||
+ /* If the user didn't supply a buffer, allocate it */
|
||||
+ cmd->output_payload = calloc(1, size);
|
||||
+ if (!cmd->output_payload)
|
||||
+ return -ENOMEM;
|
||||
+ cmd->send_cmd->out.payload = (u64)cmd->output_payload;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * Use user-buffer as is. If an automatic allocation was
|
||||
+ * previously made (based on a fixed size from query),
|
||||
+ * it will get freed during unref.
|
||||
+ */
|
||||
+ cmd->send_cmd->out.payload = (u64)buf;
|
||||
+ }
|
||||
+ cmd->send_cmd->out.size = size;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cxl_cmd_alloc_send(struct cxl_cmd *cmd, u32 cmd_id)
|
||||
+{
|
||||
+ struct cxl_mem_query_commands *query = cmd->query_cmd;
|
||||
+ struct cxl_command_info *cinfo = &query->commands[cmd->query_idx];
|
||||
+ size_t size;
|
||||
+
|
||||
+ if (!query)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ size = sizeof(struct cxl_send_command);
|
||||
+ cmd->send_cmd = calloc(1, size);
|
||||
+ if (!cmd->send_cmd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ if (cinfo->id != cmd_id)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cmd->send_cmd->id = cmd_id;
|
||||
+
|
||||
+ if (cinfo->size_in > 0) {
|
||||
+ cmd->input_payload = calloc(1, cinfo->size_in);
|
||||
+ if (!cmd->input_payload)
|
||||
+ return -ENOMEM;
|
||||
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
|
||||
+ cmd->send_cmd->in.size = cinfo->size_in;
|
||||
+ }
|
||||
+ if (cinfo->size_out > 0) {
|
||||
+ cmd->output_payload = calloc(1, cinfo->size_out);
|
||||
+ if (!cmd->output_payload)
|
||||
+ return -ENOMEM;
|
||||
+ cmd->send_cmd->out.payload = (u64)cmd->output_payload;
|
||||
+ cmd->send_cmd->out.size = cinfo->size_out;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct cxl_cmd *cxl_cmd_new_generic(struct cxl_memdev *memdev,
|
||||
+ u32 cmd_id)
|
||||
+{
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ struct cxl_cmd *cmd;
|
||||
+ int rc;
|
||||
+
|
||||
+ cmd = cxl_cmd_new(memdev);
|
||||
+ if (!cmd)
|
||||
+ return NULL;
|
||||
+
|
||||
+ rc = cxl_cmd_do_query(cmd);
|
||||
+ if (rc) {
|
||||
+ err(ctx, "%s: query returned: %s\n", devname, strerror(-rc));
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ rc = cxl_cmd_validate(cmd, cmd_id);
|
||||
+ if (rc) {
|
||||
+ errno = -rc;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ rc = cxl_cmd_alloc_send(cmd, cmd_id);
|
||||
+ if (rc) {
|
||||
+ errno = -rc;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ cmd->status = 1;
|
||||
+ return cmd;
|
||||
+
|
||||
+fail:
|
||||
+ cxl_cmd_unref(cmd);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT const char *cxl_cmd_get_devname(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ return cxl_memdev_get_devname(cmd->memdev);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev,
|
||||
+ int opcode)
|
||||
+{
|
||||
+ struct cxl_cmd *cmd;
|
||||
+
|
||||
+ /* opcode '0' is reserved */
|
||||
+ if (opcode <= 0) {
|
||||
+ errno = EINVAL;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_RAW);
|
||||
+ if (!cmd)
|
||||
+ return NULL;
|
||||
+
|
||||
+ cmd->send_cmd->raw.opcode = opcode;
|
||||
+ return cmd;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ struct cxl_memdev *memdev = cmd->memdev;
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ int rc;
|
||||
+
|
||||
+ switch (cmd->query_status) {
|
||||
+ case CXL_CMD_QUERY_OK:
|
||||
+ break;
|
||||
+ case CXL_CMD_QUERY_UNSUPPORTED:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ case CXL_CMD_QUERY_NOT_RUN:
|
||||
+ return -EINVAL;
|
||||
+ default:
|
||||
+ err(ctx, "%s: Unknown query_status %d\n",
|
||||
+ devname, cmd->query_status);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ dbg(ctx, "%s: submitting SEND cmd: in: %d, out: %d\n", devname,
|
||||
+ cmd->send_cmd->in.size, cmd->send_cmd->out.size);
|
||||
+ rc = do_cmd(cmd, CXL_MEM_SEND_COMMAND);
|
||||
+ cmd->status = cmd->send_cmd->retval;
|
||||
+ dbg(ctx, "%s: got SEND cmd: in: %d, out: %d, retval: %d, status: %d\n",
|
||||
+ devname, cmd->send_cmd->in.size, cmd->send_cmd->out.size,
|
||||
+ rc, cmd->status);
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ return cmd->status;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_get_out_size(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ return cmd->send_cmd->out.size;
|
||||
+}
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 2616e5c..3900f90 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -20,6 +20,15 @@ global:
|
||||
cxl_memdev_get_pmem_size;
|
||||
cxl_memdev_get_ram_size;
|
||||
cxl_memdev_get_firmware_verison;
|
||||
+ cxl_cmd_get_devname;
|
||||
+ cxl_cmd_new_raw;
|
||||
+ cxl_cmd_set_input_payload;
|
||||
+ cxl_cmd_set_output_payload;
|
||||
+ cxl_cmd_ref;
|
||||
+ cxl_cmd_unref;
|
||||
+ cxl_cmd_submit;
|
||||
+ cxl_cmd_get_mbox_status;
|
||||
+ cxl_cmd_get_out_size;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index fc88fa1..87ca17e 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -4,6 +4,9 @@
|
||||
#define _LIBCXL_PRIVATE_H_
|
||||
|
||||
#include <libkmod.h>
|
||||
+#include <cxl/cxl_mem.h>
|
||||
+#include <ccan/endian/endian.h>
|
||||
+#include <ccan/short_types/short_types.h>
|
||||
|
||||
#define CXL_EXPORT __attribute__ ((visibility("default")))
|
||||
|
||||
@@ -21,6 +24,36 @@ struct cxl_memdev {
|
||||
struct kmod_module *module;
|
||||
};
|
||||
|
||||
+enum cxl_cmd_query_status {
|
||||
+ CXL_CMD_QUERY_NOT_RUN = 0,
|
||||
+ CXL_CMD_QUERY_OK,
|
||||
+ CXL_CMD_QUERY_UNSUPPORTED,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct cxl_cmd - CXL memdev command
|
||||
+ * @memdev: the memory device to which the command is being sent
|
||||
+ * @query_cmd: structure for the Linux 'Query commands' ioctl
|
||||
+ * @send_cmd: structure for the Linux 'Send command' ioctl
|
||||
+ * @input_payload: buffer for input payload managed by libcxl
|
||||
+ * @output_payload: buffer for output payload managed by libcxl
|
||||
+ * @refcount: reference for passing command buffer around
|
||||
+ * @query_status: status from query_commands
|
||||
+ * @query_idx: index of 'this' command in the query_commands array
|
||||
+ * @status: command return status from the device
|
||||
+ */
|
||||
+struct cxl_cmd {
|
||||
+ struct cxl_memdev *memdev;
|
||||
+ struct cxl_mem_query_commands *query_cmd;
|
||||
+ struct cxl_send_command *send_cmd;
|
||||
+ void *input_payload;
|
||||
+ void *output_payload;
|
||||
+ int refcount;
|
||||
+ int query_status;
|
||||
+ int query_idx;
|
||||
+ int status;
|
||||
+};
|
||||
+
|
||||
static inline int check_kmod(struct kmod_ctx *kmod_ctx)
|
||||
{
|
||||
return kmod_ctx ? 0 : -ENXIO;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index fd06790..6e87b80 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -48,6 +48,17 @@ const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
memdev != NULL; \
|
||||
memdev = cxl_memdev_get_next(memdev))
|
||||
|
||||
+struct cxl_cmd;
|
||||
+const char *cxl_cmd_get_devname(struct cxl_cmd *cmd);
|
||||
+struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
+int cxl_cmd_set_input_payload(struct cxl_cmd *cmd, void *in, int size);
|
||||
+int cxl_cmd_set_output_payload(struct cxl_cmd *cmd, void *out, int size);
|
||||
+void cxl_cmd_ref(struct cxl_cmd *cmd);
|
||||
+void cxl_cmd_unref(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_submit(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_get_out_size(struct cxl_cmd *cmd);
|
||||
+
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,157 @@
|
||||
From 244862cbbfecda9b6b638eccaca526f4daba2795 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:28 -0600
|
||||
Subject: [PATCH 036/217] libcxl: add support for the 'Identify Device' command
|
||||
|
||||
Add APIs to allocate and send an 'Identify Device' command, and
|
||||
accessors to retrieve some of the fields from the resulting data.
|
||||
|
||||
Only add a handful accessor functions; more can be added as the need
|
||||
arises. The fields added are fw_revision, partition_align, and
|
||||
lsa_size.
|
||||
|
||||
Cc: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 4 ++++
|
||||
cxl/lib/private.h | 19 +++++++++++++++++
|
||||
cxl/libcxl.h | 4 ++++
|
||||
4 files changed, 79 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 727d599..ed21670 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -13,7 +13,10 @@
|
||||
#include <sys/sysmacros.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <ccan/list/list.h>
|
||||
+#include <ccan/endian/endian.h>
|
||||
+#include <ccan/minmax/minmax.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
+#include <ccan/short_types/short_types.h>
|
||||
|
||||
#include <util/log.h>
|
||||
#include <util/size.h>
|
||||
@@ -674,6 +677,55 @@ CXL_EXPORT const char *cxl_cmd_get_devname(struct cxl_cmd *cmd)
|
||||
return cxl_memdev_get_devname(cmd->memdev);
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_IDENTIFY);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev,
|
||||
+ int fw_len)
|
||||
+{
|
||||
+ struct cxl_cmd_identify *id =
|
||||
+ (struct cxl_cmd_identify *)cmd->send_cmd->out.payload;
|
||||
+
|
||||
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY)
|
||||
+ return -EINVAL;
|
||||
+ if (cmd->status < 0)
|
||||
+ return cmd->status;
|
||||
+
|
||||
+ if (fw_len > 0)
|
||||
+ memcpy(fw_rev, id->fw_revision,
|
||||
+ min(fw_len, CXL_CMD_IDENTIFY_FW_REV_LENGTH));
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT unsigned long long cxl_cmd_identify_get_partition_align(
|
||||
+ struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ struct cxl_cmd_identify *id =
|
||||
+ (struct cxl_cmd_identify *)cmd->send_cmd->out.payload;
|
||||
+
|
||||
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY)
|
||||
+ return -EINVAL;
|
||||
+ if (cmd->status < 0)
|
||||
+ return cmd->status;
|
||||
+
|
||||
+ return le64_to_cpu(id->partition_align);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ struct cxl_cmd_identify *id =
|
||||
+ (struct cxl_cmd_identify *)cmd->send_cmd->out.payload;
|
||||
+
|
||||
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_IDENTIFY)
|
||||
+ return -EINVAL;
|
||||
+ if (cmd->status < 0)
|
||||
+ return cmd->status;
|
||||
+
|
||||
+ return le32_to_cpu(id->lsa_size);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev,
|
||||
int opcode)
|
||||
{
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 3900f90..1dc45f4 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -29,6 +29,10 @@ global:
|
||||
cxl_cmd_submit;
|
||||
cxl_cmd_get_mbox_status;
|
||||
cxl_cmd_get_out_size;
|
||||
+ cxl_cmd_new_identify;
|
||||
+ cxl_cmd_identify_get_fw_rev;
|
||||
+ cxl_cmd_identify_get_partition_align;
|
||||
+ cxl_cmd_identify_get_label_size;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 87ca17e..3273f21 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -54,6 +54,25 @@ struct cxl_cmd {
|
||||
int status;
|
||||
};
|
||||
|
||||
+#define CXL_CMD_IDENTIFY_FW_REV_LENGTH 0x10
|
||||
+
|
||||
+struct cxl_cmd_identify {
|
||||
+ char fw_revision[CXL_CMD_IDENTIFY_FW_REV_LENGTH];
|
||||
+ le64 total_capacity;
|
||||
+ le64 volatile_capacity;
|
||||
+ le64 persistent_capacity;
|
||||
+ le64 partition_align;
|
||||
+ le16 info_event_log_size;
|
||||
+ le16 warning_event_log_size;
|
||||
+ le16 failure_event_log_size;
|
||||
+ le16 fatal_event_log_size;
|
||||
+ le32 lsa_size;
|
||||
+ u8 poison_list_max_mer[3];
|
||||
+ le16 inject_poison_limit;
|
||||
+ u8 poison_caps;
|
||||
+ u8 qos_telemetry_caps;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
static inline int check_kmod(struct kmod_ctx *kmod_ctx)
|
||||
{
|
||||
return kmod_ctx ? 0 : -ENXIO;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 6e87b80..0f2d5e9 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -58,6 +58,10 @@ void cxl_cmd_unref(struct cxl_cmd *cmd);
|
||||
int cxl_cmd_submit(struct cxl_cmd *cmd);
|
||||
int cxl_cmd_get_mbox_status(struct cxl_cmd *cmd);
|
||||
int cxl_cmd_get_out_size(struct cxl_cmd *cmd);
|
||||
+struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev);
|
||||
+int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, int fw_len);
|
||||
+unsigned long long cxl_cmd_identify_get_partition_align(struct cxl_cmd *cmd);
|
||||
+unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,575 @@
|
||||
From 55ada0eab92d52826c9be0186db664ba9eeba749 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:29 -0600
|
||||
Subject: [PATCH 037/217] libcxl: add GET_HEALTH_INFO mailbox command and
|
||||
accessors
|
||||
|
||||
Add libcxl APIs to create a new GET_HEALTH_INFO mailbox command, the
|
||||
command output data structure (privately), and accessor APIs to return
|
||||
the different fields in the health info output.
|
||||
|
||||
Cc: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 291 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 29 +++++
|
||||
cxl/lib/private.h | 47 ++++++++
|
||||
cxl/libcxl.h | 33 +++++
|
||||
util/bitmap.h | 85 +++++++++++++
|
||||
5 files changed, 485 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index ed21670..065824d 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -677,6 +677,297 @@ CXL_EXPORT const char *cxl_cmd_get_devname(struct cxl_cmd *cmd)
|
||||
return cxl_memdev_get_devname(cmd->memdev);
|
||||
}
|
||||
|
||||
+static int cxl_cmd_validate_status(struct cxl_cmd *cmd, u32 id)
|
||||
+{
|
||||
+ if (cmd->send_cmd->id != id)
|
||||
+ return -EINVAL;
|
||||
+ if (cmd->status < 0)
|
||||
+ return cmd->status;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Helpers for health_info fields (no endian conversion) */
|
||||
+#define cmd_get_field_u8(cmd, n, N, field) \
|
||||
+do { \
|
||||
+ struct cxl_cmd_##n *c = \
|
||||
+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \
|
||||
+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \
|
||||
+ if (rc) \
|
||||
+ return rc; \
|
||||
+ return c->field; \
|
||||
+} while(0)
|
||||
+
|
||||
+#define cmd_get_field_u16(cmd, n, N, field) \
|
||||
+do { \
|
||||
+ struct cxl_cmd_##n *c = \
|
||||
+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \
|
||||
+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \
|
||||
+ if (rc) \
|
||||
+ return rc; \
|
||||
+ return le16_to_cpu(c->field); \
|
||||
+} while(0)
|
||||
+
|
||||
+
|
||||
+#define cmd_get_field_u32(cmd, n, N, field) \
|
||||
+do { \
|
||||
+ struct cxl_cmd_##n *c = \
|
||||
+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \
|
||||
+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \
|
||||
+ if (rc) \
|
||||
+ return rc; \
|
||||
+ return le32_to_cpu(c->field); \
|
||||
+} while(0)
|
||||
+
|
||||
+
|
||||
+#define cmd_get_field_u8_mask(cmd, n, N, field, mask) \
|
||||
+do { \
|
||||
+ struct cxl_cmd_##n *c = \
|
||||
+ (struct cxl_cmd_##n *)cmd->send_cmd->out.payload; \
|
||||
+ int rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_##N); \
|
||||
+ if (rc) \
|
||||
+ return rc; \
|
||||
+ return !!(c->field & mask); \
|
||||
+} while(0)
|
||||
+
|
||||
+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_get_health_info(
|
||||
+ struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_HEALTH_INFO);
|
||||
+}
|
||||
+
|
||||
+#define cmd_health_get_status_field(c, m) \
|
||||
+ cmd_get_field_u8_mask(c, get_health_info, GET_HEALTH_INFO, health_status, m)
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_maintenance_needed(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_get_status_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_STATUS_MAINTENANCE_NEEDED_MASK);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_performance_degraded(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_get_status_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_STATUS_PERFORMANCE_DEGRADED_MASK);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_hw_replacement_needed(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_get_status_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_STATUS_HW_REPLACEMENT_NEEDED_MASK);
|
||||
+}
|
||||
+
|
||||
+#define cmd_health_check_media_field(cmd, f) \
|
||||
+do { \
|
||||
+ struct cxl_cmd_get_health_info *c = \
|
||||
+ (struct cxl_cmd_get_health_info *)cmd->send_cmd->out.payload; \
|
||||
+ int rc = cxl_cmd_validate_status(cmd, \
|
||||
+ CXL_MEM_COMMAND_ID_GET_HEALTH_INFO); \
|
||||
+ if (rc) \
|
||||
+ return rc; \
|
||||
+ return (c->media_status == f); \
|
||||
+} while(0)
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_media_normal(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NORMAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_media_not_ready(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NOT_READY);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_persistence_lost(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOST);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_media_data_lost(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOST);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_powerloss_persistence_loss(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_PERSISTENCE_LOSS);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_shutdown_persistence_loss(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_PERSISTENCE_LOSS);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_persistence_loss_imminent(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOSS_IMMINENT);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_powerloss_data_loss(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_DATA_LOSS);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_shutdown_data_loss(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_DATA_LOSS);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_media_data_loss_imminent(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_media_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOSS_IMMINENT);
|
||||
+}
|
||||
+
|
||||
+#define cmd_health_check_ext_field(cmd, fname, type) \
|
||||
+do { \
|
||||
+ struct cxl_cmd_get_health_info *c = \
|
||||
+ (struct cxl_cmd_get_health_info *)cmd->send_cmd->out.payload; \
|
||||
+ int rc = cxl_cmd_validate_status(cmd, \
|
||||
+ CXL_MEM_COMMAND_ID_GET_HEALTH_INFO); \
|
||||
+ if (rc) \
|
||||
+ return rc; \
|
||||
+ return (FIELD_GET(fname##_MASK, c->ext_status) == \
|
||||
+ fname##_##type); \
|
||||
+} while(0)
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_life_used_normal(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_LIFE_USED, NORMAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_life_used_warning(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_LIFE_USED, WARNING);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_life_used_critical(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_LIFE_USED, CRITICAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_temperature_normal(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE, NORMAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_temperature_warning(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE, WARNING);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_temperature_critical(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE, CRITICAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_corrected_volatile_normal(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE, NORMAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_corrected_volatile_warning(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE, WARNING);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_corrected_persistent_normal(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT, NORMAL);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int
|
||||
+cxl_cmd_health_info_get_ext_corrected_persistent_warning(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_health_check_ext_field(cmd,
|
||||
+ CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT, WARNING);
|
||||
+}
|
||||
+
|
||||
+static int health_info_get_life_used_raw(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_get_field_u8(cmd, get_health_info, GET_HEALTH_INFO,
|
||||
+ life_used);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_life_used(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ int rc = health_info_get_life_used_raw(cmd);
|
||||
+
|
||||
+ if (rc < 0)
|
||||
+ return rc;
|
||||
+ if (rc == CXL_CMD_HEALTH_INFO_LIFE_USED_NOT_IMPL)
|
||||
+ return -EOPNOTSUPP;
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int health_info_get_temperature_raw(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_get_field_u16(cmd, get_health_info, GET_HEALTH_INFO,
|
||||
+ temperature);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_temperature(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ int rc = health_info_get_temperature_raw(cmd);
|
||||
+
|
||||
+ if (rc < 0)
|
||||
+ return rc;
|
||||
+ if (rc == CXL_CMD_HEALTH_INFO_TEMPERATURE_NOT_IMPL)
|
||||
+ return -EOPNOTSUPP;
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_dirty_shutdowns(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_get_field_u32(cmd, get_health_info, GET_HEALTH_INFO,
|
||||
+ dirty_shutdowns);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_volatile_errors(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_get_field_u32(cmd, get_health_info, GET_HEALTH_INFO,
|
||||
+ volatile_errors);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_cmd_health_info_get_pmem_errors(struct cxl_cmd *cmd)
|
||||
+{
|
||||
+ cmd_get_field_u32(cmd, get_health_info, GET_HEALTH_INFO,
|
||||
+ pmem_errors);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev)
|
||||
{
|
||||
return cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_IDENTIFY);
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 1dc45f4..c83bc28 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -33,6 +33,35 @@ global:
|
||||
cxl_cmd_identify_get_fw_rev;
|
||||
cxl_cmd_identify_get_partition_align;
|
||||
cxl_cmd_identify_get_label_size;
|
||||
+ cxl_cmd_new_get_health_info;
|
||||
+ cxl_cmd_health_info_get_maintenance_needed;
|
||||
+ cxl_cmd_health_info_get_performance_degraded;
|
||||
+ cxl_cmd_health_info_get_hw_replacement_needed;
|
||||
+ cxl_cmd_health_info_get_media_normal;
|
||||
+ cxl_cmd_health_info_get_media_not_ready;
|
||||
+ cxl_cmd_health_info_get_media_persistence_lost;
|
||||
+ cxl_cmd_health_info_get_media_data_lost;
|
||||
+ cxl_cmd_health_info_get_media_powerloss_persistence_loss;
|
||||
+ cxl_cmd_health_info_get_media_shutdown_persistence_loss;
|
||||
+ cxl_cmd_health_info_get_media_persistence_loss_imminent;
|
||||
+ cxl_cmd_health_info_get_media_powerloss_data_loss;
|
||||
+ cxl_cmd_health_info_get_media_shutdown_data_loss;
|
||||
+ cxl_cmd_health_info_get_media_data_loss_imminent;
|
||||
+ cxl_cmd_health_info_get_ext_life_used_normal;
|
||||
+ cxl_cmd_health_info_get_ext_life_used_warning;
|
||||
+ cxl_cmd_health_info_get_ext_life_used_critical;
|
||||
+ cxl_cmd_health_info_get_ext_temperature_normal;
|
||||
+ cxl_cmd_health_info_get_ext_temperature_warning;
|
||||
+ cxl_cmd_health_info_get_ext_temperature_critical;
|
||||
+ cxl_cmd_health_info_get_ext_corrected_volatile_normal;
|
||||
+ cxl_cmd_health_info_get_ext_corrected_volatile_warning;
|
||||
+ cxl_cmd_health_info_get_ext_corrected_persistent_normal;
|
||||
+ cxl_cmd_health_info_get_ext_corrected_persistent_warning;
|
||||
+ cxl_cmd_health_info_get_life_used;
|
||||
+ cxl_cmd_health_info_get_temperature;
|
||||
+ cxl_cmd_health_info_get_dirty_shutdowns;
|
||||
+ cxl_cmd_health_info_get_volatile_errors;
|
||||
+ cxl_cmd_health_info_get_pmem_errors;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 3273f21..885553a 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -73,6 +73,53 @@ struct cxl_cmd_identify {
|
||||
u8 qos_telemetry_caps;
|
||||
} __attribute__((packed));
|
||||
|
||||
+struct cxl_cmd_get_health_info {
|
||||
+ u8 health_status;
|
||||
+ u8 media_status;
|
||||
+ u8 ext_status;
|
||||
+ u8 life_used;
|
||||
+ le16 temperature;
|
||||
+ le32 dirty_shutdowns;
|
||||
+ le32 volatile_errors;
|
||||
+ le32 pmem_errors;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
+/* CXL 2.0 8.2.9.5.3 Byte 0 Health Status */
|
||||
+#define CXL_CMD_HEALTH_INFO_STATUS_MAINTENANCE_NEEDED_MASK BIT(0)
|
||||
+#define CXL_CMD_HEALTH_INFO_STATUS_PERFORMANCE_DEGRADED_MASK BIT(1)
|
||||
+#define CXL_CMD_HEALTH_INFO_STATUS_HW_REPLACEMENT_NEEDED_MASK BIT(2)
|
||||
+
|
||||
+/* CXL 2.0 8.2.9.5.3 Byte 1 Media Status */
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NORMAL 0x0
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_NOT_READY 0x1
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOST 0x2
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOST 0x3
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_PERSISTENCE_LOSS 0x4
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_PERSISTENCE_LOSS 0x5
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_PERSISTENCE_LOSS_IMMINENT 0x6
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_POWERLOSS_DATA_LOSS 0x7
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_SHUTDOWN_DATA_LOSS 0x8
|
||||
+#define CXL_CMD_HEALTH_INFO_MEDIA_STATUS_DATA_LOSS_IMMINENT 0x9
|
||||
+
|
||||
+/* CXL 2.0 8.2.9.5.3 Byte 2 Additional Status */
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_MASK GENMASK(1, 0)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_NORMAL (0)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_WARNING (1)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_LIFE_USED_CRITICAL (2)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_MASK GENMASK(3, 2)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_NORMAL (0)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_WARNING (1)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_TEMPERATURE_CRITICAL (2)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE_MASK BIT(4)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE_NORMAL (0)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_VOLATILE_WARNING (1)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT_MASK BIT(5)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT_NORMAL (0)
|
||||
+#define CXL_CMD_HEALTH_INFO_EXT_CORRECTED_PERSISTENT_WARNING (1)
|
||||
+
|
||||
+#define CXL_CMD_HEALTH_INFO_LIFE_USED_NOT_IMPL 0xff
|
||||
+#define CXL_CMD_HEALTH_INFO_TEMPERATURE_NOT_IMPL 0xffff
|
||||
+
|
||||
static inline int check_kmod(struct kmod_ctx *kmod_ctx)
|
||||
{
|
||||
return kmod_ctx ? 0 : -ENXIO;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 0f2d5e9..eae2db8 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -62,6 +62,39 @@ struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev);
|
||||
int cxl_cmd_identify_get_fw_rev(struct cxl_cmd *cmd, char *fw_rev, int fw_len);
|
||||
unsigned long long cxl_cmd_identify_get_partition_align(struct cxl_cmd *cmd);
|
||||
unsigned int cxl_cmd_identify_get_label_size(struct cxl_cmd *cmd);
|
||||
+struct cxl_cmd *cxl_cmd_new_get_health_info(struct cxl_memdev *memdev);
|
||||
+int cxl_cmd_health_info_get_maintenance_needed(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_performance_degraded(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_hw_replacement_needed(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_normal(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_not_ready(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_persistence_lost(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_data_lost(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_normal(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_not_ready(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_persistence_lost(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_data_lost(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_powerloss_persistence_loss(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_shutdown_persistence_loss(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_persistence_loss_imminent(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_powerloss_data_loss(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_shutdown_data_loss(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_media_data_loss_imminent(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_life_used_normal(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_life_used_warning(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_life_used_critical(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_temperature_normal(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_temperature_warning(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_temperature_critical(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_corrected_volatile_normal(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_corrected_volatile_warning(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_corrected_persistent_normal(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_ext_corrected_persistent_warning(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_life_used(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_temperature(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_dirty_shutdowns(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_volatile_errors(struct cxl_cmd *cmd);
|
||||
+int cxl_cmd_health_info_get_pmem_errors(struct cxl_cmd *cmd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
diff --git a/util/bitmap.h b/util/bitmap.h
|
||||
index 490f3f0..04b3429 100644
|
||||
--- a/util/bitmap.h
|
||||
+++ b/util/bitmap.h
|
||||
@@ -3,10 +3,33 @@
|
||||
#ifndef _NDCTL_BITMAP_H_
|
||||
#define _NDCTL_BITMAP_H_
|
||||
|
||||
+#include <linux/const.h>
|
||||
#include <util/size.h>
|
||||
+#include <util/util.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
|
||||
+#ifndef _UL
|
||||
+#define _UL(x) (_AC(x, UL))
|
||||
+#endif
|
||||
+#ifndef _ULL
|
||||
+#define _ULL(x) (_AC(x, ULL))
|
||||
+#endif
|
||||
+
|
||||
#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
|
||||
+#define UL(x) (_UL(x))
|
||||
+#define ULL(x) (_ULL(x))
|
||||
+
|
||||
+/* GENMASK() and its dependencies copied from include/linux/{bits.h, const.h} */
|
||||
+#define __is_constexpr(x) \
|
||||
+ (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
|
||||
+#define GENMASK_INPUT_CHECK(h, l) \
|
||||
+ (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
|
||||
+ __is_constexpr((l) > (h)), (l) > (h), 0)))
|
||||
+#define __GENMASK(h, l) \
|
||||
+ (((~UL(0)) - (UL(1) << (l)) + 1) & \
|
||||
+ (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
|
||||
+#define GENMASK(h, l) \
|
||||
+ (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
@@ -30,5 +53,67 @@ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset);
|
||||
int bitmap_full(const unsigned long *src, unsigned int nbits);
|
||||
|
||||
+/*
|
||||
+ * Bitfield access macros
|
||||
+ * (Copied from Linux's include/linux/bitfield.h)
|
||||
+ *
|
||||
+ * FIELD_{GET,PREP} macros take as first parameter shifted mask
|
||||
+ * from which they extract the base mask and shift amount.
|
||||
+ * Mask must be a compilation time constant.
|
||||
+ *
|
||||
+ * Example:
|
||||
+ *
|
||||
+ * #define REG_FIELD_A GENMASK(6, 0)
|
||||
+ * #define REG_FIELD_B BIT(7)
|
||||
+ * #define REG_FIELD_C GENMASK(15, 8)
|
||||
+ * #define REG_FIELD_D GENMASK(31, 16)
|
||||
+ *
|
||||
+ * Get:
|
||||
+ * a = FIELD_GET(REG_FIELD_A, reg);
|
||||
+ * b = FIELD_GET(REG_FIELD_B, reg);
|
||||
+ *
|
||||
+ * Set:
|
||||
+ * reg = FIELD_PREP(REG_FIELD_A, 1) |
|
||||
+ * FIELD_PREP(REG_FIELD_B, 0) |
|
||||
+ * FIELD_PREP(REG_FIELD_C, c) |
|
||||
+ * FIELD_PREP(REG_FIELD_D, 0x40);
|
||||
+ *
|
||||
+ * Modify:
|
||||
+ * reg &= ~REG_FIELD_C;
|
||||
+ * reg |= FIELD_PREP(REG_FIELD_C, c);
|
||||
+ */
|
||||
+
|
||||
+/* Force a compilation error if a constant expression is not a power of 2 */
|
||||
+#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) \
|
||||
+ BUILD_BUG_ON(((n) & ((n) - 1)) != 0)
|
||||
+#define BUILD_BUG_ON_NOT_POWER_OF_2(n) \
|
||||
+ BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
|
||||
+
|
||||
+#define __bf_shf(x) (__builtin_ffsll(x) - 1)
|
||||
+
|
||||
+#define __BF_FIELD_CHECK(_mask, _reg, _val) \
|
||||
+ ({ \
|
||||
+ BUILD_BUG_ON(!__builtin_constant_p(_mask)); \
|
||||
+ BUILD_BUG_ON((_mask) == 0); \
|
||||
+ BUILD_BUG_ON(__builtin_constant_p(_val) ? \
|
||||
+ ~((_mask) >> __bf_shf(_mask)) & (_val) : 0); \
|
||||
+ BUILD_BUG_ON((_mask) > (typeof(_reg))~0ull); \
|
||||
+ __BUILD_BUG_ON_NOT_POWER_OF_2((_mask) + \
|
||||
+ (1ULL << __bf_shf(_mask))); \
|
||||
+ })
|
||||
+
|
||||
+/**
|
||||
+ * FIELD_GET() - extract a bitfield element
|
||||
+ * @_mask: shifted mask defining the field's length and position
|
||||
+ * @_reg: value of entire bitfield
|
||||
+ *
|
||||
+ * FIELD_GET() extracts the field specified by @_mask from the
|
||||
+ * bitfield passed in as @_reg by masking and shifting it down.
|
||||
+ */
|
||||
+#define FIELD_GET(_mask, _reg) \
|
||||
+ ({ \
|
||||
+ __BF_FIELD_CHECK(_mask, _reg, 0U); \
|
||||
+ (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \
|
||||
+ })
|
||||
|
||||
#endif /* _NDCTL_BITMAP_H_ */
|
||||
--
|
||||
2.27.0
|
||||
|
113
SOURCES/0038-libcxl-add-support-for-the-GET_LSA-command.patch
Normal file
113
SOURCES/0038-libcxl-add-support-for-the-GET_LSA-command.patch
Normal file
@ -0,0 +1,113 @@
|
||||
From c7ae078f1050ed54e254377404af2ae0879f2a39 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:30 -0600
|
||||
Subject: [PATCH 038/217] libcxl: add support for the 'GET_LSA' command
|
||||
|
||||
Add a command allocator and accessor APIs for the 'GET_LSA' mailbox
|
||||
command.
|
||||
|
||||
Cc: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 36 ++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 2 ++
|
||||
cxl/lib/private.h | 5 +++++
|
||||
cxl/libcxl.h | 4 ++++
|
||||
4 files changed, 47 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 065824d..76913a2 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -1036,6 +1036,42 @@ CXL_EXPORT struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev,
|
||||
return cmd;
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev,
|
||||
+ unsigned int offset, unsigned int length)
|
||||
+{
|
||||
+ struct cxl_cmd_get_lsa_in *get_lsa;
|
||||
+ struct cxl_cmd *cmd;
|
||||
+
|
||||
+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_LSA);
|
||||
+ if (!cmd)
|
||||
+ return NULL;
|
||||
+
|
||||
+ get_lsa = (struct cxl_cmd_get_lsa_in *)cmd->send_cmd->in.payload;
|
||||
+ get_lsa->offset = cpu_to_le32(offset);
|
||||
+ get_lsa->length = cpu_to_le32(length);
|
||||
+ return cmd;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd,
|
||||
+ void *buf, unsigned int length)
|
||||
+{
|
||||
+ struct cxl_cmd_get_lsa_in *get_lsa;
|
||||
+ void *payload;
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = cxl_cmd_validate_status(cmd, CXL_MEM_COMMAND_ID_GET_LSA);
|
||||
+ if (rc)
|
||||
+ return rc;
|
||||
+
|
||||
+ get_lsa = (struct cxl_cmd_get_lsa_in *)cmd->send_cmd->in.payload;
|
||||
+ if (length > le32_to_cpu(get_lsa->length))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ payload = (void *)cmd->send_cmd->out.payload;
|
||||
+ memcpy(buf, payload, length);
|
||||
+ return length;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_cmd_submit(struct cxl_cmd *cmd)
|
||||
{
|
||||
struct cxl_memdev *memdev = cmd->memdev;
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index c83bc28..629322c 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -62,6 +62,8 @@ global:
|
||||
cxl_cmd_health_info_get_dirty_shutdowns;
|
||||
cxl_cmd_health_info_get_volatile_errors;
|
||||
cxl_cmd_health_info_get_pmem_errors;
|
||||
+ cxl_cmd_new_read_label;
|
||||
+ cxl_cmd_read_label_get_payload;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 885553a..bf3a897 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -73,6 +73,11 @@ struct cxl_cmd_identify {
|
||||
u8 qos_telemetry_caps;
|
||||
} __attribute__((packed));
|
||||
|
||||
+struct cxl_cmd_get_lsa_in {
|
||||
+ le32 offset;
|
||||
+ le32 length;
|
||||
+} __attribute__((packed));
|
||||
+
|
||||
struct cxl_cmd_get_health_info {
|
||||
u8 health_status;
|
||||
u8 media_status;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index eae2db8..7408745 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -95,6 +95,10 @@ int cxl_cmd_health_info_get_temperature(struct cxl_cmd *cmd);
|
||||
int cxl_cmd_health_info_get_dirty_shutdowns(struct cxl_cmd *cmd);
|
||||
int cxl_cmd_health_info_get_volatile_errors(struct cxl_cmd *cmd);
|
||||
int cxl_cmd_health_info_get_pmem_errors(struct cxl_cmd *cmd);
|
||||
+struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev,
|
||||
+ unsigned int offset, unsigned int length);
|
||||
+ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, void *buf,
|
||||
+ unsigned int length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 101966ed3e4a73a6e0e1c269306e976040e068a9 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:32 -0600
|
||||
Subject: [PATCH 039/217] libcxl: add label_size to cxl_memdev, and an API to
|
||||
retrieve it
|
||||
|
||||
Size of the Label Storage Area (LSA) is available as a sysfs attribute
|
||||
called 'label_storage_size'. Add that to libcxl's memdev so that it is available
|
||||
for label related commands.
|
||||
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 12 ++++++++++++
|
||||
cxl/lib/libcxl.sym | 1 +
|
||||
cxl/lib/private.h | 1 +
|
||||
cxl/libcxl.h | 1 +
|
||||
4 files changed, 15 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 76913a2..def3a97 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -247,6 +247,13 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
||||
if (memdev->payload_max < 0)
|
||||
goto err_read;
|
||||
|
||||
+ sprintf(path, "%s/label_storage_size", cxlmem_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
+ goto err_read;
|
||||
+ memdev->lsa_size = strtoull(buf, NULL, 0);
|
||||
+ if (memdev->lsa_size == ULLONG_MAX)
|
||||
+ goto err_read;
|
||||
+
|
||||
memdev->dev_path = strdup(cxlmem_base);
|
||||
if (!memdev->dev_path)
|
||||
goto err_read;
|
||||
@@ -350,6 +357,11 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev
|
||||
return memdev->firmware_version;
|
||||
}
|
||||
|
||||
+CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ return memdev->lsa_size;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
|
||||
{
|
||||
if (!cmd)
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 629322c..858e953 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -64,6 +64,7 @@ global:
|
||||
cxl_cmd_health_info_get_pmem_errors;
|
||||
cxl_cmd_new_read_label;
|
||||
cxl_cmd_read_label_get_payload;
|
||||
+ cxl_memdev_get_label_size;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index bf3a897..c4ed741 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -21,6 +21,7 @@ struct cxl_memdev {
|
||||
unsigned long long pmem_size;
|
||||
unsigned long long ram_size;
|
||||
int payload_max;
|
||||
+ size_t lsa_size;
|
||||
struct kmod_module *module;
|
||||
};
|
||||
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 7408745..d3b97a1 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -42,6 +42,7 @@ 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);
|
||||
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
+size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
|
||||
#define cxl_memdev_foreach(ctx, memdev) \
|
||||
for (memdev = cxl_memdev_get_first(ctx); \
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,184 @@
|
||||
From cd1aed6cefe8f4f2043349e1a614876f67743439 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:33 -0600
|
||||
Subject: [PATCH 040/217] libcxl: add representation for an nvdimm bridge
|
||||
object
|
||||
|
||||
Add an nvdimm bridge object representation internal to libcxl. A bridge
|
||||
object is tied to its parent memdev object, and this patch adds its
|
||||
first interface, which checks whether a bridge is 'active' - i.e.
|
||||
implying the label space on the memdev is owned by the kernel.
|
||||
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 1 +
|
||||
cxl/lib/private.h | 8 +++++
|
||||
cxl/libcxl.h | 1 +
|
||||
4 files changed, 83 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index def3a97..60ed646 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -45,11 +45,19 @@ struct cxl_ctx {
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
+static void free_bridge(struct cxl_nvdimm_bridge *bridge)
|
||||
+{
|
||||
+ free(bridge->dev_buf);
|
||||
+ free(bridge->dev_path);
|
||||
+ free(bridge);
|
||||
+}
|
||||
+
|
||||
static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
{
|
||||
if (head)
|
||||
list_del_from(head, &memdev->list);
|
||||
kmod_module_unref(memdev->module);
|
||||
+ free_bridge(memdev->bridge);
|
||||
free(memdev->firmware_version);
|
||||
free(memdev->dev_buf);
|
||||
free(memdev->dev_path);
|
||||
@@ -205,6 +213,40 @@ CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority)
|
||||
ctx->ctx.log_priority = priority;
|
||||
}
|
||||
|
||||
+static void *add_cxl_bridge(void *parent, int id, const char *br_base)
|
||||
+{
|
||||
+ const char *devname = devpath_to_devname(br_base);
|
||||
+ struct cxl_memdev *memdev = parent;
|
||||
+ struct cxl_ctx *ctx = memdev->ctx;
|
||||
+ struct cxl_nvdimm_bridge *bridge;
|
||||
+
|
||||
+ dbg(ctx, "%s: bridge_base: \'%s\'\n", devname, br_base);
|
||||
+
|
||||
+ bridge = calloc(1, sizeof(*bridge));
|
||||
+ if (!bridge)
|
||||
+ goto err_dev;
|
||||
+ bridge->id = id;
|
||||
+
|
||||
+ bridge->dev_path = strdup(br_base);
|
||||
+ if (!bridge->dev_path)
|
||||
+ goto err_read;
|
||||
+
|
||||
+ bridge->dev_buf = calloc(1, strlen(br_base) + 50);
|
||||
+ if (!bridge->dev_buf)
|
||||
+ goto err_read;
|
||||
+ bridge->buf_len = strlen(br_base) + 50;
|
||||
+
|
||||
+ memdev->bridge = bridge;
|
||||
+ return bridge;
|
||||
+
|
||||
+ err_read:
|
||||
+ free(bridge->dev_buf);
|
||||
+ free(bridge->dev_path);
|
||||
+ free(bridge);
|
||||
+ err_dev:
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
||||
{
|
||||
const char *devname = devpath_to_devname(cxlmem_base);
|
||||
@@ -271,6 +313,8 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
||||
goto err_read;
|
||||
memdev->buf_len = strlen(cxlmem_base) + 50;
|
||||
|
||||
+ sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_bridge);
|
||||
+
|
||||
cxl_memdev_foreach(ctx, memdev_dup)
|
||||
if (memdev_dup->id == memdev->id) {
|
||||
free_memdev(memdev, NULL);
|
||||
@@ -362,6 +406,35 @@ CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev)
|
||||
return memdev->lsa_size;
|
||||
}
|
||||
|
||||
+static int is_enabled(const char *drvpath)
|
||||
+{
|
||||
+ struct stat st;
|
||||
+
|
||||
+ if (lstat(drvpath, &st) < 0 || !S_ISLNK(st.st_mode))
|
||||
+ return 0;
|
||||
+ else
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ struct cxl_nvdimm_bridge *bridge = memdev->bridge;
|
||||
+ char *path = bridge->dev_buf;
|
||||
+ int len = bridge->buf_len;
|
||||
+
|
||||
+ if (!bridge)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) {
|
||||
+ err(ctx, "%s: nvdimm bridge buffer too small!\n",
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return is_enabled(path);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
|
||||
{
|
||||
if (!cmd)
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 858e953..f3b0c63 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -65,6 +65,7 @@ global:
|
||||
cxl_cmd_new_read_label;
|
||||
cxl_cmd_read_label_get_payload;
|
||||
cxl_memdev_get_label_size;
|
||||
+ cxl_memdev_nvdimm_bridge_active;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index c4ed741..525c41e 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -10,6 +10,13 @@
|
||||
|
||||
#define CXL_EXPORT __attribute__ ((visibility("default")))
|
||||
|
||||
+struct cxl_nvdimm_bridge {
|
||||
+ int id;
|
||||
+ void *dev_buf;
|
||||
+ size_t buf_len;
|
||||
+ char *dev_path;
|
||||
+};
|
||||
+
|
||||
struct cxl_memdev {
|
||||
int id, major, minor;
|
||||
void *dev_buf;
|
||||
@@ -23,6 +30,7 @@ struct cxl_memdev {
|
||||
int payload_max;
|
||||
size_t lsa_size;
|
||||
struct kmod_module *module;
|
||||
+ struct cxl_nvdimm_bridge *bridge;
|
||||
};
|
||||
|
||||
enum cxl_cmd_query_status {
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index d3b97a1..535e349 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -43,6 +43,7 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev);
|
||||
unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
||||
|
||||
#define cxl_memdev_foreach(ctx, memdev) \
|
||||
for (memdev = cxl_memdev_get_first(ctx); \
|
||||
--
|
||||
2.27.0
|
||||
|
247
SOURCES/0041-libcxl-add-interfaces-for-label-operations.patch
Normal file
247
SOURCES/0041-libcxl-add-interfaces-for-label-operations.patch
Normal file
@ -0,0 +1,247 @@
|
||||
From 6255d23452809ddc6d48083c35fc935e4fa420d8 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:34 -0600
|
||||
Subject: [PATCH 041/217] libcxl: add interfaces for label operations
|
||||
|
||||
Add libcxl interfaces to allow performinfg label (LSA) manipulations.
|
||||
Add a 'cxl_cmd_new_set_lsa' interface to create a 'Set LSA' mailbox
|
||||
command payload, and interfaces to read, write, and zero the LSA area on
|
||||
a memdev.
|
||||
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 158 +++++++++++++++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 4 ++
|
||||
cxl/lib/private.h | 6 ++
|
||||
cxl/libcxl.h | 8 +++
|
||||
4 files changed, 176 insertions(+)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 60ed646..f0664be 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -1197,3 +1197,161 @@ CXL_EXPORT int cxl_cmd_get_out_size(struct cxl_cmd *cmd)
|
||||
{
|
||||
return cmd->send_cmd->out.size;
|
||||
}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev,
|
||||
+ void *lsa_buf, unsigned int offset, unsigned int length)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ struct cxl_cmd_set_lsa *set_lsa;
|
||||
+ struct cxl_cmd *cmd;
|
||||
+ int rc;
|
||||
+
|
||||
+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_SET_LSA);
|
||||
+ if (!cmd)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* this will allocate 'in.payload' */
|
||||
+ rc = cxl_cmd_set_input_payload(cmd, NULL, sizeof(*set_lsa) + length);
|
||||
+ if (rc) {
|
||||
+ err(ctx, "%s: cmd setup failed: %s\n",
|
||||
+ cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
+ goto out_fail;
|
||||
+ }
|
||||
+ set_lsa = (struct cxl_cmd_set_lsa *)cmd->send_cmd->in.payload;
|
||||
+ set_lsa->offset = cpu_to_le32(offset);
|
||||
+ memcpy(set_lsa->lsa_data, lsa_buf, length);
|
||||
+
|
||||
+ return cmd;
|
||||
+
|
||||
+out_fail:
|
||||
+ cxl_cmd_unref(cmd);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+enum lsa_op {
|
||||
+ LSA_OP_GET,
|
||||
+ LSA_OP_SET,
|
||||
+ LSA_OP_ZERO,
|
||||
+};
|
||||
+
|
||||
+static int __lsa_op(struct cxl_memdev *memdev, int op, void *buf,
|
||||
+ size_t length, size_t offset)
|
||||
+{
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ void *zero_buf = NULL;
|
||||
+ struct cxl_cmd *cmd;
|
||||
+ ssize_t ret_len;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ switch (op) {
|
||||
+ case LSA_OP_GET:
|
||||
+ cmd = cxl_cmd_new_read_label(memdev, offset, length);
|
||||
+ if (!cmd)
|
||||
+ return -ENOMEM;
|
||||
+ rc = cxl_cmd_set_output_payload(cmd, buf, length);
|
||||
+ if (rc) {
|
||||
+ err(ctx, "%s: cmd setup failed: %s\n",
|
||||
+ cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ break;
|
||||
+ case LSA_OP_ZERO:
|
||||
+ zero_buf = calloc(1, length);
|
||||
+ if (!zero_buf)
|
||||
+ return -ENOMEM;
|
||||
+ buf = zero_buf;
|
||||
+ /* fall through */
|
||||
+ case LSA_OP_SET:
|
||||
+ cmd = cxl_cmd_new_write_label(memdev, buf, offset, length);
|
||||
+ if (!cmd) {
|
||||
+ rc = -ENOMEM;
|
||||
+ goto out_free;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ rc = cxl_cmd_submit(cmd);
|
||||
+ if (rc < 0) {
|
||||
+ err(ctx, "%s: cmd submission failed: %s\n",
|
||||
+ devname, strerror(-rc));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = cxl_cmd_get_mbox_status(cmd);
|
||||
+ if (rc != 0) {
|
||||
+ err(ctx, "%s: firmware status: %d\n",
|
||||
+ devname, rc);
|
||||
+ rc = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (op == LSA_OP_GET) {
|
||||
+ ret_len = cxl_cmd_read_label_get_payload(cmd, buf, length);
|
||||
+ if (ret_len < 0) {
|
||||
+ rc = ret_len;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ cxl_cmd_unref(cmd);
|
||||
+out_free:
|
||||
+ free(zero_buf);
|
||||
+ return rc;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int lsa_op(struct cxl_memdev *memdev, int op, void *buf,
|
||||
+ size_t length, size_t offset)
|
||||
+{
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ size_t remaining = length, cur_len, cur_off = 0;
|
||||
+ int label_iter_max, rc = 0;
|
||||
+
|
||||
+ if (op != LSA_OP_ZERO && buf == NULL) {
|
||||
+ err(ctx, "%s: LSA buffer cannot be NULL\n", devname);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (length == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ label_iter_max = memdev->payload_max - sizeof(struct cxl_cmd_set_lsa);
|
||||
+ while (remaining) {
|
||||
+ cur_len = min((size_t)label_iter_max, remaining);
|
||||
+ rc = __lsa_op(memdev, op, buf + cur_off,
|
||||
+ cur_len, offset + cur_off);
|
||||
+ if (rc)
|
||||
+ break;
|
||||
+
|
||||
+ remaining -= cur_len;
|
||||
+ cur_off += cur_len;
|
||||
+ }
|
||||
+
|
||||
+ if (rc && (op == LSA_OP_SET))
|
||||
+ err(ctx, "%s: labels may be in an inconsistent state\n",
|
||||
+ devname);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length,
|
||||
+ size_t offset)
|
||||
+{
|
||||
+ return lsa_op(memdev, LSA_OP_ZERO, NULL, length, offset);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf,
|
||||
+ size_t length, size_t offset)
|
||||
+{
|
||||
+ return lsa_op(memdev, LSA_OP_SET, buf, length, offset);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf,
|
||||
+ size_t length, size_t offset)
|
||||
+{
|
||||
+ return lsa_op(memdev, LSA_OP_GET, buf, length, offset);
|
||||
+}
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index f3b0c63..077d104 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -66,6 +66,10 @@ global:
|
||||
cxl_cmd_read_label_get_payload;
|
||||
cxl_memdev_get_label_size;
|
||||
cxl_memdev_nvdimm_bridge_active;
|
||||
+ cxl_cmd_new_write_label;
|
||||
+ cxl_memdev_zero_label;
|
||||
+ cxl_memdev_write_label;
|
||||
+ cxl_memdev_read_label;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 525c41e..a1b8b50 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -87,6 +87,12 @@ struct cxl_cmd_get_lsa_in {
|
||||
le32 length;
|
||||
} __attribute__((packed));
|
||||
|
||||
+struct cxl_cmd_set_lsa {
|
||||
+ le32 offset;
|
||||
+ le32 rsvd;
|
||||
+ unsigned char lsa_data[0];
|
||||
+} __attribute__ ((packed));
|
||||
+
|
||||
struct cxl_cmd_get_health_info {
|
||||
u8 health_status;
|
||||
u8 media_status;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 535e349..89d35ba 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -44,6 +44,12 @@ unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length,
|
||||
+ size_t offset);
|
||||
+int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length,
|
||||
+ size_t offset);
|
||||
+int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
|
||||
+ size_t offset);
|
||||
|
||||
#define cxl_memdev_foreach(ctx, memdev) \
|
||||
for (memdev = cxl_memdev_get_first(ctx); \
|
||||
@@ -101,6 +107,8 @@ struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev,
|
||||
unsigned int offset, unsigned int length);
|
||||
ssize_t cxl_cmd_read_label_get_payload(struct cxl_cmd *cmd, void *buf,
|
||||
unsigned int length);
|
||||
+struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev,
|
||||
+ void *buf, unsigned int offset, unsigned int length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,583 @@
|
||||
From c415cebe4b5ca50e06db78a4719f312e33106936 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:35 -0600
|
||||
Subject: [PATCH 042/217] cxl: add commands to read, write, and zero labels
|
||||
|
||||
Add the following cxl-cli commands: read-labels, write-labels,
|
||||
zero-labels. They operate on a CXL memdev, or a set of memdevs, and
|
||||
allow interacting with the label storage area (LSA) on the device.
|
||||
|
||||
Add man pages for the above cxl-cli commands.
|
||||
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/Makefile.am | 5 +-
|
||||
Documentation/cxl/cxl-read-labels.txt | 33 +++
|
||||
Documentation/cxl/cxl-write-labels.txt | 32 +++
|
||||
Documentation/cxl/cxl-zero-labels.txt | 29 ++
|
||||
Documentation/cxl/labels-description.txt | 8 +
|
||||
Documentation/cxl/labels-options.txt | 17 ++
|
||||
Documentation/cxl/memdev-option.txt | 4 +
|
||||
cxl/Makefile.am | 1 +
|
||||
cxl/builtin.h | 5 +
|
||||
cxl/cxl.c | 3 +
|
||||
cxl/memdev.c | 324 +++++++++++++++++++++++
|
||||
11 files changed, 460 insertions(+), 1 deletion(-)
|
||||
create mode 100644 Documentation/cxl/cxl-read-labels.txt
|
||||
create mode 100644 Documentation/cxl/cxl-write-labels.txt
|
||||
create mode 100644 Documentation/cxl/cxl-zero-labels.txt
|
||||
create mode 100644 Documentation/cxl/labels-description.txt
|
||||
create mode 100644 Documentation/cxl/labels-options.txt
|
||||
create mode 100644 Documentation/cxl/memdev-option.txt
|
||||
create mode 100644 cxl/memdev.c
|
||||
|
||||
diff --git a/Documentation/cxl/Makefile.am b/Documentation/cxl/Makefile.am
|
||||
index db98dd7..efabaa3 100644
|
||||
--- a/Documentation/cxl/Makefile.am
|
||||
+++ b/Documentation/cxl/Makefile.am
|
||||
@@ -19,7 +19,10 @@ endif
|
||||
|
||||
man1_MANS = \
|
||||
cxl.1 \
|
||||
- cxl-list.1
|
||||
+ cxl-list.1 \
|
||||
+ cxl-read-labels.1 \
|
||||
+ cxl-write-labels.1 \
|
||||
+ cxl-zero-labels.1
|
||||
|
||||
EXTRA_DIST = $(man1_MANS)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-read-labels.txt b/Documentation/cxl/cxl-read-labels.txt
|
||||
new file mode 100644
|
||||
index 0000000..143f296
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/cxl-read-labels.txt
|
||||
@@ -0,0 +1,33 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+cxl-read-labels(1)
|
||||
+==================
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+cxl-read-labels - read out the label area on a CXL memdev
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+'cxl read-labels' <mem0> [<mem1>..<memN>] [<options>]
|
||||
+
|
||||
+include::labels-description.txt[]
|
||||
+This command dumps the raw binary data in a memdev's label area to stdout or a
|
||||
+file. In the multi-memdev case the data is concatenated.
|
||||
+
|
||||
+OPTIONS
|
||||
+-------
|
||||
+include::labels-options.txt[]
|
||||
+
|
||||
+-o::
|
||||
+--output::
|
||||
+ output file
|
||||
+
|
||||
+include::../copyright.txt[]
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linkcxl:cxl-write-labels[1],
|
||||
+linkcxl:cxl-zero-labels[1],
|
||||
+CXL-2.0 9.13.2
|
||||
diff --git a/Documentation/cxl/cxl-write-labels.txt b/Documentation/cxl/cxl-write-labels.txt
|
||||
new file mode 100644
|
||||
index 0000000..75f42a5
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/cxl-write-labels.txt
|
||||
@@ -0,0 +1,32 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+cxl-write-labels(1)
|
||||
+===================
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+cxl-write-labels - write data to the label area on a memdev
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+'cxl write-labels <mem> [-i <filename>]'
|
||||
+
|
||||
+include::labels-description.txt[]
|
||||
+Read data from the input filename, or stdin, and write it to the given
|
||||
+<mem> device. Note that the device must not be active in any region, or
|
||||
+actively registered with the nvdimm subsystem. If it is, the kernel will
|
||||
+not allow write access to the device's label data area.
|
||||
+
|
||||
+OPTIONS
|
||||
+-------
|
||||
+include::labels-options.txt[]
|
||||
+-i::
|
||||
+--input::
|
||||
+ input file
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linkcxl:cxl-read-labels[1],
|
||||
+linkcxl:cxl-zero-labels[1],
|
||||
+CXL-2.0 9.13.2
|
||||
diff --git a/Documentation/cxl/cxl-zero-labels.txt b/Documentation/cxl/cxl-zero-labels.txt
|
||||
new file mode 100644
|
||||
index 0000000..bf95b24
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/cxl-zero-labels.txt
|
||||
@@ -0,0 +1,29 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+cxl-zero-labels(1)
|
||||
+==================
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+cxl-zero-labels - zero out the label area on a set of memdevs
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+'cxl zero-labels' <mem0> [<mem1>..<memN>] [<options>]
|
||||
+
|
||||
+include::labels-description.txt[]
|
||||
+This command resets the device to its default state by
|
||||
+deleting all labels.
|
||||
+
|
||||
+OPTIONS
|
||||
+-------
|
||||
+include::labels-options.txt[]
|
||||
+
|
||||
+include::../copyright.txt[]
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linkcxl:cxl-read-labels[1],
|
||||
+linkcxl:cxl-write-labels[1],
|
||||
+CXL-2.0 9.13.2
|
||||
diff --git a/Documentation/cxl/labels-description.txt b/Documentation/cxl/labels-description.txt
|
||||
new file mode 100644
|
||||
index 0000000..f60bd5d
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/labels-description.txt
|
||||
@@ -0,0 +1,8 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+DESCRIPTION
|
||||
+-----------
|
||||
+The region label area is a small persistent partition of capacity
|
||||
+available on some CXL memory devices. The label area is used to
|
||||
+and configure or determine the set of memory devices participating
|
||||
+in different interleave sets.
|
||||
diff --git a/Documentation/cxl/labels-options.txt b/Documentation/cxl/labels-options.txt
|
||||
new file mode 100644
|
||||
index 0000000..06fbac3
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/labels-options.txt
|
||||
@@ -0,0 +1,17 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+<memory device(s)>::
|
||||
+include::memdev-option.txt[]
|
||||
+
|
||||
+-s::
|
||||
+--size=::
|
||||
+ Limit the operation to the given number of bytes. A size of 0
|
||||
+ indicates to operate over the entire label capacity.
|
||||
+
|
||||
+-O::
|
||||
+--offset=::
|
||||
+ Begin the operation at the given offset into the label area.
|
||||
+
|
||||
+-v::
|
||||
+ Turn on verbose debug messages in the library (if libcxl was built with
|
||||
+ logging and debug enabled).
|
||||
diff --git a/Documentation/cxl/memdev-option.txt b/Documentation/cxl/memdev-option.txt
|
||||
new file mode 100644
|
||||
index 0000000..e778582
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/memdev-option.txt
|
||||
@@ -0,0 +1,4 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+A 'memX' device name, or a memdev id number. Restrict the operation to
|
||||
+the specified memdev(s). The keyword 'all' can be specified to indicate
|
||||
+the lack of any restriction.
|
||||
diff --git a/cxl/Makefile.am b/cxl/Makefile.am
|
||||
index 98606b9..da9f91d 100644
|
||||
--- a/cxl/Makefile.am
|
||||
+++ b/cxl/Makefile.am
|
||||
@@ -10,6 +10,7 @@ config.h: $(srcdir)/Makefile.am
|
||||
cxl_SOURCES =\
|
||||
cxl.c \
|
||||
list.c \
|
||||
+ memdev.c \
|
||||
../util/json.c \
|
||||
builtin.h
|
||||
|
||||
diff --git a/cxl/builtin.h b/cxl/builtin.h
|
||||
index 3797f98..78eca6e 100644
|
||||
--- a/cxl/builtin.h
|
||||
+++ b/cxl/builtin.h
|
||||
@@ -5,4 +5,9 @@
|
||||
|
||||
struct cxl_ctx;
|
||||
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
#endif /* _CXL_BUILTIN_H_ */
|
||||
diff --git a/cxl/cxl.c b/cxl/cxl.c
|
||||
index a7725f8..4b1661d 100644
|
||||
--- a/cxl/cxl.c
|
||||
+++ b/cxl/cxl.c
|
||||
@@ -61,6 +61,9 @@ static struct cmd_struct commands[] = {
|
||||
{ "version", .c_fn = cmd_version },
|
||||
{ "list", .c_fn = cmd_list },
|
||||
{ "help", .c_fn = cmd_help },
|
||||
+ { "zero-labels", .c_fn = cmd_zero_labels },
|
||||
+ { "read-labels", .c_fn = cmd_read_labels },
|
||||
+ { "write-labels", .c_fn = cmd_write_labels },
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
diff --git a/cxl/memdev.c b/cxl/memdev.c
|
||||
new file mode 100644
|
||||
index 0000000..5ee38e5
|
||||
--- /dev/null
|
||||
+++ b/cxl/memdev.c
|
||||
@@ -0,0 +1,324 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */
|
||||
+#include <stdio.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+#include <limits.h>
|
||||
+#include <util/log.h>
|
||||
+#include <util/filter.h>
|
||||
+#include <cxl/libcxl.h>
|
||||
+#include <util/parse-options.h>
|
||||
+#include <ccan/minmax/minmax.h>
|
||||
+#include <ccan/array_size/array_size.h>
|
||||
+
|
||||
+struct action_context {
|
||||
+ FILE *f_out;
|
||||
+ FILE *f_in;
|
||||
+};
|
||||
+
|
||||
+static struct parameters {
|
||||
+ const char *outfile;
|
||||
+ const char *infile;
|
||||
+ unsigned len;
|
||||
+ unsigned offset;
|
||||
+ bool verbose;
|
||||
+} param;
|
||||
+
|
||||
+#define fail(fmt, ...) \
|
||||
+do { \
|
||||
+ fprintf(stderr, "cxl-%s:%s:%d: " fmt, \
|
||||
+ VERSION, __func__, __LINE__, ##__VA_ARGS__); \
|
||||
+} while (0)
|
||||
+
|
||||
+#define BASE_OPTIONS() \
|
||||
+OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug")
|
||||
+
|
||||
+#define READ_OPTIONS() \
|
||||
+OPT_STRING('o', "output", ¶m.outfile, "output-file", \
|
||||
+ "filename to write label area contents")
|
||||
+
|
||||
+#define WRITE_OPTIONS() \
|
||||
+OPT_STRING('i', "input", ¶m.infile, "input-file", \
|
||||
+ "filename to read label area data")
|
||||
+
|
||||
+#define LABEL_OPTIONS() \
|
||||
+OPT_UINTEGER('s', "size", ¶m.len, "number of label bytes to operate"), \
|
||||
+OPT_UINTEGER('O', "offset", ¶m.offset, \
|
||||
+ "offset into the label area to start operation")
|
||||
+
|
||||
+static const struct option read_options[] = {
|
||||
+ BASE_OPTIONS(),
|
||||
+ LABEL_OPTIONS(),
|
||||
+ READ_OPTIONS(),
|
||||
+ OPT_END(),
|
||||
+};
|
||||
+
|
||||
+static const struct option write_options[] = {
|
||||
+ BASE_OPTIONS(),
|
||||
+ LABEL_OPTIONS(),
|
||||
+ WRITE_OPTIONS(),
|
||||
+ OPT_END(),
|
||||
+};
|
||||
+
|
||||
+static const struct option zero_options[] = {
|
||||
+ BASE_OPTIONS(),
|
||||
+ LABEL_OPTIONS(),
|
||||
+ OPT_END(),
|
||||
+};
|
||||
+
|
||||
+static int action_zero(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
+{
|
||||
+ size_t size;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (param.len)
|
||||
+ size = param.len;
|
||||
+ else
|
||||
+ size = cxl_memdev_get_label_size(memdev);
|
||||
+
|
||||
+ if (cxl_memdev_nvdimm_bridge_active(memdev)) {
|
||||
+ fprintf(stderr,
|
||||
+ "%s: has active nvdimm bridge, abort label write\n",
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ rc = cxl_memdev_zero_label(memdev, size, param.offset);
|
||||
+ if (rc < 0)
|
||||
+ fprintf(stderr, "%s: label zeroing failed: %s\n",
|
||||
+ cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
+{
|
||||
+ size_t size = param.len, read_len;
|
||||
+ unsigned char *buf;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (cxl_memdev_nvdimm_bridge_active(memdev)) {
|
||||
+ fprintf(stderr,
|
||||
+ "%s: has active nvdimm bridge, abort label write\n",
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ if (!size) {
|
||||
+ size_t label_size = cxl_memdev_get_label_size(memdev);
|
||||
+
|
||||
+ fseek(actx->f_in, 0L, SEEK_END);
|
||||
+ size = ftell(actx->f_in);
|
||||
+ fseek(actx->f_in, 0L, SEEK_SET);
|
||||
+
|
||||
+ if (size > label_size) {
|
||||
+ fprintf(stderr,
|
||||
+ "File size (%zu) greater than label area size (%zu), aborting\n",
|
||||
+ size, label_size);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ buf = calloc(1, size);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ read_len = fread(buf, 1, size, actx->f_in);
|
||||
+ if (read_len != size) {
|
||||
+ rc = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ rc = cxl_memdev_write_label(memdev, buf, size, param.offset);
|
||||
+ if (rc < 0)
|
||||
+ fprintf(stderr, "%s: label write failed: %s\n",
|
||||
+ cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
+
|
||||
+out:
|
||||
+ free(buf);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int action_read(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
+{
|
||||
+ size_t size, write_len;
|
||||
+ char *buf;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (param.len)
|
||||
+ size = param.len;
|
||||
+ else
|
||||
+ size = cxl_memdev_get_label_size(memdev);
|
||||
+
|
||||
+ buf = calloc(1, size);
|
||||
+ if (!buf)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rc = cxl_memdev_read_label(memdev, buf, size, param.offset);
|
||||
+ if (rc < 0) {
|
||||
+ fprintf(stderr, "%s: label read failed: %s\n",
|
||||
+ cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ write_len = fwrite(buf, 1, size, actx->f_out);
|
||||
+ if (write_len != size) {
|
||||
+ rc = -ENXIO;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ fflush(actx->f_out);
|
||||
+
|
||||
+out:
|
||||
+ free(buf);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
+ int (*action)(struct cxl_memdev *memdev, struct action_context *actx),
|
||||
+ const struct option *options, const char *usage)
|
||||
+{
|
||||
+ struct cxl_memdev *memdev, *single = NULL;
|
||||
+ struct action_context actx = { 0 };
|
||||
+ int i, rc = 0, count = 0, err = 0;
|
||||
+ const char * const u[] = {
|
||||
+ usage,
|
||||
+ NULL
|
||||
+ };
|
||||
+ unsigned long id;
|
||||
+
|
||||
+ argc = parse_options(argc, argv, options, u, 0);
|
||||
+
|
||||
+ if (argc == 0)
|
||||
+ usage_with_options(u, options);
|
||||
+ for (i = 0; i < argc; i++) {
|
||||
+ if (strcmp(argv[i], "all") == 0) {
|
||||
+ argv[0] = "all";
|
||||
+ argc = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (sscanf(argv[i], "mem%lu", &id) != 1) {
|
||||
+ fprintf(stderr, "'%s' is not a valid memdev name\n",
|
||||
+ argv[i]);
|
||||
+ err++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (err == argc) {
|
||||
+ usage_with_options(u, options);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!param.outfile)
|
||||
+ actx.f_out = stdout;
|
||||
+ else {
|
||||
+ actx.f_out = fopen(param.outfile, "w+");
|
||||
+ if (!actx.f_out) {
|
||||
+ fprintf(stderr, "failed to open: %s: (%s)\n",
|
||||
+ param.outfile, strerror(errno));
|
||||
+ rc = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!param.infile) {
|
||||
+ actx.f_in = stdin;
|
||||
+ } else {
|
||||
+ actx.f_in = fopen(param.infile, "r");
|
||||
+ if (!actx.f_in) {
|
||||
+ fprintf(stderr, "failed to open: %s: (%s)\n",
|
||||
+ param.infile, strerror(errno));
|
||||
+ rc = -errno;
|
||||
+ goto out_close_fout;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (param.verbose)
|
||||
+ cxl_set_log_priority(ctx, LOG_DEBUG);
|
||||
+
|
||||
+ rc = 0;
|
||||
+ err = 0;
|
||||
+ count = 0;
|
||||
+
|
||||
+ for (i = 0; i < argc; i++) {
|
||||
+ if (sscanf(argv[i], "mem%lu", &id) != 1
|
||||
+ && strcmp(argv[i], "all") != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ cxl_memdev_foreach (ctx, memdev) {
|
||||
+ if (!util_cxl_memdev_filter(memdev, argv[i]))
|
||||
+ continue;
|
||||
+
|
||||
+ if (action == action_write) {
|
||||
+ single = memdev;
|
||||
+ rc = 0;
|
||||
+ } else
|
||||
+ rc = action(memdev, &actx);
|
||||
+
|
||||
+ if (rc == 0)
|
||||
+ count++;
|
||||
+ else if (rc && !err)
|
||||
+ err = rc;
|
||||
+ }
|
||||
+ }
|
||||
+ rc = err;
|
||||
+
|
||||
+ if (action == action_write) {
|
||||
+ if (count > 1) {
|
||||
+ error("write-labels only supports writing a single memdev\n");
|
||||
+ usage_with_options(u, options);
|
||||
+ return -EINVAL;
|
||||
+ } else if (single) {
|
||||
+ rc = action(single, &actx);
|
||||
+ if (rc)
|
||||
+ count = 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (actx.f_in != stdin)
|
||||
+ fclose(actx.f_in);
|
||||
+
|
||||
+ out_close_fout:
|
||||
+ if (actx.f_out != stdout)
|
||||
+ fclose(actx.f_out);
|
||||
+
|
||||
+ out:
|
||||
+ /*
|
||||
+ * count if some actions succeeded, 0 if none were attempted,
|
||||
+ * negative error code otherwise.
|
||||
+ */
|
||||
+ if (count > 0)
|
||||
+ return count;
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ int count = memdev_action(argc, argv, ctx, action_write, write_options,
|
||||
+ "cxl write-labels <memdev> [-i <filename>]");
|
||||
+
|
||||
+ fprintf(stderr, "wrote %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
+ return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ int count = memdev_action(argc, argv, ctx, action_read, read_options,
|
||||
+ "cxl read-labels <mem0> [<mem1>..<memN>] [-o <filename>]");
|
||||
+
|
||||
+ fprintf(stderr, "read %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
+ return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ int count = memdev_action(argc, argv, ctx, action_zero, zero_options,
|
||||
+ "cxl zero-labels <mem0> [<mem1>..<memN>] [<options>]");
|
||||
+
|
||||
+ fprintf(stderr, "zeroed %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
+ return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
+}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,248 @@
|
||||
From 62fe17528d362110e258d56d8a2f44f2798f3f45 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:36 -0600
|
||||
Subject: [PATCH 043/217] Documentation/cxl: add library API documentation
|
||||
|
||||
Add library API documentation for libcxl(3) using the existing
|
||||
asciidoc(tor) build system. Add a section 3 man page for 'libcxl' that
|
||||
provides an overview of the library and its usage, and a man page for
|
||||
the 'cxl_new()' API.
|
||||
|
||||
Cc: Ben Widawsky <ben.widawsky@intel.com>
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.gitignore | 3 ++
|
||||
Documentation/cxl/lib/Makefile.am | 58 +++++++++++++++++++++++++++++++
|
||||
Documentation/cxl/lib/cxl_new.txt | 43 +++++++++++++++++++++++
|
||||
Documentation/cxl/lib/libcxl.txt | 56 +++++++++++++++++++++++++++++
|
||||
Makefile.am | 1 +
|
||||
configure.ac | 1 +
|
||||
6 files changed, 162 insertions(+)
|
||||
create mode 100644 Documentation/cxl/lib/Makefile.am
|
||||
create mode 100644 Documentation/cxl/lib/cxl_new.txt
|
||||
create mode 100644 Documentation/cxl/lib/libcxl.txt
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index 6a97b92..6468c7a 100644
|
||||
--- a/.gitignore
|
||||
+++ b/.gitignore
|
||||
@@ -14,12 +14,15 @@ Makefile.in
|
||||
/libtool
|
||||
/stamp-h1
|
||||
*.1
|
||||
+*.3
|
||||
Documentation/daxctl/asciidoc.conf
|
||||
Documentation/ndctl/asciidoc.conf
|
||||
Documentation/cxl/asciidoc.conf
|
||||
+Documentation/cxl/lib/asciidoc.conf
|
||||
Documentation/daxctl/asciidoctor-extensions.rb
|
||||
Documentation/ndctl/asciidoctor-extensions.rb
|
||||
Documentation/cxl/asciidoctor-extensions.rb
|
||||
+Documentation/cxl/lib/asciidoctor-extensions.rb
|
||||
Documentation/ndctl/attrs.adoc
|
||||
.dirstamp
|
||||
daxctl/config.h
|
||||
diff --git a/Documentation/cxl/lib/Makefile.am b/Documentation/cxl/lib/Makefile.am
|
||||
new file mode 100644
|
||||
index 0000000..41e3a5f
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/lib/Makefile.am
|
||||
@@ -0,0 +1,58 @@
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+# Copyright (C) 2020-2021 Intel Corporation. All rights reserved.
|
||||
+
|
||||
+if USE_ASCIIDOCTOR
|
||||
+
|
||||
+do_subst = sed -e 's,@Utility@,Libcxl,g' -e's,@utility@,libcxl,g'
|
||||
+CONFFILE = asciidoctor-extensions.rb
|
||||
+asciidoctor-extensions.rb: ../../asciidoctor-extensions.rb.in
|
||||
+ $(AM_V_GEN) $(do_subst) < $< > $@
|
||||
+
|
||||
+else
|
||||
+
|
||||
+do_subst = sed -e 's,UTILITY,libcxl,g'
|
||||
+CONFFILE = asciidoc.conf
|
||||
+asciidoc.conf: ../../asciidoc.conf.in
|
||||
+ $(AM_V_GEN) $(do_subst) < $< > $@
|
||||
+
|
||||
+endif
|
||||
+
|
||||
+man3_MANS = \
|
||||
+ libcxl.3 \
|
||||
+ cxl_new.3
|
||||
+
|
||||
+EXTRA_DIST = $(man3_MANS)
|
||||
+
|
||||
+CLEANFILES = $(man3_MANS)
|
||||
+
|
||||
+XML_DEPS = \
|
||||
+ ../../../version.m4 \
|
||||
+ ../../copyright.txt \
|
||||
+ Makefile \
|
||||
+ $(CONFFILE)
|
||||
+
|
||||
+RM ?= rm -f
|
||||
+
|
||||
+if USE_ASCIIDOCTOR
|
||||
+
|
||||
+%.3: %.txt $(XML_DEPS)
|
||||
+ $(AM_V_GEN)$(RM) $@+ $@ && \
|
||||
+ $(ASCIIDOC) -b manpage -d manpage -acompat-mode \
|
||||
+ -I. -rasciidoctor-extensions \
|
||||
+ -amansource=libcxl -amanmanual="libcxl Manual" \
|
||||
+ -andctl_version=$(VERSION) -o $@+ $< && \
|
||||
+ mv $@+ $@
|
||||
+
|
||||
+else
|
||||
+
|
||||
+%.xml: %.txt $(XML_DEPS)
|
||||
+ $(AM_V_GEN)$(RM) $@+ $@ && \
|
||||
+ $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
|
||||
+ --unsafe -alibcxl_version=$(VERSION) -o $@+ $< && \
|
||||
+ mv $@+ $@
|
||||
+
|
||||
+%.3: %.xml $(XML_DEPS)
|
||||
+ $(AM_V_GEN)$(RM) $@ && \
|
||||
+ $(XMLTO) -o . -m ../../manpage-normal.xsl man $<
|
||||
+
|
||||
+endif
|
||||
diff --git a/Documentation/cxl/lib/cxl_new.txt b/Documentation/cxl/lib/cxl_new.txt
|
||||
new file mode 100644
|
||||
index 0000000..147d4e0
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/lib/cxl_new.txt
|
||||
@@ -0,0 +1,43 @@
|
||||
+// SPDX-License-Identifier: LGPL-2.0
|
||||
+
|
||||
+cxl_new(3)
|
||||
+==========
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+cxl_new - Create a new library context object that acts as a handle for all
|
||||
+library operations
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+----
|
||||
+#include <cxl/libcxl.h>
|
||||
+
|
||||
+int cxl_new(struct cxl_ctx **ctx);
|
||||
+----
|
||||
+
|
||||
+DESCRIPTION
|
||||
+-----------
|
||||
+Instantiates a new library context, and stores an opaque pointer in ctx. The
|
||||
+context is freed by linklibcxl:cxl_unref[3], i.e. cxl_new(3) implies an
|
||||
+internal linklibcxl:cxl_ref[3].
|
||||
+
|
||||
+
|
||||
+RETURN VALUE
|
||||
+------------
|
||||
+Returns 0 on success, and a negative errno on failure.
|
||||
+Possible error codes are:
|
||||
+
|
||||
+ * -ENOMEM
|
||||
+ * -ENXIO
|
||||
+
|
||||
+EXAMPLE
|
||||
+-------
|
||||
+See example usage in test/libcxl.c
|
||||
+
|
||||
+include::../../copyright.txt[]
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linklibcxl:cxl_ref[3], linklibcxl:cxl_unref[3]
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
new file mode 100644
|
||||
index 0000000..2539369
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -0,0 +1,56 @@
|
||||
+// SPDX-License-Identifier: LGPL-2.0
|
||||
+
|
||||
+libcxl(3)
|
||||
+=========
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+libcxl - A library to interact with CXL devices through sysfs(5)
|
||||
+and ioctl(2) interfaces
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+#include <cxl/libcxl.h>
|
||||
+cc ... -lcxl
|
||||
+
|
||||
+DESCRIPTION
|
||||
+-----------
|
||||
+libcxl provides interfaces to interact with CXL devices in Linux, using sysfs
|
||||
+interfaces for most kernel interactions, and the ioctl() interface for command
|
||||
+submission.
|
||||
+
|
||||
+The starting point for all library interfaces is a 'cxl_ctx' object, returned
|
||||
+by linklibcxl:cxl_new[3]. CXL 'Type 3' memory devices are children of the
|
||||
+cxl_ctx object, and can be iterated through using an iterator API.
|
||||
+
|
||||
+Library level interfaces that are agnostic to any device, or a specific
|
||||
+subclass of operations have the prefix 'cxl_'
|
||||
+
|
||||
+The object representing a CXL Type 3 device is 'cxl_memdev'. Library interfaces
|
||||
+related to these devices have the prefix 'cxl_memdev_'. These interfaces are
|
||||
+mostly associated with sysfs interactions (unless otherwise noted in their
|
||||
+respective documentation pages). They are typically used to retrieve data
|
||||
+published by the kernel, or to send data or trigger kernel operations for a
|
||||
+given device.
|
||||
+
|
||||
+A 'cxl_cmd' is a reference counted object which is used to perform 'Mailbox'
|
||||
+commands as described in the CXL Specification. A 'cxl_cmd' object is tied to a
|
||||
+'cxl_memdev'. Associated library interfaces have the prefix 'cxl_cmd_'. Within
|
||||
+this sub-class of interfaces, there are:
|
||||
+
|
||||
+ * 'cxl_cmd_new_*' interfaces that allocate a new cxl_cmd object for a given
|
||||
+ command type.
|
||||
+
|
||||
+ * 'cxl_cmd_submit' which submits the command via ioctl()
|
||||
+
|
||||
+ * 'cxl_cmd_<name>_get_<field>' interfaces that get specific fields out of the
|
||||
+ command response
|
||||
+
|
||||
+ * 'cxl_cmd_get_*' interfaces to get general command related information.
|
||||
+
|
||||
+include::../../copyright.txt[]
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linklibcxl:cxl[1]
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index 4904ee7..e2f6bef 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
SUBDIRS = . cxl/lib daxctl/lib ndctl/lib cxl ndctl daxctl
|
||||
if ENABLE_DOCS
|
||||
SUBDIRS += Documentation/ndctl Documentation/daxctl Documentation/cxl
|
||||
+SUBDIRS += Documentation/cxl/lib
|
||||
endif
|
||||
SUBDIRS += test
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index dadae0a..00497ae 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -231,6 +231,7 @@ AC_CONFIG_FILES([
|
||||
Documentation/ndctl/Makefile
|
||||
Documentation/daxctl/Makefile
|
||||
Documentation/cxl/Makefile
|
||||
+ Documentation/cxl/lib/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
--
|
||||
2.27.0
|
||||
|
147
SOURCES/0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch
Normal file
147
SOURCES/0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch
Normal file
@ -0,0 +1,147 @@
|
||||
From 57b1484fa427228afd52cdfa4fa3916a7a5878bf Mon Sep 17 00:00:00 2001
|
||||
From: Ira Weiny <ira.weiny@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:37 -0600
|
||||
Subject: [PATCH 044/217] ndctl: Add CXL packages to the RPM spec
|
||||
|
||||
Add CXL related packages - the cxl-cli utility, the libcxl library, and
|
||||
development headers to respective RPM packages in the main spec file.
|
||||
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Makefile.am | 4 ++++
|
||||
ndctl.spec.in | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 53 insertions(+)
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index e2f6bef..fa2010a 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -23,17 +23,21 @@ CLEANFILES += $(noinst_SCRIPTS)
|
||||
|
||||
do_rhel_subst = sed -e 's,VERSION,$(VERSION),g' \
|
||||
-e 's,DAX_DNAME,daxctl-devel,g' \
|
||||
+ -e 's,CXL_DNAME,cxl-devel,g' \
|
||||
-e 's,DNAME,ndctl-devel,g' \
|
||||
-e '/^%defattr.*/d' \
|
||||
-e 's,DAX_LNAME,daxctl-libs,g' \
|
||||
+ -e 's,CXL_LNAME,cxl-libs,g' \
|
||||
-e 's,LNAME,ndctl-libs,g'
|
||||
|
||||
do_sles_subst = sed -e 's,VERSION,$(VERSION),g' \
|
||||
-e 's,DAX_DNAME,libdaxctl-devel,g' \
|
||||
+ -e 's,CXL_DNAME,libcxl-devel,g' \
|
||||
-e 's,DNAME,libndctl-devel,g' \
|
||||
-e 's,%license,%doc,g' \
|
||||
-e 's,\(^License:.*GPL\)v2,\1-2.0,g' \
|
||||
-e "s,DAX_LNAME,libdaxctl$$(($(LIBDAXCTL_CURRENT) - $(LIBDAXCTL_AGE))),g" \
|
||||
+ -e "s,CXL_LNAME,libcxl$$(($(LIBCXL_CURRENT) - $(LIBCXL_AGE))),g" \
|
||||
-e "s,LNAME,libndctl$$(($(LIBNDCTL_CURRENT) - $(LIBNDCTL_AGE))),g"
|
||||
|
||||
rhel/ndctl.spec: ndctl.spec.in Makefile.am version.m4
|
||||
diff --git a/ndctl.spec.in b/ndctl.spec.in
|
||||
index 0563b2d..4b08c05 100644
|
||||
--- a/ndctl.spec.in
|
||||
+++ b/ndctl.spec.in
|
||||
@@ -8,6 +8,7 @@ Source0: https://github.com/pmem/%{name}/archive/v%{version}.tar.gz#/%{name}-%{v
|
||||
|
||||
Requires: LNAME%{?_isa} = %{version}-%{release}
|
||||
Requires: DAX_LNAME%{?_isa} = %{version}-%{release}
|
||||
+Requires: CXL_LNAME%{?_isa} = %{version}-%{release}
|
||||
BuildRequires: autoconf
|
||||
%if 0%{?rhel} < 9
|
||||
BuildRequires: asciidoc
|
||||
@@ -54,6 +55,24 @@ the Linux kernel Device-DAX facility. This facility enables DAX mappings
|
||||
of performance / feature differentiated memory without need of a
|
||||
filesystem.
|
||||
|
||||
+%package -n cxl-cli
|
||||
+Summary: Manage CXL devices
|
||||
+License: GPLv2
|
||||
+Requires: CXL_LNAME%{?_isa} = %{version}-%{release}
|
||||
+
|
||||
+%description -n cxl-cli
|
||||
+The cxl utility provides enumeration and provisioning commands for
|
||||
+the Linux kernel CXL devices.
|
||||
+
|
||||
+%package -n CXL_DNAME
|
||||
+Summary: Development files for libcxl
|
||||
+License: LGPLv2
|
||||
+Requires: CXL_LNAME%{?_isa} = %{version}-%{release}
|
||||
+
|
||||
+%description -n CXL_DNAME
|
||||
+This package contains libraries and header files for developing applications
|
||||
+that use libcxl, a library for enumerating and communicating with CXL devices.
|
||||
+
|
||||
%package -n DAX_DNAME
|
||||
Summary: Development files for libdaxctl
|
||||
License: LGPLv2
|
||||
@@ -84,6 +103,13 @@ Device DAX is a facility for establishing DAX mappings of performance /
|
||||
feature-differentiated memory. DAX_LNAME provides an enumeration /
|
||||
control API for these devices.
|
||||
|
||||
+%package -n CXL_LNAME
|
||||
+Summary: Management library for CXL devices
|
||||
+License: LGPLv2
|
||||
+
|
||||
+%description -n CXL_LNAME
|
||||
+libcxl is a library for enumerating and communicating with CXL devices.
|
||||
+
|
||||
|
||||
%prep
|
||||
%setup -q ndctl-%{version}
|
||||
@@ -105,6 +131,8 @@ make check
|
||||
|
||||
%ldconfig_scriptlets -n DAX_LNAME
|
||||
|
||||
+%ldconfig_scriptlets -n CXL_LNAME
|
||||
+
|
||||
%define bashcompdir %(pkg-config --variable=completionsdir bash-completion)
|
||||
|
||||
%files
|
||||
@@ -126,6 +154,12 @@ make check
|
||||
%{_mandir}/man1/daxctl*
|
||||
%{_datadir}/daxctl/daxctl.conf
|
||||
|
||||
+%files -n cxl-cli
|
||||
+%defattr(-,root,root)
|
||||
+%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0
|
||||
+%{_bindir}/cxl
|
||||
+%{_mandir}/man1/cxl*
|
||||
+
|
||||
%files -n LNAME
|
||||
%defattr(-,root,root)
|
||||
%doc README.md
|
||||
@@ -138,6 +172,12 @@ make check
|
||||
%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0
|
||||
%{_libdir}/libdaxctl.so.*
|
||||
|
||||
+%files -n CXL_LNAME
|
||||
+%defattr(-,root,root)
|
||||
+%doc README.md
|
||||
+%license LICENSES/preferred/LGPL-2.1 LICENSES/other/MIT LICENSES/other/CC0-1.0
|
||||
+%{_libdir}/libcxl.so.*
|
||||
+
|
||||
%files -n DNAME
|
||||
%defattr(-,root,root)
|
||||
%license LICENSES/preferred/LGPL-2.1
|
||||
@@ -152,6 +192,15 @@ make check
|
||||
%{_libdir}/libdaxctl.so
|
||||
%{_libdir}/pkgconfig/libdaxctl.pc
|
||||
|
||||
+%files -n CXL_DNAME
|
||||
+%defattr(-,root,root)
|
||||
+%license LICENSES/preferred/LGPL-2.1
|
||||
+%{_includedir}/cxl/
|
||||
+%{_libdir}/libcxl.so
|
||||
+%{_libdir}/pkgconfig/libcxl.pc
|
||||
+%{_mandir}/man3/cxl*
|
||||
+%{_mandir}/man3/libcxl.3.gz
|
||||
+
|
||||
|
||||
%changelog
|
||||
* Fri May 27 2016 Dan Williams <dan.j.williams@intel.com> - 53-1
|
||||
--
|
||||
2.27.0
|
||||
|
139
SOURCES/0045-cxl-cli-add-bash-completion.patch
Normal file
139
SOURCES/0045-cxl-cli-add-bash-completion.patch
Normal file
@ -0,0 +1,139 @@
|
||||
From 02c40b971bd4d092b3612fcb5e9ddd57548e6dbb Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:38 -0600
|
||||
Subject: [PATCH 045/217] cxl-cli: add bash completion
|
||||
|
||||
Add bash completion for the cxl-cli commands implemented so far:
|
||||
cxl-list
|
||||
cxl-read-labels
|
||||
cxl-write-labels
|
||||
cxl-zero-labels
|
||||
|
||||
Acked-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
contrib/ndctl | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 109 insertions(+)
|
||||
|
||||
diff --git a/contrib/ndctl b/contrib/ndctl
|
||||
index 680fe6a..cae4b1b 100755
|
||||
--- a/contrib/ndctl
|
||||
+++ b/contrib/ndctl
|
||||
@@ -647,5 +647,114 @@ _daxctl()
|
||||
__daxctl_main
|
||||
}
|
||||
|
||||
+### cxl-cli ###
|
||||
+
|
||||
+__cxl_get_devs()
|
||||
+{
|
||||
+ local opts=("--memdevs" "$*")
|
||||
+ cxl list "${opts[@]}" | grep -E "^\s*\"memdev\":" | cut -d'"' -f4
|
||||
+}
|
||||
+
|
||||
+__cxlcomp()
|
||||
+{
|
||||
+ local i=0
|
||||
+
|
||||
+ COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
|
||||
+ for cword in "${COMPREPLY[@]}"; do
|
||||
+ if [[ "$cword" == @(--memdev|--offset|--size|--input|--output) ]]; then
|
||||
+ COMPREPLY[$i]="${cword}="
|
||||
+ else
|
||||
+ COMPREPLY[$i]="${cword} "
|
||||
+ fi
|
||||
+ ((i++))
|
||||
+ done
|
||||
+}
|
||||
+
|
||||
+__cxl_comp_options()
|
||||
+{
|
||||
+
|
||||
+ local cur=$1
|
||||
+ local opts
|
||||
+
|
||||
+ if [[ "$cur" == *=* ]]; then
|
||||
+ local cur_subopt=${cur%%=*}
|
||||
+ local cur_arg=${cur##*=}
|
||||
+ case $cur_subopt in
|
||||
+ --memdev)
|
||||
+ opts="$(__cxl_get_devs -i)"
|
||||
+ ;;
|
||||
+ *)
|
||||
+ return
|
||||
+ ;;
|
||||
+ esac
|
||||
+ __cxlcomp "$opts" "$cur_arg"
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+__cxl_comp_non_option_args()
|
||||
+{
|
||||
+ local subcmd=$1
|
||||
+ local cur=$2
|
||||
+ local opts
|
||||
+
|
||||
+ case $subcmd in
|
||||
+ read-labels)
|
||||
+ ;&
|
||||
+ write-labels)
|
||||
+ ;&
|
||||
+ zero-labels)
|
||||
+ opts="$(__cxl_get_devs -i) all"
|
||||
+ ;;
|
||||
+ *)
|
||||
+ return
|
||||
+ ;;
|
||||
+ esac
|
||||
+ __cxlcomp "$opts" "$cur"
|
||||
+}
|
||||
+
|
||||
+__cxl_main()
|
||||
+{
|
||||
+ local cmd subcmd
|
||||
+
|
||||
+ cmd=${words[0]}
|
||||
+ COMPREPLY=()
|
||||
+
|
||||
+ # Skip options backward and find the last cxl command
|
||||
+ __nd_common_prev_skip_opts
|
||||
+ subcmd=$prev_skip_opts
|
||||
+ # List cxl subcommands or long options
|
||||
+ if [ -z $subcmd ]; then
|
||||
+ if [[ $cur == --* ]]; then
|
||||
+ cmds="--version --help --list-cmds"
|
||||
+ else
|
||||
+ cmds=$($cmd --list-cmds)
|
||||
+ fi
|
||||
+ __cxlcomp "$cmds" "$cur"
|
||||
+ else
|
||||
+ # List long option names
|
||||
+ if [[ $cur == --* ]]; then
|
||||
+ opts=$($cmd $subcmd --list-opts)
|
||||
+ __cxlcomp "$opts" "$cur"
|
||||
+ __cxl_comp_options "$cur"
|
||||
+ else
|
||||
+ [ -z "$subcmd" ] && return
|
||||
+ __cxl_comp_non_option_args "$subcmd" "$cur"
|
||||
+ fi
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+type cxl &>/dev/null &&
|
||||
+_cxl()
|
||||
+{
|
||||
+ local cur words cword prev
|
||||
+ if [ $preload_get_comp_words_by_ref = "true" ]; then
|
||||
+ _get_comp_words_by_ref -n =: cur words cword prev
|
||||
+ else
|
||||
+ __nd_common_get_comp_words_by_ref -n =: cur words cword prev
|
||||
+ fi
|
||||
+ __cxl_main
|
||||
+}
|
||||
+
|
||||
complete -o nospace -F _ndctl ndctl
|
||||
complete -o nospace -F _daxctl daxctl
|
||||
+complete -o nospace -F _cxl cxl
|
||||
--
|
||||
2.27.0
|
||||
|
308
SOURCES/0046-cxl-add-health-information-to-cxl-list.patch
Normal file
308
SOURCES/0046-cxl-add-health-information-to-cxl-list.patch
Normal file
@ -0,0 +1,308 @@
|
||||
From f5d1e2133c54c1f420a0c3cf45fa633f097823be Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Thu, 7 Oct 2021 02:21:39 -0600
|
||||
Subject: [PATCH 046/217] cxl: add health information to cxl-list
|
||||
|
||||
Add JSON output for fields from the 'GET_HEALTH_INFO' mailbox command
|
||||
to memory device listings.
|
||||
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 38 +++++++
|
||||
cxl/list.c | 5 +
|
||||
util/json.c | 179 +++++++++++++++++++++++++++++++++
|
||||
util/json.h | 1 +
|
||||
4 files changed, 223 insertions(+)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 370d5b8..c8d10fb 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -48,6 +48,44 @@ OPTIONS
|
||||
--idle::
|
||||
Include idle (not enabled / zero-sized) devices in the listing
|
||||
|
||||
+-H::
|
||||
+--health::
|
||||
+ Include health information in the memdev listing. Example listing:
|
||||
+----
|
||||
+# cxl list -m mem0 -H
|
||||
+[
|
||||
+ {
|
||||
+ "memdev":"mem0",
|
||||
+ "pmem_size":268435456,
|
||||
+ "ram_size":268435456,
|
||||
+ "health":{
|
||||
+ "maintenance_needed":true,
|
||||
+ "performance_degraded":true,
|
||||
+ "hw_replacement_needed":true,
|
||||
+ "media_normal":false,
|
||||
+ "media_not_ready":false,
|
||||
+ "media_persistence_lost":false,
|
||||
+ "media_data_lost":true,
|
||||
+ "media_powerloss_persistence_loss":false,
|
||||
+ "media_shutdown_persistence_loss":false,
|
||||
+ "media_persistence_loss_imminent":false,
|
||||
+ "media_powerloss_data_loss":false,
|
||||
+ "media_shutdown_data_loss":false,
|
||||
+ "media_data_loss_imminent":false,
|
||||
+ "ext_life_used":"normal",
|
||||
+ "ext_temperature":"critical",
|
||||
+ "ext_corrected_volatile":"warning",
|
||||
+ "ext_corrected_persistent":"normal",
|
||||
+ "life_used_percent":15,
|
||||
+ "temperature":25,
|
||||
+ "dirty_shutdowns":10,
|
||||
+ "volatile_errors":20,
|
||||
+ "pmem_errors":30
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+----
|
||||
+
|
||||
include::human-option.txt[]
|
||||
|
||||
include::verbose-option.txt[]
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 043d20c..b1468b7 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -16,6 +16,7 @@ static struct {
|
||||
bool memdevs;
|
||||
bool idle;
|
||||
bool human;
|
||||
+ bool health;
|
||||
} list;
|
||||
|
||||
static unsigned long listopts_to_flags(void)
|
||||
@@ -26,6 +27,8 @@ static unsigned long listopts_to_flags(void)
|
||||
flags |= UTIL_JSON_IDLE;
|
||||
if (list.human)
|
||||
flags |= UTIL_JSON_HUMAN;
|
||||
+ if (list.health)
|
||||
+ flags |= UTIL_JSON_HEALTH;
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -57,6 +60,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"),
|
||||
OPT_BOOLEAN('u', "human", &list.human,
|
||||
"use human friendly number formats "),
|
||||
+ OPT_BOOLEAN('H', "health", &list.health,
|
||||
+ "include memory device health information "),
|
||||
OPT_END(),
|
||||
};
|
||||
const char * const u[] = {
|
||||
diff --git a/util/json.c b/util/json.c
|
||||
index 3be3a92..f97cf07 100644
|
||||
--- a/util/json.c
|
||||
+++ b/util/json.c
|
||||
@@ -1442,6 +1442,180 @@ struct json_object *util_badblock_rec_to_json(u64 block, u64 count,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct json_object *util_cxl_memdev_health_to_json(
|
||||
+ struct cxl_memdev *memdev, unsigned long flags)
|
||||
+{
|
||||
+ struct json_object *jhealth;
|
||||
+ struct json_object *jobj;
|
||||
+ struct cxl_cmd *cmd;
|
||||
+ u32 field;
|
||||
+ int rc;
|
||||
+
|
||||
+ jhealth = json_object_new_object();
|
||||
+ if (!jhealth)
|
||||
+ return NULL;
|
||||
+ if (!memdev)
|
||||
+ goto err_jobj;
|
||||
+
|
||||
+ cmd = cxl_cmd_new_get_health_info(memdev);
|
||||
+ if (!cmd)
|
||||
+ goto err_jobj;
|
||||
+
|
||||
+ rc = cxl_cmd_submit(cmd);
|
||||
+ if (rc < 0)
|
||||
+ goto err_cmd;
|
||||
+ rc = cxl_cmd_get_mbox_status(cmd);
|
||||
+ if (rc != 0)
|
||||
+ goto err_cmd;
|
||||
+
|
||||
+ /* health_status fields */
|
||||
+ rc = cxl_cmd_health_info_get_maintenance_needed(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "maintenance_needed", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_performance_degraded(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "performance_degraded", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_hw_replacement_needed(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "hw_replacement_needed", jobj);
|
||||
+
|
||||
+ /* media_status fields */
|
||||
+ rc = cxl_cmd_health_info_get_media_normal(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_normal", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_not_ready(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_not_ready", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_persistence_lost(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_persistence_lost", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_data_lost(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_data_lost", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_powerloss_persistence_loss(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_powerloss_persistence_loss", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_shutdown_persistence_loss(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_shutdown_persistence_loss", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_persistence_loss_imminent(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_persistence_loss_imminent", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_powerloss_data_loss(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_powerloss_data_loss", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_shutdown_data_loss(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_shutdown_data_loss", jobj);
|
||||
+
|
||||
+ rc = cxl_cmd_health_info_get_media_data_loss_imminent(cmd);
|
||||
+ jobj = json_object_new_boolean(rc);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "media_data_loss_imminent", jobj);
|
||||
+
|
||||
+ /* ext_status fields */
|
||||
+ if (cxl_cmd_health_info_get_ext_life_used_normal(cmd))
|
||||
+ jobj = json_object_new_string("normal");
|
||||
+ else if (cxl_cmd_health_info_get_ext_life_used_warning(cmd))
|
||||
+ jobj = json_object_new_string("warning");
|
||||
+ else if (cxl_cmd_health_info_get_ext_life_used_critical(cmd))
|
||||
+ jobj = json_object_new_string("critical");
|
||||
+ else
|
||||
+ jobj = json_object_new_string("unknown");
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "ext_life_used", jobj);
|
||||
+
|
||||
+ if (cxl_cmd_health_info_get_ext_temperature_normal(cmd))
|
||||
+ jobj = json_object_new_string("normal");
|
||||
+ else if (cxl_cmd_health_info_get_ext_temperature_warning(cmd))
|
||||
+ jobj = json_object_new_string("warning");
|
||||
+ else if (cxl_cmd_health_info_get_ext_temperature_critical(cmd))
|
||||
+ jobj = json_object_new_string("critical");
|
||||
+ else
|
||||
+ jobj = json_object_new_string("unknown");
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "ext_temperature", jobj);
|
||||
+
|
||||
+ if (cxl_cmd_health_info_get_ext_corrected_volatile_normal(cmd))
|
||||
+ jobj = json_object_new_string("normal");
|
||||
+ else if (cxl_cmd_health_info_get_ext_corrected_volatile_warning(cmd))
|
||||
+ jobj = json_object_new_string("warning");
|
||||
+ else
|
||||
+ jobj = json_object_new_string("unknown");
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "ext_corrected_volatile", jobj);
|
||||
+
|
||||
+ if (cxl_cmd_health_info_get_ext_corrected_persistent_normal(cmd))
|
||||
+ jobj = json_object_new_string("normal");
|
||||
+ else if (cxl_cmd_health_info_get_ext_corrected_persistent_warning(cmd))
|
||||
+ jobj = json_object_new_string("warning");
|
||||
+ else
|
||||
+ jobj = json_object_new_string("unknown");
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "ext_corrected_persistent", jobj);
|
||||
+
|
||||
+ /* other fields */
|
||||
+ field = cxl_cmd_health_info_get_life_used(cmd);
|
||||
+ if (field != 0xff) {
|
||||
+ jobj = json_object_new_int(field);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "life_used_percent", jobj);
|
||||
+ }
|
||||
+
|
||||
+ field = cxl_cmd_health_info_get_temperature(cmd);
|
||||
+ if (field != 0xffff) {
|
||||
+ jobj = json_object_new_int(field);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "temperature", jobj);
|
||||
+ }
|
||||
+
|
||||
+ field = cxl_cmd_health_info_get_dirty_shutdowns(cmd);
|
||||
+ jobj = json_object_new_int64(field);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "dirty_shutdowns", jobj);
|
||||
+
|
||||
+ field = cxl_cmd_health_info_get_volatile_errors(cmd);
|
||||
+ jobj = json_object_new_int64(field);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "volatile_errors", jobj);
|
||||
+
|
||||
+ field = cxl_cmd_health_info_get_pmem_errors(cmd);
|
||||
+ jobj = json_object_new_int64(field);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jhealth, "pmem_errors", jobj);
|
||||
+
|
||||
+ cxl_cmd_unref(cmd);
|
||||
+ return jhealth;
|
||||
+
|
||||
+err_cmd:
|
||||
+ cxl_cmd_unref(cmd);
|
||||
+err_jobj:
|
||||
+ json_object_put(jhealth);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
unsigned long flags)
|
||||
{
|
||||
@@ -1464,5 +1638,10 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
if (jobj)
|
||||
json_object_object_add(jdev, "ram_size", jobj);
|
||||
|
||||
+ if (flags & UTIL_JSON_HEALTH) {
|
||||
+ jobj = util_cxl_memdev_health_to_json(memdev, flags);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdev, "health", jobj);
|
||||
+ }
|
||||
return jdev;
|
||||
}
|
||||
diff --git a/util/json.h b/util/json.h
|
||||
index 91918c8..ce575e6 100644
|
||||
--- a/util/json.h
|
||||
+++ b/util/json.h
|
||||
@@ -19,6 +19,7 @@ enum util_json_flags {
|
||||
UTIL_JSON_CONFIGURED = (1 << 7),
|
||||
UTIL_JSON_FIRMWARE = (1 << 8),
|
||||
UTIL_JSON_DAX_MAPPINGS = (1 << 9),
|
||||
+ UTIL_JSON_HEALTH = (1 << 10),
|
||||
};
|
||||
|
||||
struct json_object;
|
||||
--
|
||||
2.27.0
|
||||
|
75
SOURCES/0047-ndctl-install-bash-completion-symlinks.patch
Normal file
75
SOURCES/0047-ndctl-install-bash-completion-symlinks.patch
Normal file
@ -0,0 +1,75 @@
|
||||
From ac46d00d7d4d555a238bb898e2ff4af0c444bebe Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Tue, 16 Nov 2021 17:51:31 -0700
|
||||
Subject: [PATCH 047/217] ndctl: install bash-completion symlinks
|
||||
|
||||
Install symlinks for other utilities (daxctl, cxl-cli) in the
|
||||
completions directory so that the dynamic completion loader can pick up
|
||||
their respective names. Without this, completions for daxctl and cxl
|
||||
would only work after a prior invocation of ndctl's completion.
|
||||
|
||||
Reported-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Makefile.am | 3 +++
|
||||
configure.ac | 1 +
|
||||
ndctl.spec.in | 4 +++-
|
||||
3 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile.am b/Makefile.am
|
||||
index fa2010a..bd0037e 100644
|
||||
--- a/Makefile.am
|
||||
+++ b/Makefile.am
|
||||
@@ -49,6 +49,9 @@ sles/ndctl.spec: sles/header ndctl.spec.in Makefile.am version.m4
|
||||
if ENABLE_BASH_COMPLETION
|
||||
bashcompletiondir = $(BASH_COMPLETION_DIR)
|
||||
dist_bashcompletion_DATA = contrib/ndctl
|
||||
+install-data-hook:
|
||||
+ $(LN_S) -f $(BASH_COMPLETION_DIR)/ndctl $(DESTDIR)/$(BASH_COMPLETION_DIR)/daxctl
|
||||
+ $(LN_S) -f $(BASH_COMPLETION_DIR)/ndctl $(DESTDIR)/$(BASH_COMPLETION_DIR)/cxl
|
||||
endif
|
||||
|
||||
modprobe_file = contrib/nvdimm-security.conf
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 00497ae..9ac785f 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -31,6 +31,7 @@ AC_PREFIX_DEFAULT([/usr])
|
||||
|
||||
AC_PROG_SED
|
||||
AC_PROG_MKDIR_P
|
||||
+AC_PROG_LN_S
|
||||
|
||||
AC_ARG_ENABLE([docs],
|
||||
AS_HELP_STRING([--disable-docs],
|
||||
diff --git a/ndctl.spec.in b/ndctl.spec.in
|
||||
index 4b08c05..27ca097 100644
|
||||
--- a/ndctl.spec.in
|
||||
+++ b/ndctl.spec.in
|
||||
@@ -140,7 +140,7 @@ make check
|
||||
%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0
|
||||
%{_bindir}/ndctl
|
||||
%{_mandir}/man1/ndctl*
|
||||
-%{bashcompdir}/
|
||||
+%{bashcompdir}/ndctl
|
||||
%{_unitdir}/ndctl-monitor.service
|
||||
%{_sysconfdir}/ndctl/keys/keys.readme
|
||||
%{_sysconfdir}/modprobe.d/nvdimm-security.conf
|
||||
@@ -153,12 +153,14 @@ make check
|
||||
%{_bindir}/daxctl
|
||||
%{_mandir}/man1/daxctl*
|
||||
%{_datadir}/daxctl/daxctl.conf
|
||||
+%{bashcompdir}/daxctl
|
||||
|
||||
%files -n cxl-cli
|
||||
%defattr(-,root,root)
|
||||
%license LICENSES/preferred/GPL-2.0 LICENSES/other/MIT LICENSES/other/CC0-1.0
|
||||
%{_bindir}/cxl
|
||||
%{_mandir}/man1/cxl*
|
||||
+%{bashcompdir}/cxl
|
||||
|
||||
%files -n LNAME
|
||||
%defattr(-,root,root)
|
||||
--
|
||||
2.27.0
|
||||
|
400
SOURCES/0048-scripts-Add-a-man-page-template-generator.patch
Normal file
400
SOURCES/0048-scripts-Add-a-man-page-template-generator.patch
Normal file
@ -0,0 +1,400 @@
|
||||
From 706a418798633ccb550b114eca7cc11038ab2695 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Tue, 14 Dec 2021 19:01:02 -0700
|
||||
Subject: [PATCH 048/217] scripts: Add a man page template generator
|
||||
|
||||
Add a script to generate man page templates for the utils and libraries
|
||||
under ndctl - including cxl, libcxl, ndctl, and daxctl.
|
||||
|
||||
The script can control certain include options depending on the options
|
||||
supplied, and either dump the templates to stdout, or write the actual
|
||||
files in their eventual directories, and open up an editor to further
|
||||
edit them (unless --no-edit is used).
|
||||
|
||||
Link: https://lore.kernel.org/r/20211215020102.97880-1-vishal.l.verma@intel.com
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
scripts/docsurgeon | 339 +++++++++++++++++++++++++
|
||||
scripts/docsurgeon_parser_generator.m4 | 23 ++
|
||||
2 files changed, 362 insertions(+)
|
||||
create mode 100755 scripts/docsurgeon
|
||||
create mode 100644 scripts/docsurgeon_parser_generator.m4
|
||||
|
||||
diff --git a/scripts/docsurgeon b/scripts/docsurgeon
|
||||
new file mode 100755
|
||||
index 0000000..ca0ad78
|
||||
--- /dev/null
|
||||
+++ b/scripts/docsurgeon
|
||||
@@ -0,0 +1,339 @@
|
||||
+#!/bin/bash -eE
|
||||
+
|
||||
+this_script="docsurgeon"
|
||||
+script_dir="$(cd "$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")" && pwd)"
|
||||
+env_file="${script_dir}/.env"
|
||||
+if [ -e "$env_file" ]; then
|
||||
+ # shellcheck source=.env
|
||||
+ . "$env_file"
|
||||
+fi
|
||||
+
|
||||
+sources_file="${script_dir}/.sources"
|
||||
+
|
||||
+parser_generator="${script_dir}/${this_script}_parser_generator.m4"
|
||||
+parser_lib="${script_dir}/${this_script}_parser.sh"
|
||||
+if [ ! -e "$parser_lib" ] || [ "$parser_generator" -nt "$parser_lib" ]; then
|
||||
+ if command -V argbash > /dev/null; then
|
||||
+ argbash --strip user-content "$parser_generator" -o "$parser_lib"
|
||||
+ else
|
||||
+ echo "error: please install argbash" >&2
|
||||
+ exit 1
|
||||
+ fi
|
||||
+fi
|
||||
+
|
||||
+if [[ $1 != "bin" ]]; then
|
||||
+ # shellcheck source=docsurgeon_parser.sh
|
||||
+ . "${script_dir}/${this_script}_parser.sh" || { echo "Couldn't find $parser_lib" >&2; exit 1; }
|
||||
+fi
|
||||
+
|
||||
+# some script defaults - override using '.env'
|
||||
+docbase="Documentation"
|
||||
+copyright_cli="// SPDX-License-Identifier: GPL-2.0"
|
||||
+copyright_footer_cli="include::../copyright.txt[]"
|
||||
+copyright_lib="// SPDX-License-Identifier: LGPL-2.0"
|
||||
+copyright_footer_lib="include::../../copyright.txt[]"
|
||||
+
|
||||
+# List of files we're creating, to be edited/renamed later
|
||||
+# This starts out blank, and is filled in as we go by gen_*() functions
|
||||
+declare -a outfiles
|
||||
+
|
||||
+cleanup()
|
||||
+{
|
||||
+ if [ ${#outfiles[@]} -gt 0 ]; then
|
||||
+ rm -f "${outfiles[@]}"
|
||||
+ fi
|
||||
+ set +x
|
||||
+}
|
||||
+
|
||||
+trap cleanup EXIT
|
||||
+
|
||||
+auto_detect_params()
|
||||
+{
|
||||
+ fs=""
|
||||
+ module=""
|
||||
+ section=""
|
||||
+
|
||||
+ # if module and section were explicitly specified, respect them
|
||||
+ if [[ $_arg_module ]] && [[ $_arg_section ]]; then
|
||||
+ return
|
||||
+ fi
|
||||
+
|
||||
+ # check if names are self-consistent, and determine 'fs'
|
||||
+ for name in ${_arg_name[@]}; do
|
||||
+ if [[ ! $fs ]]; then
|
||||
+ if [[ $name == *-* ]]; then
|
||||
+ fs="-"
|
||||
+ elif [[ $name == *_* ]]; then
|
||||
+ fs="_"
|
||||
+ else
|
||||
+ # can't autodetect section
|
||||
+ return
|
||||
+ fi
|
||||
+ fi
|
||||
+ if [[ $fs == "-" ]] && [[ $name == *_* ]]; then
|
||||
+ die "can't auto-detect params with mixed-style names"
|
||||
+ fi
|
||||
+ if [[ $fs == "_" ]] && [[ $name == *-* ]]; then
|
||||
+ die "can't auto-detect params with mixed-style names"
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ # try to detect module name
|
||||
+ for name in ${_arg_name[@]}; do
|
||||
+ str=${name%%$fs*}
|
||||
+ if [[ $module ]]; then
|
||||
+ if [[ $str != $module ]]; then
|
||||
+ die "Can't autodetect module because of mixed names ($str and $module)"
|
||||
+ fi
|
||||
+ else
|
||||
+ module="$str"
|
||||
+ fi
|
||||
+ done
|
||||
+
|
||||
+ # try to detect section number
|
||||
+ case "$fs" in
|
||||
+ -)
|
||||
+ section=1
|
||||
+ ;;
|
||||
+ _)
|
||||
+ section=3
|
||||
+ ;;
|
||||
+ *)
|
||||
+ die "Unknown fs, can't autodetect section number"
|
||||
+ ;;
|
||||
+ esac
|
||||
+
|
||||
+ if [[ $module ]]; then
|
||||
+ _arg_module="$module"
|
||||
+ fi
|
||||
+ if [[ $section ]]; then
|
||||
+ _arg_section="$section"
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+process_options_logic()
|
||||
+{
|
||||
+ if [[ $_arg_debug == "on" ]]; then
|
||||
+ set -x
|
||||
+ fi
|
||||
+
|
||||
+ auto_detect_params
|
||||
+}
|
||||
+
|
||||
+gen_underline()
|
||||
+{
|
||||
+ name="$1"
|
||||
+ char="$2"
|
||||
+ num="${#name}"
|
||||
+
|
||||
+ printf -v tmpstring "%-${num}s" " "
|
||||
+ echo "${tmpstring// /$char}"
|
||||
+}
|
||||
+
|
||||
+gen_header()
|
||||
+{
|
||||
+ printf "\n%s\n%s\n" "$1" "$(gen_underline "$1" "=")"
|
||||
+}
|
||||
+
|
||||
+gen_section()
|
||||
+{
|
||||
+ printf "\n%s\n%s\n" "$1" "$(gen_underline "$1" "-")"
|
||||
+}
|
||||
+
|
||||
+gen_section_name()
|
||||
+{
|
||||
+ name="$1"
|
||||
+
|
||||
+ gen_section "NAME"
|
||||
+ cat <<- EOF
|
||||
+ $name -
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_section_synopsis_1()
|
||||
+{
|
||||
+ name="$1"
|
||||
+
|
||||
+ gen_section "SYNOPSIS"
|
||||
+ cat <<- EOF
|
||||
+ [verse]
|
||||
+ '$_arg_module ${name#*-} [<options>]'
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_section_synopsis_3()
|
||||
+{
|
||||
+ name="$1"
|
||||
+
|
||||
+ gen_section "SYNOPSIS"
|
||||
+ cat <<- EOF
|
||||
+ [verse]
|
||||
+ ----
|
||||
+ #include <$_arg_module/lib$_arg_module.h>
|
||||
+
|
||||
+ <type> $name();
|
||||
+ ----
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_section_example_1()
|
||||
+{
|
||||
+ name="$1"
|
||||
+
|
||||
+ gen_section "EXAMPLE"
|
||||
+ cat <<- EOF
|
||||
+ ----
|
||||
+ # $_arg_module ${name#*-}
|
||||
+ ----
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_section_example_3()
|
||||
+{
|
||||
+ name="$1"
|
||||
+
|
||||
+ gen_section "EXAMPLE"
|
||||
+ cat <<- EOF
|
||||
+ See example usage in test/lib$_arg_module.c
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_section_options_1()
|
||||
+{
|
||||
+ gen_section "OPTIONS"
|
||||
+cat << EOF
|
||||
+-o::
|
||||
+--option::
|
||||
+ Description
|
||||
+EOF
|
||||
+
|
||||
+ if [[ $_arg_human_option == "on" ]]; then
|
||||
+ printf "\n%s\n" "include::human-option.txt[]"
|
||||
+ fi
|
||||
+ if [[ $_arg_verbose_option == "on" ]]; then
|
||||
+ printf "\n%s\n" "include::verbose-option.txt[]"
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+gen_section_seealso_1()
|
||||
+{
|
||||
+ gen_section "SEE ALSO"
|
||||
+ cat <<- EOF
|
||||
+ link$_arg_module:$_arg_module-list[$_arg_section],
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_section_seealso_3()
|
||||
+{
|
||||
+ gen_section "SEE ALSO"
|
||||
+ cat <<- EOF
|
||||
+ linklib$_arg_module:${_arg_module}_other_API[$_arg_section],
|
||||
+ EOF
|
||||
+}
|
||||
+
|
||||
+gen_cli()
|
||||
+{
|
||||
+ name="$1"
|
||||
+ path="$docbase/$_arg_module"
|
||||
+ if [ ! -d "$path" ]; then
|
||||
+ die "Not found: $path"
|
||||
+ fi
|
||||
+
|
||||
+ tmp="$(mktemp -p "$path" "$name.txt.XXXX")"
|
||||
+ outfiles+=("$tmp")
|
||||
+
|
||||
+ # Start template generation
|
||||
+ printf "%s\n" "$copyright_cli" > "$tmp"
|
||||
+ gen_header "$name" >> "$tmp"
|
||||
+ gen_section_name "$name" >> "$tmp"
|
||||
+ gen_section_synopsis_1 "$name" >> "$tmp"
|
||||
+ gen_section "DESCRIPTION" >> "$tmp"
|
||||
+ gen_section_example_1 "$name" >> "$tmp"
|
||||
+ gen_section_options_1 >> "$tmp"
|
||||
+ printf "\n%s\n" "$copyright_footer_cli" >> "$tmp"
|
||||
+ gen_section_seealso_1 >> "$tmp"
|
||||
+}
|
||||
+
|
||||
+gen_lib()
|
||||
+{
|
||||
+ name="$1"
|
||||
+ path="$docbase/$_arg_module/lib"
|
||||
+ if [ ! -d "$path" ]; then
|
||||
+ die "Not found: $path"
|
||||
+ fi
|
||||
+
|
||||
+ tmp="$(mktemp -p "$path" "$name.txt.XXXX")"
|
||||
+ outfiles+=("$tmp")
|
||||
+
|
||||
+ # Start template generation
|
||||
+ printf "%s\n" "$copyright_lib" > "$tmp"
|
||||
+ gen_header "$name($_arg_section)" >> "$tmp"
|
||||
+ gen_section_name "$name" >> "$tmp"
|
||||
+ gen_section_synopsis_3 "$name" >> "$tmp"
|
||||
+ gen_section "DESCRIPTION" >> "$tmp"
|
||||
+ gen_section "RETURN VALUE" >> "$tmp"
|
||||
+ gen_section_example_3 "$name" >> "$tmp"
|
||||
+ printf "\n%s\n" "$copyright_footer_lib" >> "$tmp"
|
||||
+ gen_section_seealso_3 >> "$tmp"
|
||||
+}
|
||||
+
|
||||
+gen_man()
|
||||
+{
|
||||
+ name="$1"
|
||||
+ case "$_arg_section" in
|
||||
+ 1)
|
||||
+ gen_cli "$name"
|
||||
+ ;;
|
||||
+ 3)
|
||||
+ gen_lib "$name"
|
||||
+ ;;
|
||||
+ *)
|
||||
+ die "Unknown section: $_arg_section"
|
||||
+ ;;
|
||||
+ esac
|
||||
+}
|
||||
+
|
||||
+gen_include()
|
||||
+{
|
||||
+ echo "in gen_include"
|
||||
+}
|
||||
+
|
||||
+main()
|
||||
+{
|
||||
+ process_options_logic
|
||||
+
|
||||
+ cmd="$_arg_command"
|
||||
+ case "$cmd" in
|
||||
+ gen-man)
|
||||
+ for name in ${_arg_name[@]}; do
|
||||
+ gen_man "$name"
|
||||
+ done
|
||||
+ ;;
|
||||
+ gen-include)
|
||||
+ for name in ${_arg_name[@]}; do
|
||||
+ gen_include
|
||||
+ done
|
||||
+ ;;
|
||||
+ *)
|
||||
+ die "Unknown command: $cmd"
|
||||
+ ;;
|
||||
+ esac
|
||||
+
|
||||
+ if [[ $_arg_dump == "on" ]]; then
|
||||
+ for file in ${outfiles[@]}; do
|
||||
+ echo "${file##*/}"
|
||||
+ cat "$file"
|
||||
+ rm "$file"
|
||||
+ done
|
||||
+ elif [ ${#outfiles[@]} -gt 0 ]; then
|
||||
+ if [[ $_arg_edit = "on" ]]; then
|
||||
+ vim -p "${outfiles[@]}"
|
||||
+ fi
|
||||
+
|
||||
+ for file in ${outfiles[@]}; do
|
||||
+ mv "$file" "${file%.*}"
|
||||
+ done
|
||||
+ fi
|
||||
+}
|
||||
+
|
||||
+main "$@"
|
||||
diff --git a/scripts/docsurgeon_parser_generator.m4 b/scripts/docsurgeon_parser_generator.m4
|
||||
new file mode 100644
|
||||
index 0000000..9283c7c
|
||||
--- /dev/null
|
||||
+++ b/scripts/docsurgeon_parser_generator.m4
|
||||
@@ -0,0 +1,23 @@
|
||||
+#!/bin/bash
|
||||
+
|
||||
+# m4_ignore(
|
||||
+echo "This is just a parsing library template, not the library - pass this file to 'argbash' to fix this." >&2
|
||||
+exit 11 #)Created by argbash-init v2.9.0
|
||||
+# Rearrange the order of options below according to what you would like to see in the help message.
|
||||
+# ARG_OPTIONAL_REPEATED([name], [n], [Command or function name to generate a template for.\n Can be repeated for multiple names. ], [])
|
||||
+# ARG_OPTIONAL_BOOLEAN([edit], [e], [Edit template files after creation], [on])
|
||||
+# ARG_OPTIONAL_BOOLEAN([debug], [], [Debug script problems (enables set -x)], )
|
||||
+# ARG_OPTIONAL_BOOLEAN([dump], [], [Write generated file to stdout instead of a file], )
|
||||
+# ARG_OPTIONAL_SINGLE([module], [m], [Module (Docs subdir) in which to create the template], [])
|
||||
+# ARG_OPTIONAL_SINGLE([section], [s], [man section for which to create the template], [])
|
||||
+# ARG_OPTIONAL_BOOLEAN([human-option], [u], [Include the human option in 'OPTIONS'], )
|
||||
+# ARG_OPTIONAL_BOOLEAN([verbose-option], [V], [Include the verbose option in 'OPTIONS'], )
|
||||
+# ARG_POSITIONAL_DOUBLEDASH()
|
||||
+# ARG_POSITIONAL_SINGLE([command], [Operation to perform:\n gen-man\n gen-include], [])
|
||||
+# ARGBASH_SET_DELIM([ =])
|
||||
+# ARG_OPTION_STACKING([getopt])
|
||||
+# ARG_RESTRICT_VALUES([no-local-options])
|
||||
+# ARG_DEFAULTS_POS
|
||||
+# ARG_HELP([Tool to aid in creating and managing man page templates])
|
||||
+# ARG_VERSION([echo "docsurgeon 0.1"])
|
||||
+# ARGBASH_GO
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,167 @@
|
||||
From 8f4e42c0c526e85b045fd0329df7cb904f511c98 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Thu, 7 Oct 2021 14:59:53 -0700
|
||||
Subject: [PATCH 049/217] daxctl: Add "Soft Reservation" theory of operation
|
||||
|
||||
As systems are starting to ship memory with the EFI "Special Purpose"
|
||||
attribute that Linux optionally turns into "Soft Reserved" ranges one of
|
||||
the immediate first questions is "where is my special memory, and how do
|
||||
access it". Add some documentation to explain the default behaviour of
|
||||
"Soft Reserved".
|
||||
|
||||
Link: https://lore.kernel.org/r/163364399303.201290.6835215953983673447.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Reported-by: John Groves <john@jagalactic.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.../daxctl/daxctl-reconfigure-device.txt | 127 ++++++++++++------
|
||||
1 file changed, 88 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt
|
||||
index f112b3c..132684c 100644
|
||||
--- a/Documentation/daxctl/daxctl-reconfigure-device.txt
|
||||
+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt
|
||||
@@ -12,6 +12,94 @@ SYNOPSIS
|
||||
[verse]
|
||||
'daxctl reconfigure-device' <dax0.0> [<dax1.0>...<daxY.Z>] [<options>]
|
||||
|
||||
+DESCRIPTION
|
||||
+-----------
|
||||
+
|
||||
+Reconfigure the operational mode of a dax device. This can be used to convert
|
||||
+a regular 'devdax' mode device to the 'system-ram' mode which arranges for the
|
||||
+dax range to be hot-plugged into the system as regular memory.
|
||||
+
|
||||
+NOTE: This is a destructive operation. Any data on the dax device *will* be
|
||||
+lost.
|
||||
+
|
||||
+NOTE: Device reconfiguration depends on the dax-bus device model. See
|
||||
+linkdaxctl:daxctl-migrate-device-model[1] for more information. If dax-class is
|
||||
+in use (via the dax_pmem_compat driver), the reconfiguration will fail with an
|
||||
+error such as the following:
|
||||
+----
|
||||
+# daxctl reconfigure-device --mode=system-ram --region=0 all
|
||||
+libdaxctl: daxctl_dev_disable: dax3.0: error: device model is dax-class
|
||||
+dax3.0: disable failed: Operation not supported
|
||||
+error reconfiguring devices: Operation not supported
|
||||
+reconfigured 0 devices
|
||||
+----
|
||||
+
|
||||
+'daxctl-reconfigure-device' nominally expects that it will online new memory
|
||||
+blocks as 'movable', so that kernel data doesn't make it into this memory.
|
||||
+However, there are other potential agents that may be configured to
|
||||
+automatically online new hot-plugged memory as it appears. Most notably,
|
||||
+these are the '/sys/devices/system/memory/auto_online_blocks' configuration,
|
||||
+or system udev rules. If such an agent races to online memory sections, daxctl
|
||||
+checks if the blocks were onlined as 'movable' memory. If this was not the
|
||||
+case, and the memory blocks are found to be in a different zone, then a
|
||||
+warning is displayed. If it is desired that a different agent control the
|
||||
+onlining of memory blocks, and the associated memory zone, then it is
|
||||
+recommended to use the --no-online option described below. This will abridge
|
||||
+the device reconfiguration operation to just hotplugging the memory, and
|
||||
+refrain from then onlining it.
|
||||
+
|
||||
+In case daxctl detects that there is a kernel policy to auto-online blocks
|
||||
+(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to
|
||||
+system-ram will result in a failure. This can be overridden with '--force'.
|
||||
+
|
||||
+
|
||||
+THEORY OF OPERATION
|
||||
+-------------------
|
||||
+The kernel device-dax subsystem surfaces character devices
|
||||
+that provide DAX-access (direct mappings sans page-cache buffering) to a
|
||||
+given memory region. The devices are named /dev/daxX.Y where X is a
|
||||
+region-id and Y is an instance-id within that region. There are 2
|
||||
+mechanisms that trigger device-dax instances to appear:
|
||||
+
|
||||
+1. Persistent Memory (PMEM) namespace configured in "devdax" mode. See
|
||||
+"ndctl create-namspace --help" and
|
||||
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/dax/Kconfig[CONFIG_DEV_DAX_PMEM].
|
||||
+In this case the device-dax instance is statically sized to its host
|
||||
+memory region which is bounded to the physical address range of the host
|
||||
+namespace.
|
||||
+
|
||||
+2. Soft Reserved memory enumerated by platform firmware. On EFI systems
|
||||
+this is communicated via the so called EFI_MEMORY_SP "Special Purpose"
|
||||
+attribute. See
|
||||
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/dax/Kconfig[CONFIG_DEV_DAX_HMEM].
|
||||
+In this case the device-dax instance(s) associated with the given memory
|
||||
+region can be resized and divided into multiple devices.
|
||||
+
|
||||
+In the Soft Reservation case the expectation for EFI + ACPI based
|
||||
+platforms is that in addition to the EFI_MEMORY_SP attribute the
|
||||
+firmware also creates distinct ACPI proximity domains for any address
|
||||
+range that has different performance characteristics than default
|
||||
+"System RAM". So, the SRAT will define the proximity domain, the SLIT
|
||||
+communicates relative distance to other proximity domains, and the HMAT
|
||||
+is populated with nominal read/write latency and read/write bandwidth
|
||||
+data. That HMAT data is emitted to the kernel log on bootup, and also
|
||||
+exported to sysfs. See
|
||||
+https://www.kernel.org/doc/html/latest/admin-guide/mm/numaperf.html[NUMAPERF],
|
||||
+for the runtime representation of CPU to Memory node performance
|
||||
+details.
|
||||
+
|
||||
+Outside of the NUMA performance details linked above the other method to
|
||||
+detect the presence of "Soft Reserved" memory is to dump /proc/iomem and
|
||||
+look for "Soft Reserved" ranges. If the kernel was not built with
|
||||
+CONFIG_EFI_SOFTRESERVE, predates the introduction of
|
||||
+CONFIG_EFI_SOFTRESERVE (v5.5), or was booted with the efi=nosoftreserve
|
||||
+command line then device-dax will not attach and the expectation is that
|
||||
+the memory shows up as a memory-only NUMA node. Otherwise the memory
|
||||
+shows up as a device-dax instance and DAXCTL(1) can be used to
|
||||
+optionally partition it and assign the memory back to the kernel as
|
||||
+"System RAM", or the device can be mapped directly as the back end of a
|
||||
+userspace memory allocator like https://pmem.io/vmem/libvmem/[LIBVMEM].
|
||||
+
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
@@ -83,45 +171,6 @@ reconfigured 1 device
|
||||
reconfigured 1 device
|
||||
----
|
||||
|
||||
-DESCRIPTION
|
||||
------------
|
||||
-
|
||||
-Reconfigure the operational mode of a dax device. This can be used to convert
|
||||
-a regular 'devdax' mode device to the 'system-ram' mode which arranges for the
|
||||
-dax range to be hot-plugged into the system as regular memory.
|
||||
-
|
||||
-NOTE: This is a destructive operation. Any data on the dax device *will* be
|
||||
-lost.
|
||||
-
|
||||
-NOTE: Device reconfiguration depends on the dax-bus device model. See
|
||||
-linkdaxctl:daxctl-migrate-device-model[1] for more information. If dax-class is
|
||||
-in use (via the dax_pmem_compat driver), the reconfiguration will fail with an
|
||||
-error such as the following:
|
||||
-----
|
||||
-# daxctl reconfigure-device --mode=system-ram --region=0 all
|
||||
-libdaxctl: daxctl_dev_disable: dax3.0: error: device model is dax-class
|
||||
-dax3.0: disable failed: Operation not supported
|
||||
-error reconfiguring devices: Operation not supported
|
||||
-reconfigured 0 devices
|
||||
-----
|
||||
-
|
||||
-'daxctl-reconfigure-device' nominally expects that it will online new memory
|
||||
-blocks as 'movable', so that kernel data doesn't make it into this memory.
|
||||
-However, there are other potential agents that may be configured to
|
||||
-automatically online new hot-plugged memory as it appears. Most notably,
|
||||
-these are the '/sys/devices/system/memory/auto_online_blocks' configuration,
|
||||
-or system udev rules. If such an agent races to online memory sections, daxctl
|
||||
-checks if the blocks were onlined as 'movable' memory. If this was not the
|
||||
-case, and the memory blocks are found to be in a different zone, then a
|
||||
-warning is displayed. If it is desired that a different agent control the
|
||||
-onlining of memory blocks, and the associated memory zone, then it is
|
||||
-recommended to use the --no-online option described below. This will abridge
|
||||
-the device reconfiguration operation to just hotplugging the memory, and
|
||||
-refrain from then onlining it.
|
||||
-
|
||||
-In case daxctl detects that there is a kernel policy to auto-online blocks
|
||||
-(via /sys/devices/system/memory/auto_online_blocks), then reconfiguring to
|
||||
-system-ram will result in a failure. This can be overridden with '--force'.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,46 @@
|
||||
From c55b18181281b2fffadb9e0e8955d74b8b719349 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Fri, 17 Dec 2021 19:25:11 -0700
|
||||
Subject: [PATCH 061/217] libcxl: fix potential NULL dereference in
|
||||
cxl_memdev_nvdimm_bridge_active()
|
||||
|
||||
Static analysis points out that the function above has a check for
|
||||
'if (!bridge)', implying that bridge maybe NULL, but it is dereferenced
|
||||
before the check, which could result in a NULL dereference.
|
||||
|
||||
Fix this by moving any accesses to the bridge structure after the NULL
|
||||
check.
|
||||
|
||||
Link: https://lore.kernel.org/r/20211218022511.314928-1-vishal.l.verma@intel.com
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index f0664be..3390eb9 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -420,12 +420,15 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
||||
{
|
||||
struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
struct cxl_nvdimm_bridge *bridge = memdev->bridge;
|
||||
- char *path = bridge->dev_buf;
|
||||
- int len = bridge->buf_len;
|
||||
+ char *path;
|
||||
+ int len;
|
||||
|
||||
if (!bridge)
|
||||
return 0;
|
||||
|
||||
+ path = bridge->dev_buf;
|
||||
+ len = bridge->buf_len;
|
||||
+
|
||||
if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) {
|
||||
err(ctx, "%s: nvdimm bridge buffer too small!\n",
|
||||
cxl_memdev_get_devname(memdev));
|
||||
--
|
||||
2.27.0
|
||||
|
142
SOURCES/0064-ndctl-release-v72.patch
Normal file
142
SOURCES/0064-ndctl-release-v72.patch
Normal file
@ -0,0 +1,142 @@
|
||||
From 25062cf34c70012f5d42ce1fef7e2dc129807c10 Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Fri, 17 Dec 2021 21:14:37 -0700
|
||||
Subject: [PATCH 064/217] ndctl: release v72
|
||||
|
||||
This release incorporates functionality up to the 5.16 kernel.
|
||||
|
||||
Highlights include a new utility and library for interfacing with the
|
||||
'CXL' drivers and devices, a policy based configuration mechanism for
|
||||
ndctl and daxctl, fixes, test updates, and general additions for the
|
||||
PAPR family of NVDIMMs, more seed device accounting fixes, misc unit
|
||||
test and documentation updates, and fixes to NVDIMM bus scrubbing.
|
||||
|
||||
Commands:
|
||||
cxl-cli: new utility providing list, {read,write,zero}-label commands
|
||||
daxctl-reconfigure-device: new --check-config option
|
||||
ndctl-monitor: add support for a new unified config file format
|
||||
ndctl-*-namespace: seed namespace accounting fixes
|
||||
|
||||
Tests:
|
||||
Fix device-dax mremap() test
|
||||
Exercise soft_offline_page() corner cases
|
||||
Fix btt expect table compile warning
|
||||
monitor.sh: add checking the presence of jq command ahead of time
|
||||
|
||||
APIs:
|
||||
ndctl_bus_nfit_translate_spa
|
||||
ndctl_dimm_sizeof_namespace_index
|
||||
ndctl_get_config_path
|
||||
ndctl_set_config_path
|
||||
daxctl_dev_has_online_memory
|
||||
daxctl_dev_will_auto_online_memory
|
||||
daxctl_get_config_path
|
||||
daxctl_set_config_path
|
||||
cxl_cmd_get_devname
|
||||
cxl_cmd_get_mbox_status
|
||||
cxl_cmd_get_out_size
|
||||
cxl_cmd_health_info_get_dirty_shutdowns
|
||||
cxl_cmd_health_info_get_ext_corrected_persistent_normal
|
||||
cxl_cmd_health_info_get_ext_corrected_persistent_warning
|
||||
cxl_cmd_health_info_get_ext_corrected_volatile_normal
|
||||
cxl_cmd_health_info_get_ext_corrected_volatile_warning
|
||||
cxl_cmd_health_info_get_ext_life_used_critical
|
||||
cxl_cmd_health_info_get_ext_life_used_normal
|
||||
cxl_cmd_health_info_get_ext_life_used_warning
|
||||
cxl_cmd_health_info_get_ext_temperature_critical
|
||||
cxl_cmd_health_info_get_ext_temperature_normal
|
||||
cxl_cmd_health_info_get_ext_temperature_warning
|
||||
cxl_cmd_health_info_get_hw_replacement_needed
|
||||
cxl_cmd_health_info_get_life_used
|
||||
cxl_cmd_health_info_get_maintenance_needed
|
||||
cxl_cmd_health_info_get_media_data_loss_imminent
|
||||
cxl_cmd_health_info_get_media_data_lost
|
||||
cxl_cmd_health_info_get_media_normal
|
||||
cxl_cmd_health_info_get_media_not_ready
|
||||
cxl_cmd_health_info_get_media_persistence_loss_imminent
|
||||
cxl_cmd_health_info_get_media_persistence_lost
|
||||
cxl_cmd_health_info_get_media_powerloss_data_loss
|
||||
cxl_cmd_health_info_get_media_powerloss_persistence_loss
|
||||
cxl_cmd_health_info_get_media_shutdown_data_loss
|
||||
cxl_cmd_health_info_get_media_shutdown_persistence_loss
|
||||
cxl_cmd_health_info_get_performance_degraded
|
||||
cxl_cmd_health_info_get_pmem_errors
|
||||
cxl_cmd_health_info_get_temperature
|
||||
cxl_cmd_health_info_get_volatile_errors
|
||||
cxl_cmd_identify_get_fw_rev
|
||||
cxl_cmd_identify_get_label_size
|
||||
cxl_cmd_identify_get_partition_align
|
||||
cxl_cmd_new_get_health_info
|
||||
cxl_cmd_new_identify
|
||||
cxl_cmd_new_raw
|
||||
cxl_cmd_new_read_label
|
||||
cxl_cmd_new_write_label
|
||||
cxl_cmd_read_label_get_payload
|
||||
cxl_cmd_ref
|
||||
cxl_cmd_set_input_payload
|
||||
cxl_cmd_set_output_payload
|
||||
cxl_cmd_submit
|
||||
cxl_cmd_unref
|
||||
cxl_get_log_priority
|
||||
cxl_get_private_data
|
||||
cxl_get_userdata
|
||||
cxl_memdev_get_ctx
|
||||
cxl_memdev_get_devname
|
||||
cxl_memdev_get_firmware_verison
|
||||
cxl_memdev_get_first
|
||||
cxl_memdev_get_id
|
||||
cxl_memdev_get_label_size
|
||||
cxl_memdev_get_major
|
||||
cxl_memdev_get_minor
|
||||
cxl_memdev_get_next
|
||||
cxl_memdev_get_pmem_size
|
||||
cxl_memdev_get_ram_size
|
||||
cxl_memdev_nvdimm_bridge_active
|
||||
cxl_memdev_read_label
|
||||
cxl_memdev_write_label
|
||||
cxl_memdev_zero_label
|
||||
cxl_new
|
||||
cxl_ref
|
||||
cxl_set_log_fn
|
||||
cxl_set_log_priority
|
||||
cxl_set_private_data
|
||||
cxl_set_userdata
|
||||
cxl_unref
|
||||
---
|
||||
Makefile.am.in | 8 ++++----
|
||||
git-version | 2 +-
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff -up ndctl-71.1/Makefile.am.in.orig ndctl-71.1/Makefile.am.in
|
||||
--- ndctl-71.1/Makefile.am.in.orig 2022-10-07 15:20:47.982353042 -0400
|
||||
+++ ndctl-71.1/Makefile.am.in 2022-10-07 15:21:02.174401362 -0400
|
||||
@@ -36,13 +36,13 @@ SED_PROCESS = \
|
||||
-e 's,@includedir\@,$(includedir),g' \
|
||||
< $< > $@ || rm $@
|
||||
|
||||
-LIBNDCTL_CURRENT=25
|
||||
+LIBNDCTL_CURRENT=26
|
||||
LIBNDCTL_REVISION=1
|
||||
-LIBNDCTL_AGE=19
|
||||
+LIBNDCTL_AGE=20
|
||||
|
||||
-LIBDAXCTL_CURRENT=6
|
||||
+LIBDAXCTL_CURRENT=7
|
||||
LIBDAXCTL_REVISION=0
|
||||
-LIBDAXCTL_AGE=5
|
||||
+LIBDAXCTL_AGE=6
|
||||
|
||||
LIBCXL_CURRENT=1
|
||||
LIBCXL_REVISION=0
|
||||
diff -up ndctl-71.1/git-version.orig ndctl-71.1/git-version
|
||||
--- ndctl-71.1/git-version.orig 2022-10-07 15:21:02.175401365 -0400
|
||||
+++ ndctl-71.1/git-version 2022-10-07 15:21:27.267486796 -0400
|
||||
@@ -19,7 +19,7 @@ dirty() {
|
||||
fi
|
||||
}
|
||||
|
||||
-DEF_VER=71.1
|
||||
+DEF_VER=72
|
||||
|
||||
LF='
|
||||
'
|
32
SOURCES/0067-ndctl-add-repology-graphic-to-README.md.patch
Normal file
32
SOURCES/0067-ndctl-add-repology-graphic-to-README.md.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 20a714fe89a7941ef99898821719a46f04f7488b Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Tue, 4 Jan 2022 17:18:23 -0700
|
||||
Subject: [PATCH 067/217] ndctl: add repology graphic to README.md
|
||||
|
||||
Add a graphic/badge from repology showing the packaging status of ndctl
|
||||
with various distros.
|
||||
|
||||
Link: https://lore.kernel.org/r/20220105001823.299797-1-vishal.l.verma@intel.com
|
||||
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
README.md | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/README.md b/README.md
|
||||
index 89dfc87..4ab4523 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -4,6 +4,9 @@
|
||||
Utility library for managing the libnvdimm (non-volatile memory device)
|
||||
sub-system in the Linux kernel
|
||||
|
||||
+<a href="https://repology.org/project/ndctl/versions">
|
||||
+ <img src="https://repology.org/badge/vertical-allrepos/ndctl.svg" alt="Packaging status" align="right">
|
||||
+</a>
|
||||
|
||||
Build
|
||||
=====
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 3f2a2973b23fa86c810aab49eeb8ff5f97a02720 Mon Sep 17 00:00:00 2001
|
||||
From: Yasunori Goto <y-goto@fujitsu.com>
|
||||
Date: Wed, 3 Feb 2021 19:17:07 +0900
|
||||
Subject: [PATCH 068/217] Documentation/ndctl: fix self-reference of ndctl
|
||||
disable-namespace
|
||||
|
||||
The man manual of ndctl disable-namespace link to itself at See
|
||||
Also section. It should be enable-namespace instead of it.
|
||||
|
||||
Signed-off-by: Yasunori Goto <y-goto@fujitsu.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://github.com/pmem/ndctl/pull/160
|
||||
---
|
||||
Documentation/ndctl/ndctl-disable-namespace.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Documentation/ndctl/ndctl-disable-namespace.txt b/Documentation/ndctl/ndctl-disable-namespace.txt
|
||||
index 5d3a8be..187348f 100644
|
||||
--- a/Documentation/ndctl/ndctl-disable-namespace.txt
|
||||
+++ b/Documentation/ndctl/ndctl-disable-namespace.txt
|
||||
@@ -22,4 +22,4 @@ include::../copyright.txt[]
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
-linkndctl:ndctl-disable-namespace[1]
|
||||
+linkndctl:ndctl-enable-namespace[1]
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,97 @@
|
||||
From 475cb041a97d3c7140efd1b0cda820fb22b69d11 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:31:44 -0800
|
||||
Subject: [PATCH 069/217] ndctl/docs: Clarify update-firwmware activation
|
||||
'overflow' conditions
|
||||
|
||||
Give examples and remediation for "overflow" events, i.e. where the
|
||||
estimated time to complete activation exceeds the platform advertised
|
||||
maximum. When that happens forced activation can lead to undefined results.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141830490.3990253.6263569501446070716.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/ndctl/ndctl-update-firmware.txt | 64 ++++++++++++++++++-
|
||||
1 file changed, 63 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Documentation/ndctl/ndctl-update-firmware.txt b/Documentation/ndctl/ndctl-update-firmware.txt
|
||||
index 1080d62..6166457 100644
|
||||
--- a/Documentation/ndctl/ndctl-update-firmware.txt
|
||||
+++ b/Documentation/ndctl/ndctl-update-firmware.txt
|
||||
@@ -58,7 +58,69 @@ include::xable-bus-options.txt[]
|
||||
Arm a device for firmware activation. This is enabled by default
|
||||
when a firmware image is specified. Specify --no-arm to disable
|
||||
this default. Otherwise, without a firmware image, this option can be
|
||||
- used to manually arm a device for firmware activate.
|
||||
+ used to manually arm a device for firmware activate. When a
|
||||
+ device transitions from unarmed to armed the platform recalculates the
|
||||
+ firmware activation time and compares it against the maximum platform
|
||||
+ supported time. If the activation time would exceed the platform maximum the
|
||||
+ arm attempt is aborted:
|
||||
+
|
||||
+[verse]
|
||||
+ndctl update-firmware --arm --bus=nfit_test.0 all
|
||||
+ Error: update firmware: nmem4: arm aborted, tripped overflow
|
||||
+[
|
||||
+ {
|
||||
+ "dev":"nmem1",
|
||||
+ "id":"cdab-0a-07e0-ffffffff",
|
||||
+ "handle":"0",
|
||||
+ "phys_id":"0",
|
||||
+ "security":"disabled",
|
||||
+ "firmware":{
|
||||
+ "current_version":"0",
|
||||
+ "can_update":true
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "dev":"nmem3",
|
||||
+ "id":"cdab-0a-07e0-fffeffff",
|
||||
+ "handle":"0x100",
|
||||
+ "phys_id":"0x2",
|
||||
+ "security":"disabled",
|
||||
+ "firmware":{
|
||||
+ "current_version":"0",
|
||||
+ "can_update":true
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ "dev":"nmem2",
|
||||
+ "id":"cdab-0a-07e0-feffffff",
|
||||
+ "handle":"0x1",
|
||||
+ "phys_id":"0x1",
|
||||
+ "security":"disabled",
|
||||
+ "firmware":{
|
||||
+ "current_version":"0",
|
||||
+ "can_update":true
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
+updated 3 nmems.
|
||||
+
|
||||
+ It is possible, but not recommended, to ignore timeout overflows
|
||||
+ with the --force option. At any point to view the 'armed' state of the
|
||||
+ bus do:
|
||||
+
|
||||
+[verse]
|
||||
+ndctl list -BF -b nfit_test.0
|
||||
+[
|
||||
+ {
|
||||
+ "provider":"nfit_test.0",
|
||||
+ "dev":"ndbus2",
|
||||
+ "scrub_state":"idle",
|
||||
+ "firmware":{
|
||||
+ "activate_method":"suspend",
|
||||
+ "activate_state":"overflow"
|
||||
+ }
|
||||
+ }
|
||||
+]
|
||||
|
||||
-D::
|
||||
--disarm::
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,23 +1,22 @@
|
||||
ndctl/test: Prepare for BLK-aperture support removal
|
||||
From e423b467e10e3405e6e09260b7669e7022b5f5f7 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:31:50 -0800
|
||||
Subject: [PATCH 070/217] ndctl/test: Prepare for BLK-aperture support removal
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141031
|
||||
The kernel is dropping its support for the BLK-aperture access method. The
|
||||
primary side effect of this for nfit_test is that NVDIMM namespace labeling
|
||||
will not be enabled by default. Update the unit tests to initialize the
|
||||
label index area in this scenario.
|
||||
|
||||
commit e423b467e10e3405e6e09260b7669e7022b5f5f7
|
||||
Author: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed Jan 5 13:31:50 2022 -0800
|
||||
|
||||
ndctl/test: Prepare for BLK-aperture support removal
|
||||
|
||||
The kernel is dropping its support for the BLK-aperture access method. The
|
||||
primary side effect of this for nfit_test is that NVDIMM namespace labeling
|
||||
will not be enabled by default. Update the unit tests to initialize the
|
||||
label index area in this scenario.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141830999.3990253.5021445352398348657.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/164141830999.3990253.5021445352398348657.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/core.c | 31 ++++++++++++++++++++++++++++---
|
||||
test/libndctl.c | 49 +++++++++++++++++++++++++++++++++++--------------
|
||||
2 files changed, 63 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/test/core.c b/test/core.c
|
||||
index 2b03aa9..93e1dae 100644
|
||||
@ -167,3 +166,6 @@ index d9b50f4..c0e4b4c 100644
|
||||
|
||||
/*
|
||||
* Starting with v4.10 the dimm on nfit_test.1 gets a unique
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,24 +1,40 @@
|
||||
ndctl/test: Move 'reset()' to function in 'common'
|
||||
From 6538529be5738f06543a0d7178f97e0b0e6b63c2 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:31:55 -0800
|
||||
Subject: [PATCH 071/217] ndctl/test: Move 'reset()' to function in 'common'
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141031
|
||||
When BLK mode is removed, tests that expect the nfit_test region to allow
|
||||
pmem namespace creation will need to 'init' rather than 'zero' labels. In
|
||||
preparation, take the time opportunity to move reset() to a common
|
||||
function. So that 'ndctl zero-labels' can be replaced with 'ndctl
|
||||
init-labels' in one central location.
|
||||
|
||||
commit 6538529be5738f06543a0d7178f97e0b0e6b63c2
|
||||
Author: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed Jan 5 13:31:55 2022 -0800
|
||||
|
||||
ndctl/test: Move 'reset()' to function in 'common'
|
||||
|
||||
When BLK mode is removed, tests that expect the nfit_test region to allow
|
||||
pmem namespace creation will need to 'init' rather than 'zero' labels. In
|
||||
preparation, take the time opportunity to move reset() to a common
|
||||
function. So that 'ndctl zero-labels' can be replaced with 'ndctl
|
||||
init-labels' in one central location.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141831509.3990253.14783946910211635678.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/164141831509.3990253.14783946910211635678.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/blk-exhaust.sh | 4 +---
|
||||
test/btt-check.sh | 7 -------
|
||||
test/btt-errors.sh | 12 +++---------
|
||||
test/btt-pad-compat.sh | 7 -------
|
||||
test/clear.sh | 4 +---
|
||||
test/common | 15 +++++++++++++++
|
||||
test/create.sh | 4 +---
|
||||
test/daxctl-create.sh | 4 ++--
|
||||
test/daxdev-errors.sh | 4 +---
|
||||
test/firmware-update.sh | 8 +++-----
|
||||
test/inject-error.sh | 7 -------
|
||||
test/max_available_extent_ns.sh | 9 +--------
|
||||
test/monitor.sh | 11 ++---------
|
||||
test/multi-dax.sh | 4 +---
|
||||
test/pfn-meta-errors.sh | 4 +---
|
||||
test/pmem-errors.sh | 4 +---
|
||||
test/rescan-partitions.sh | 7 -------
|
||||
test/sector-mode.sh | 9 ++-------
|
||||
test/track-uuid.sh | 4 +---
|
||||
19 files changed, 36 insertions(+), 92 deletions(-)
|
||||
|
||||
diff --git a/test/blk-exhaust.sh b/test/blk-exhaust.sh
|
||||
index 09c4aae..b6d3808 100755
|
||||
@ -407,3 +423,6 @@ index be3cf9c..3bacd2c 100755
|
||||
|
||||
rc=1
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,28 +1,27 @@
|
||||
ndctl/test: Initialize the label area by default
|
||||
From fe37c85f1ffb0b2d04ef60e8ece6a9a44a145cc5 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:00 -0800
|
||||
Subject: [PATCH 072/217] ndctl/test: Initialize the label area by default
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2143636
|
||||
The removal of BLK-mode support causes nfit_test regions to not be
|
||||
'aliased' by default, which means that the only way to enable labels is to
|
||||
initialize the namespace label index block. In support of that the common
|
||||
'reset()' helper is updated to initialize v1.1 labels instead of zero them.
|
||||
Additionally, it highlighted that some btt tests have silent assumptions of
|
||||
v1.1 vs v1.2 label support. Add a 'resetV()' alternative to the common
|
||||
'reset()' function that initializes the label area to v1.2.
|
||||
|
||||
commit fe37c85f1ffb0b2d04ef60e8ece6a9a44a145cc5
|
||||
Author: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed Jan 5 13:32:00 2022 -0800
|
||||
|
||||
ndctl/test: Initialize the label area by default
|
||||
|
||||
The removal of BLK-mode support causes nfit_test regions to not be
|
||||
'aliased' by default, which means that the only way to enable labels is to
|
||||
initialize the namespace label index block. In support of that the common
|
||||
'reset()' helper is updated to initialize v1.1 labels instead of zero them.
|
||||
Additionally, it highlighted that some btt tests have silent assumptions of
|
||||
v1.1 vs v1.2 label support. Add a 'resetV()' alternative to the common
|
||||
'reset()' function that initializes the label area to v1.2.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141832017.3990253.10383328274835531066.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
|
||||
Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
|
||||
Link: https://lore.kernel.org/r/164141832017.3990253.10383328274835531066.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/btt-errors.sh | 4 ++--
|
||||
test/btt-pad-compat.sh | 2 +-
|
||||
test/common | 11 +++++++++--
|
||||
test/label-compat.sh | 2 +-
|
||||
4 files changed, 13 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/test/btt-errors.sh b/test/btt-errors.sh
|
||||
index 5a20d26..6e69178 100755
|
||||
@ -100,3 +99,6 @@ index 8ab2858..7ae4d5e 100755
|
||||
|
||||
# grab the largest pmem region on -b $NFIT_TEST_BUS0
|
||||
query=". | sort_by(.available_size) | reverse | .[0].dev"
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,22 +1,20 @@
|
||||
ndctl/test: Skip BLK flags checks
|
||||
From 756a6598a0fa6cebdd0e98564af089ca6b463fb1 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:05 -0800
|
||||
Subject: [PATCH 073/217] ndctl/test: Skip BLK flags checks
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141031
|
||||
With the removal of BLK-mode support, test/libndctl will fail to detect the
|
||||
JEDEC format on the nfit_test bus. Report + skip that check rather than
|
||||
fail the test when that happens.
|
||||
|
||||
commit 756a6598a0fa6cebdd0e98564af089ca6b463fb1
|
||||
Author: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed Jan 5 13:32:05 2022 -0800
|
||||
|
||||
ndctl/test: Skip BLK flags checks
|
||||
|
||||
With the removal of BLK-mode support, test/libndctl will fail to detect the
|
||||
JEDEC format on the nfit_test bus. Report + skip that check rather than
|
||||
fail the test when that happens.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141832529.3990253.16538298357542644310.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/164141832529.3990253.16538298357542644310.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/libndctl.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/test/libndctl.c b/test/libndctl.c
|
||||
index c0e4b4c..1e97926 100644
|
||||
@ -40,3 +38,6 @@ index c0e4b4c..1e97926 100644
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,41 @@
|
||||
From b787320498508192f1e04ac38d39da4eb3ca26e9 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:10 -0800
|
||||
Subject: [PATCH 074/217] ndctl/test: Move sector-mode to a different region
|
||||
|
||||
Previously the largest region on the nfit_test.1 bus belonged to a BLK-mode
|
||||
region. With the removal of BLK-mode support update the test to instead
|
||||
find a suitable PMEM region to perform the checkout.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141833068.3990253.15694496866707006837.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/sector-mode.sh | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/test/sector-mode.sh b/test/sector-mode.sh
|
||||
index 439ef33..f70b0f1 100755
|
||||
--- a/test/sector-mode.sh
|
||||
+++ b/test/sector-mode.sh
|
||||
@@ -19,11 +19,11 @@ reset
|
||||
reset1
|
||||
|
||||
rc=1
|
||||
-query=". | sort_by(.size) | reverse | .[0].dev"
|
||||
-NAMESPACE=$($NDCTL list -b $NFIT_TEST_BUS1 -N | jq -r "$query")
|
||||
-REGION=$($NDCTL list -R --namespace=$NAMESPACE | jq -r "(.[]) | .dev")
|
||||
+query=". | sort_by(.available_size) | reverse | .[0].dev"
|
||||
+REGION=$($NDCTL list -R -b $NFIT_TEST_BUS1 | jq -r "$query")
|
||||
echo 0 > /sys/bus/nd/devices/$REGION/read_only
|
||||
-$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K
|
||||
+echo $ALIGN_SIZE > /sys/bus/nd/devices/$REGION/align
|
||||
+NAMESPACE=$($NDCTL create-namespace --no-autolabel -r $REGION -m sector -f -l 4K | jq -r ".dev")
|
||||
$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m dax -f -a $ALIGN_SIZE
|
||||
$NDCTL create-namespace --no-autolabel -e $NAMESPACE -m sector -f -l 4K
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -1,23 +1,46 @@
|
||||
ndctl: Deprecate BLK aperture support
|
||||
From 2e05cd6b4aee656f69e11cf8b5e280dd47a14b1b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:15 -0800
|
||||
Subject: [PATCH 075/217] ndctl: Deprecate BLK aperture support
|
||||
|
||||
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141031
|
||||
The kernel is dropping its BLK aperture support, so deprecate the same in
|
||||
ndctl. The options will still be supported, and the library calls will not
|
||||
be deleted in case code needs them to compile. However the documentation
|
||||
and the tests for BLK mode can be removed.
|
||||
|
||||
commit 2e05cd6b4aee656f69e11cf8b5e280dd47a14b1b
|
||||
Author: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed Jan 5 13:32:15 2022 -0800
|
||||
|
||||
ndctl: Deprecate BLK aperture support
|
||||
|
||||
The kernel is dropping its BLK aperture support, so deprecate the same in
|
||||
ndctl. The options will still be supported, and the library calls will not
|
||||
be deleted in case code needs them to compile. However the documentation
|
||||
and the tests for BLK mode can be removed.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141833579.3990253.17885822648406789915.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Link: https://lore.kernel.org/r/164141833579.3990253.17885822648406789915.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.gitignore | 4 -
|
||||
Documentation/ndctl/labels-description.txt | 5 +-
|
||||
.../ndctl/ndctl-create-namespace.txt | 29 +-
|
||||
Documentation/ndctl/ndctl-init-labels.txt | 7 +-
|
||||
Documentation/ndctl/ndctl-list.txt | 4 -
|
||||
Documentation/ndctl/region-description.txt | 10 +-
|
||||
README.md | 1 -
|
||||
contrib/nfit_test_depmod.conf | 1 -
|
||||
ndctl/Makefile.am | 6 +-
|
||||
ndctl/bat.c | 5 -
|
||||
ndctl/test.c | 11 -
|
||||
test.h | 3 -
|
||||
test/Makefile.am | 31 --
|
||||
test/blk-exhaust.sh | 30 --
|
||||
test/blk_namespaces.c | 357 ------------------
|
||||
test/core.c | 1 -
|
||||
test/create.sh | 13 -
|
||||
test/dpa-alloc.c | 326 ----------------
|
||||
test/libndctl.c | 198 ++--------
|
||||
test/multi-pmem.c | 285 --------------
|
||||
test/parent-uuid.c | 254 -------------
|
||||
21 files changed, 51 insertions(+), 1530 deletions(-)
|
||||
delete mode 100755 test/blk-exhaust.sh
|
||||
delete mode 100644 test/blk_namespaces.c
|
||||
delete mode 100644 test/dpa-alloc.c
|
||||
delete mode 100644 test/multi-pmem.c
|
||||
delete mode 100644 test/parent-uuid.c
|
||||
|
||||
diff --git a/.gitignore b/.gitignore
|
||||
index 6468c7a..6b19d90 100644
|
||||
@ -1938,3 +1961,6 @@ index bded33a..0000000
|
||||
- ndctl_unref(ctx);
|
||||
- return ndctl_test_result(test, rc);
|
||||
-}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,78 @@
|
||||
From 9bfb567715d1b45e6598e6b38bef531312c72db3 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:21 -0800
|
||||
Subject: [PATCH 076/217] ndctl/test: Fix support for missing dax_pmem_compat
|
||||
module
|
||||
|
||||
The kernel is moving to drop CONFIG_DEV_DAX_PMEM_COMPAT. Update
|
||||
ndctl_test_init() to not error out if dax_pmem_compat is missing. It seems
|
||||
that the original implementation of support for missing dax_pmem_compat was
|
||||
broken, or since that time newer versions of kmod_module_new_from_name() no
|
||||
longer fail when the module is missing.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141834155.3990253.5388773351209410262.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Fixes: b7991dbc22f3 ("ndctl/test: Relax dax_pmem_compat requirement")
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/core.c | 25 +++++++++++--------------
|
||||
1 file changed, 11 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/test/core.c b/test/core.c
|
||||
index dc1405d..5d1aa23 100644
|
||||
--- a/test/core.c
|
||||
+++ b/test/core.c
|
||||
@@ -120,7 +120,6 @@ int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
"nfit",
|
||||
"device_dax",
|
||||
"dax_pmem",
|
||||
- "dax_pmem_core",
|
||||
"dax_pmem_compat",
|
||||
"libnvdimm",
|
||||
"nd_btt",
|
||||
@@ -180,29 +179,27 @@ int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
/*
|
||||
* Skip device-dax bus-model modules on pre-v5.1
|
||||
*/
|
||||
- if ((strcmp(name, "dax_pmem_core") == 0
|
||||
- || strcmp(name, "dax_pmem_compat") == 0)
|
||||
- && !ndctl_test_attempt(test,
|
||||
- KERNEL_VERSION(5, 1, 0)))
|
||||
+ if ((strcmp(name, "dax_pmem_compat") == 0) &&
|
||||
+ !ndctl_test_attempt(test, KERNEL_VERSION(5, 1, 0)))
|
||||
continue;
|
||||
|
||||
retry:
|
||||
rc = kmod_module_new_from_name(*ctx, name, mod);
|
||||
-
|
||||
- /*
|
||||
- * dax_pmem_compat is not required, missing is ok,
|
||||
- * present-but-production is not ok.
|
||||
- */
|
||||
- if (rc && strcmp(name, "dax_pmem_compat") == 0)
|
||||
- continue;
|
||||
-
|
||||
if (rc) {
|
||||
- log_err(&log_ctx, "%s.ko: missing\n", name);
|
||||
+ log_err(&log_ctx, "failed to interrogate %s.ko\n",
|
||||
+ name);
|
||||
break;
|
||||
}
|
||||
|
||||
path = kmod_module_get_path(*mod);
|
||||
if (!path) {
|
||||
+ /*
|
||||
+ * dax_pmem_compat is not required, missing is
|
||||
+ * ok, present-but-production is not ok.
|
||||
+ */
|
||||
+ if (strcmp(name, "dax_pmem_compat") == 0)
|
||||
+ continue;
|
||||
+
|
||||
if (family != NVDIMM_FAMILY_INTEL &&
|
||||
(strcmp(name, "nfit") == 0 ||
|
||||
strcmp(name, "nd_e820") == 0))
|
||||
--
|
||||
2.27.0
|
||||
|
File diff suppressed because it is too large
Load Diff
104
SOURCES/0078-Documentation-Drop-attrs.adoc-include.patch
Normal file
104
SOURCES/0078-Documentation-Drop-attrs.adoc-include.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From d1b966de2b32f6152bc3b9c3f5d842ba12407a87 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:32 -0800
|
||||
Subject: [PATCH 078/217] Documentation: Drop attrs.adoc include
|
||||
|
||||
In preparation for switching build systems, drop the attrs.adoc include for
|
||||
communicating variables to asciidoc. Simply add the necessary variable
|
||||
values to the invocation of the command using the --attribute argument.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141835217.3990253.17678912974035740752.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.gitignore | 1 -
|
||||
Documentation/daxctl/Makefile.am | 17 +++++++----------
|
||||
.../daxctl/daxctl-reconfigure-device.txt | 2 --
|
||||
Documentation/ndctl/Makefile.am | 17 +++++++----------
|
||||
Documentation/ndctl/intel-nvdimm-security.txt | 2 --
|
||||
Documentation/ndctl/ndctl-load-keys.txt | 2 --
|
||||
Documentation/ndctl/ndctl-monitor.txt | 2 --
|
||||
Documentation/ndctl/ndctl-sanitize-dimm.txt | 2 --
|
||||
Documentation/ndctl/ndctl-setup-passphrase.txt | 2 --
|
||||
Documentation/ndctl/ndctl-update-passphrase.txt | 2 --
|
||||
10 files changed, 14 insertions(+), 35 deletions(-)
|
||||
|
||||
diff -up ndctl-71.1/.gitignore.orig ndctl-71.1/.gitignore
|
||||
--- ndctl-71.1/.gitignore.orig 2022-10-07 15:58:15.663005697 -0400
|
||||
+++ ndctl-71.1/.gitignore 2022-10-07 15:58:57.238147247 -0400
|
||||
@@ -23,7 +23,6 @@ Documentation/daxctl/asciidoctor-extensi
|
||||
Documentation/ndctl/asciidoctor-extensions.rb
|
||||
Documentation/cxl/asciidoctor-extensions.rb
|
||||
Documentation/cxl/lib/asciidoctor-extensions.rb
|
||||
-Documentation/ndctl/attrs.adoc
|
||||
.dirstamp
|
||||
daxctl/config.h
|
||||
daxctl/daxctl
|
||||
diff -up ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt.orig ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt
|
||||
--- ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/Documentation/ndctl/intel-nvdimm-security.txt 2022-10-07 15:59:06.192177733 -0400
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
-include::attrs.adoc[]
|
||||
-
|
||||
THEORY OF OPERATION
|
||||
-------------------
|
||||
The Intel Device Specific Methods (DSM) specification v1.7 and v1.8 [1]
|
||||
diff -up ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt
|
||||
--- ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/Documentation/ndctl/ndctl-load-keys.txt 2022-10-07 15:59:06.192177733 -0400
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
-include::attrs.adoc[]
|
||||
-
|
||||
ndctl-load-keys(1)
|
||||
==================
|
||||
|
||||
diff -up ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt
|
||||
--- ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/Documentation/ndctl/ndctl-monitor.txt 2022-10-07 15:59:06.192177733 -0400
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
-include::attrs.adoc[]
|
||||
-
|
||||
ndctl-monitor(1)
|
||||
================
|
||||
|
||||
diff -up ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt
|
||||
--- ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/Documentation/ndctl/ndctl-sanitize-dimm.txt 2022-10-07 15:59:06.192177733 -0400
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
-include::attrs.adoc[]
|
||||
-
|
||||
ndctl-sanitize-dimm(1)
|
||||
======================
|
||||
|
||||
diff -up ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt
|
||||
--- ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/Documentation/ndctl/ndctl-setup-passphrase.txt 2022-10-07 15:59:06.193177737 -0400
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
-include::attrs.adoc[]
|
||||
-
|
||||
ndctl-setup-passphrase(1)
|
||||
=========================
|
||||
|
||||
diff -up ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt.orig ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt
|
||||
--- ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/Documentation/ndctl/ndctl-update-passphrase.txt 2022-10-07 15:59:06.193177737 -0400
|
||||
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
-include::attrs.adoc[]
|
||||
-
|
||||
ndctl-update-passphrase(1)
|
||||
==========================
|
||||
|
@ -0,0 +1,53 @@
|
||||
From 3297995248081d31d282fc9a339894989ff94e23 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:37 -0800
|
||||
Subject: [PATCH 079/217] build: Drop unnecessary $tool/config.h includes
|
||||
|
||||
In preparation for support for meson as the build infrastructure remove
|
||||
some explicit config.h includes that will be replaced by a unified config.h
|
||||
at the top of the project.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141835727.3990253.12971738434561351928.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
daxctl/migrate.c | 1 -
|
||||
ndctl/keys.c | 1 -
|
||||
ndctl/monitor.c | 1 -
|
||||
3 files changed, 3 deletions(-)
|
||||
|
||||
diff -up ndctl-71.1/daxctl/migrate.c.orig ndctl-71.1/daxctl/migrate.c
|
||||
--- ndctl-71.1/daxctl/migrate.c.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/daxctl/migrate.c 2022-10-07 16:01:20.316634385 -0400
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
-#include <daxctl/config.h>
|
||||
#include <daxctl/libdaxctl.h>
|
||||
#include <util/parse-options.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
diff -up ndctl-71.1/ndctl/keys.c.orig ndctl-71.1/ndctl/keys.c
|
||||
--- ndctl-71.1/ndctl/keys.c.orig 2022-10-07 16:01:03.161575978 -0400
|
||||
+++ ndctl-71.1/ndctl/keys.c 2022-10-07 16:01:20.317634389 -0400
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <keyutils.h>
|
||||
#include <syslog.h>
|
||||
|
||||
-#include <ndctl/config.h>
|
||||
#include <ndctl/ndctl.h>
|
||||
#include <ndctl/libndctl.h>
|
||||
|
||||
diff -up ndctl-71.1/ndctl/monitor.c.orig ndctl-71.1/ndctl/monitor.c
|
||||
--- ndctl-71.1/ndctl/monitor.c.orig 2022-10-07 16:01:03.164575988 -0400
|
||||
+++ ndctl-71.1/ndctl/monitor.c 2022-10-07 16:01:20.318634392 -0400
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <util/util.h>
|
||||
#include <util/parse-options.h>
|
||||
#include <util/strbuf.h>
|
||||
-#include <ndctl/config.h>
|
||||
#include <ndctl/ndctl.h>
|
||||
#include <ndctl/libndctl.h>
|
||||
#include <sys/epoll.h>
|
355
SOURCES/0080-test-Prepare-out-of-line-builds.patch
Normal file
355
SOURCES/0080-test-Prepare-out-of-line-builds.patch
Normal file
@ -0,0 +1,355 @@
|
||||
From d12d5f82755db50277e50c8daa97be15107f924d Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:42 -0800
|
||||
Subject: [PATCH 080/217] test: Prepare out of line builds
|
||||
|
||||
In preparation for converting to meson prepare the unit tests to run out of
|
||||
a build directory rather than out of the source directory. Introduce
|
||||
TEST_PATH for the location of the test executables.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141836235.3990253.5237538466465550643.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/btt-errors.sh | 4 +---
|
||||
test/common | 37 +++++++++++++++++++++----------------
|
||||
test/dax-pmd.c | 11 +++++++++--
|
||||
test/dax.sh | 6 +++---
|
||||
test/daxdev-errors.sh | 4 ++--
|
||||
test/device-dax-fio.sh | 2 +-
|
||||
test/dm.sh | 4 ++--
|
||||
test/inject-smart.sh | 2 +-
|
||||
test/mmap.sh | 6 +++---
|
||||
test/monitor.sh | 6 +++---
|
||||
test/pmem-errors.sh | 8 +++-----
|
||||
test/sub-section.sh | 4 ++--
|
||||
test/track-uuid.sh | 2 +-
|
||||
13 files changed, 52 insertions(+), 44 deletions(-)
|
||||
|
||||
diff --git a/test/btt-errors.sh b/test/btt-errors.sh
|
||||
index 6e69178..18518d5 100755
|
||||
--- a/test/btt-errors.sh
|
||||
+++ b/test/btt-errors.sh
|
||||
@@ -11,14 +11,12 @@ rc=77
|
||||
|
||||
cleanup()
|
||||
{
|
||||
- rm -f $FILE
|
||||
- rm -f $MNT/$FILE
|
||||
if grep -q "$MNT" /proc/mounts; then
|
||||
umount $MNT
|
||||
else
|
||||
rc=77
|
||||
fi
|
||||
- rmdir $MNT
|
||||
+ rm -rf $MNT
|
||||
}
|
||||
|
||||
force_raw()
|
||||
diff --git a/test/common b/test/common
|
||||
index b6d4712..fb48795 100644
|
||||
--- a/test/common
|
||||
+++ b/test/common
|
||||
@@ -4,27 +4,32 @@
|
||||
# Global variables
|
||||
|
||||
# NDCTL
|
||||
-#
|
||||
-if [ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ]; then
|
||||
- export NDCTL=../ndctl/ndctl
|
||||
-elif [ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ]; then
|
||||
- export NDCTL=./ndctl/ndctl
|
||||
-else
|
||||
- echo "Couldn't find an ndctl binary"
|
||||
- exit 1
|
||||
+if [ -z $NDCTL ]; then
|
||||
+ if [ -f "../ndctl/ndctl" ] && [ -x "../ndctl/ndctl" ]; then
|
||||
+ export NDCTL=../ndctl/ndctl
|
||||
+ elif [ -f "./ndctl/ndctl" ] && [ -x "./ndctl/ndctl" ]; then
|
||||
+ export NDCTL=./ndctl/ndctl
|
||||
+ else
|
||||
+ echo "Couldn't find an ndctl binary"
|
||||
+ exit 1
|
||||
+ fi
|
||||
fi
|
||||
|
||||
# DAXCTL
|
||||
-#
|
||||
-if [ -f "../daxctl/daxctl" ] && [ -x "../daxctl/daxctl" ]; then
|
||||
- export DAXCTL=../daxctl/daxctl
|
||||
-elif [ -f "./daxctl/daxctl" ] && [ -x "./daxctl/daxctl" ]; then
|
||||
- export DAXCTL=./daxctl/daxctl
|
||||
-else
|
||||
- echo "Couldn't find an daxctl binary"
|
||||
- exit 1
|
||||
+if [ -z $DAXCTL ]; then
|
||||
+ if [ -f "../daxctl/daxctl" ] && [ -x "../daxctl/daxctl" ]; then
|
||||
+ export DAXCTL=../daxctl/daxctl
|
||||
+ elif [ -f "./daxctl/daxctl" ] && [ -x "./daxctl/daxctl" ]; then
|
||||
+ export DAXCTL=./daxctl/daxctl
|
||||
+ else
|
||||
+ echo "Couldn't find an daxctl binary"
|
||||
+ exit 1
|
||||
+ fi
|
||||
fi
|
||||
|
||||
+if [ -z $TEST_PATH ]; then
|
||||
+ export TEST_PATH=.
|
||||
+fi
|
||||
|
||||
# NFIT_TEST_BUS[01]
|
||||
#
|
||||
diff --git a/test/dax-pmd.c b/test/dax-pmd.c
|
||||
index 7648e34..f840875 100644
|
||||
--- a/test/dax-pmd.c
|
||||
+++ b/test/dax-pmd.c
|
||||
@@ -24,7 +24,8 @@
|
||||
__func__, __LINE__, strerror(errno))
|
||||
#define faili(i) fprintf(stderr, "%s: failed at: %d: %d (%s)\n", \
|
||||
__func__, __LINE__, i, strerror(errno))
|
||||
-#define TEST_FILE "test_dax_data"
|
||||
+#define TEST_DIR "test_dax_mnt"
|
||||
+#define TEST_FILE TEST_DIR "/test_dax_data"
|
||||
|
||||
#define REGION_MEM_SIZE 4096*4
|
||||
#define REGION_PM_SIZE 4096*512
|
||||
@@ -171,8 +172,14 @@ int test_dax_directio(int dax_fd, unsigned long align, void *dax_addr, off_t off
|
||||
}
|
||||
rc = -ENXIO;
|
||||
|
||||
+ rc = mkdir(TEST_DIR, 0600);
|
||||
+ if (rc < 0 && errno != EEXIST) {
|
||||
+ faili(i);
|
||||
+ munmap(addr, 2 * align);
|
||||
+ break;
|
||||
+ }
|
||||
fd2 = open(TEST_FILE, O_CREAT|O_TRUNC|O_DIRECT|O_RDWR,
|
||||
- DEFFILEMODE);
|
||||
+ 0600);
|
||||
if (fd2 < 0) {
|
||||
faili(i);
|
||||
munmap(addr, 2*align);
|
||||
diff --git a/test/dax.sh b/test/dax.sh
|
||||
index bcdd4e9..bb9848b 100755
|
||||
--- a/test/dax.sh
|
||||
+++ b/test/dax.sh
|
||||
@@ -15,13 +15,13 @@ cleanup() {
|
||||
else
|
||||
rc=77
|
||||
fi
|
||||
- rmdir $MNT
|
||||
+ rm -rf $MNT
|
||||
exit $rc
|
||||
}
|
||||
|
||||
run_test() {
|
||||
rc=0
|
||||
- if ! trace-cmd record -e fs_dax:dax_pmd_fault_done ./dax-pmd $MNT/$FILE; then
|
||||
+ if ! trace-cmd record -e fs_dax:dax_pmd_fault_done $TEST_PATH/dax-pmd $MNT/$FILE; then
|
||||
rc=$?
|
||||
if [ "$rc" -ne 77 ] && [ "$rc" -ne 0 ]; then
|
||||
cleanup "$1"
|
||||
@@ -104,7 +104,7 @@ set -e
|
||||
mkdir -p $MNT
|
||||
trap 'err $LINENO cleanup' ERR
|
||||
|
||||
-dev=$(./dax-dev)
|
||||
+dev=$($TEST_PATH/dax-dev)
|
||||
json=$($NDCTL list -N -n $dev)
|
||||
eval $(json2var <<< "$json")
|
||||
rc=1
|
||||
diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh
|
||||
index e13453d..7f79718 100755
|
||||
--- a/test/daxdev-errors.sh
|
||||
+++ b/test/daxdev-errors.sh
|
||||
@@ -62,8 +62,8 @@ read sector len < /sys/bus/nd/devices/$region/badblocks
|
||||
echo "sector: $sector len: $len"
|
||||
|
||||
# run the daxdev-errors test
|
||||
-test -x ./daxdev-errors
|
||||
-./daxdev-errors $busdev $region
|
||||
+test -x $TEST_PATH/daxdev-errors
|
||||
+$TEST_PATH/daxdev-errors $busdev $region
|
||||
|
||||
# check badblocks, should be empty
|
||||
if read sector len < /sys/bus/platform/devices/nfit_test.0/$busdev/$region/badblocks; then
|
||||
diff --git a/test/device-dax-fio.sh b/test/device-dax-fio.sh
|
||||
index f57a9d2..c43ac05 100755
|
||||
--- a/test/device-dax-fio.sh
|
||||
+++ b/test/device-dax-fio.sh
|
||||
@@ -18,7 +18,7 @@ if ! fio --enghelp | grep -q "dev-dax"; then
|
||||
exit 77
|
||||
fi
|
||||
|
||||
-dev=$(./dax-dev)
|
||||
+dev=$($TEST_PATH/dax-dev)
|
||||
for align in 4k 2m 1g
|
||||
do
|
||||
json=$($NDCTL create-namespace -m devdax -a $align -f -e $dev)
|
||||
diff --git a/test/dm.sh b/test/dm.sh
|
||||
index 4656e5b..b780a65 100755
|
||||
--- a/test/dm.sh
|
||||
+++ b/test/dm.sh
|
||||
@@ -8,7 +8,7 @@ SKIP=77
|
||||
FAIL=1
|
||||
SUCCESS=0
|
||||
|
||||
-. ./common
|
||||
+. $(dirname $0)/common
|
||||
|
||||
MNT=test_dax_mnt
|
||||
TEST_DM_PMEM=/dev/mapper/test_pmem
|
||||
@@ -30,7 +30,7 @@ cleanup() {
|
||||
if [ -L $TEST_DM_PMEM ]; then
|
||||
dmsetup remove $TEST_DM_PMEM
|
||||
fi
|
||||
- rmdir $MNT
|
||||
+ rm -rf $MNT
|
||||
# opportunistic cleanup, not fatal if these fail
|
||||
namespaces=$($NDCTL list -N | jq -r ".[] | select(.name==\"$NAME\") | .dev")
|
||||
for i in $namespaces
|
||||
diff --git a/test/inject-smart.sh b/test/inject-smart.sh
|
||||
index 4ca83b8..8b91360 100755
|
||||
--- a/test/inject-smart.sh
|
||||
+++ b/test/inject-smart.sh
|
||||
@@ -170,7 +170,7 @@ check_prereq "jq"
|
||||
modprobe nfit_test
|
||||
rc=1
|
||||
|
||||
-jlist=$(./list-smart-dimm -b $bus)
|
||||
+jlist=$($TEST_PATH/list-smart-dimm -b $bus)
|
||||
dimm="$(jq '.[]."dev"?, ."dev"?' <<< $jlist | sort | head -1 | xargs)"
|
||||
test -n "$dimm"
|
||||
|
||||
diff --git a/test/mmap.sh b/test/mmap.sh
|
||||
index 50a1d34..760257d 100755
|
||||
--- a/test/mmap.sh
|
||||
+++ b/test/mmap.sh
|
||||
@@ -7,7 +7,7 @@
|
||||
MNT=test_mmap_mnt
|
||||
FILE=image
|
||||
DEV=""
|
||||
-TEST=./mmap
|
||||
+TEST=$TEST_PATH/mmap
|
||||
rc=77
|
||||
|
||||
cleanup() {
|
||||
@@ -17,7 +17,7 @@ cleanup() {
|
||||
else
|
||||
rc=77
|
||||
fi
|
||||
- rmdir $MNT
|
||||
+ rm -rf $MNT
|
||||
exit $rc
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ set -e
|
||||
mkdir -p $MNT
|
||||
trap 'err $LINENO cleanup' ERR
|
||||
|
||||
-dev=$(./dax-dev)
|
||||
+dev=$($TEST_PATH/dax-dev)
|
||||
json=$($NDCTL list -N -n $dev)
|
||||
eval $(json2var <<< "$json")
|
||||
DEV="/dev/${blockdev}"
|
||||
diff --git a/test/monitor.sh b/test/monitor.sh
|
||||
index 6aa4196..e58c908 100755
|
||||
--- a/test/monitor.sh
|
||||
+++ b/test/monitor.sh
|
||||
@@ -31,7 +31,7 @@ start_monitor()
|
||||
set_smart_supported_bus()
|
||||
{
|
||||
smart_supported_bus=$NFIT_TEST_BUS0
|
||||
- monitor_dimms=$(./list-smart-dimm -b $smart_supported_bus | jq -r .[0].dev)
|
||||
+ monitor_dimms=$($TEST_PATH/list-smart-dimm -b $smart_supported_bus | jq -r .[0].dev)
|
||||
if [ -z $monitor_dimms ]; then
|
||||
smart_supported_bus=$NFIT_TEST_BUS1
|
||||
fi
|
||||
@@ -39,14 +39,14 @@ set_smart_supported_bus()
|
||||
|
||||
get_monitor_dimm()
|
||||
{
|
||||
- jlist=$(./list-smart-dimm -b $smart_supported_bus $1)
|
||||
+ jlist=$($TEST_PATH/list-smart-dimm -b $smart_supported_bus $1)
|
||||
monitor_dimms=$(jq '.[]."dev"?, ."dev"?' <<<$jlist | sort | uniq | xargs)
|
||||
echo $monitor_dimms
|
||||
}
|
||||
|
||||
call_notify()
|
||||
{
|
||||
- ./smart-notify $smart_supported_bus
|
||||
+ $TEST_PATH/smart-notify $smart_supported_bus
|
||||
sync; sleep 3
|
||||
}
|
||||
|
||||
diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh
|
||||
index 2065780..9a59c25 100755
|
||||
--- a/test/pmem-errors.sh
|
||||
+++ b/test/pmem-errors.sh
|
||||
@@ -10,14 +10,12 @@ rc=77
|
||||
|
||||
cleanup()
|
||||
{
|
||||
- rm -f $FILE
|
||||
- rm -f $MNT/$FILE
|
||||
if [ -n "$blockdev" ]; then
|
||||
umount /dev/$blockdev
|
||||
else
|
||||
rc=77
|
||||
fi
|
||||
- rmdir $MNT
|
||||
+ rm -rf $MNT
|
||||
}
|
||||
|
||||
check_min_kver "4.7" || do_skip "may lack dax error handling"
|
||||
@@ -82,8 +80,8 @@ echo $start_sect 8 > /sys/block/$blockdev/badblocks
|
||||
dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1 && err $LINENO || true
|
||||
|
||||
# run the dax-errors test
|
||||
-test -x ./dax-errors
|
||||
-./dax-errors $MNT/$FILE
|
||||
+test -x $TEST_PATH/dax-errors
|
||||
+$TEST_PATH/dax-errors $MNT/$FILE
|
||||
|
||||
# TODO: disable this check till we have clear-on-write in the kernel
|
||||
#if read sector len < /sys/block/$blockdev/badblocks; then
|
||||
diff --git a/test/sub-section.sh b/test/sub-section.sh
|
||||
index 92ae816..77b9633 100755
|
||||
--- a/test/sub-section.sh
|
||||
+++ b/test/sub-section.sh
|
||||
@@ -8,7 +8,7 @@ SKIP=77
|
||||
FAIL=1
|
||||
SUCCESS=0
|
||||
|
||||
-. ./common
|
||||
+. $(dirname $0)/common
|
||||
|
||||
check_min_kver "5.3" || do_skip "may lack align sub-section hotplug support"
|
||||
|
||||
@@ -30,7 +30,7 @@ cleanup() {
|
||||
if mountpoint -q $MNT; then
|
||||
umount $MNT
|
||||
fi
|
||||
- rmdir $MNT
|
||||
+ rm -rf $MNT
|
||||
# opportunistic cleanup, not fatal if these fail
|
||||
namespaces=$($NDCTL list -N | jq -r ".[] | select(.name==\"$NAME\") | .dev")
|
||||
for i in $namespaces
|
||||
diff --git a/test/track-uuid.sh b/test/track-uuid.sh
|
||||
index 3bacd2c..a967d0e 100755
|
||||
--- a/test/track-uuid.sh
|
||||
+++ b/test/track-uuid.sh
|
||||
@@ -5,7 +5,7 @@
|
||||
blockdev=""
|
||||
rc=77
|
||||
|
||||
-. ./common
|
||||
+. $(dirname $0)/common
|
||||
|
||||
set -e
|
||||
trap 'err $LINENO' ERR
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,28 @@
|
||||
From 7912cb0d19b5d17321439d118d41e57236b5484b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:47 -0800
|
||||
Subject: [PATCH 081/217] ndctl: Drop executable bit for bash-completion script
|
||||
|
||||
The rpm build process warns:
|
||||
|
||||
*** WARNING: ./usr/share/bash-completion/completions/ndctl is executable but has no shebang, removing executable bit
|
||||
|
||||
Clear the unnecessary executable bit since completion helpers are sourced,
|
||||
not executed.
|
||||
|
||||
Link: https://lore.kernel.org/r/164141836772.3990253.4996882214531720931.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
contrib/ndctl | 0
|
||||
1 file changed, 0 insertions(+), 0 deletions(-)
|
||||
mode change 100755 => 100644 contrib/ndctl
|
||||
|
||||
diff --git a/contrib/ndctl b/contrib/ndctl
|
||||
old mode 100755
|
||||
new mode 100644
|
||||
--
|
||||
2.27.0
|
||||
|
1577
SOURCES/0082-build-Add-meson-build-infrastructure.patch
Normal file
1577
SOURCES/0082-build-Add-meson-build-infrastructure.patch
Normal file
File diff suppressed because it is too large
Load Diff
223
SOURCES/0083-build-Add-meson-rpmbuild-support.patch
Normal file
223
SOURCES/0083-build-Add-meson-rpmbuild-support.patch
Normal file
@ -0,0 +1,223 @@
|
||||
From 8b5b941093521dd18fcc99659b3e3b1b9e9456b7 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Wed, 5 Jan 2022 13:32:58 -0800
|
||||
Subject: [PATCH 083/217] build: Add meson rpmbuild support
|
||||
|
||||
Beyond being a prerequisite for removing autotools support, this capability
|
||||
served as validation that the meson conversion generated all the same files
|
||||
as autotools and installed them to the same expected locations.
|
||||
|
||||
The procedure to use the rpmbuild.sh script is:
|
||||
|
||||
meson setup build
|
||||
meson compile -C build rhel/ndctl.spec
|
||||
./rpmbuild.sh build/rhel/ndctl.spec
|
||||
|
||||
Link: https://lore.kernel.org/r/164141837841.3990253.11379060834465142446.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Tested-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Tested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.gitignore | 2 +-
|
||||
Makefile.am | 2 ++
|
||||
meson.build | 6 ++++++
|
||||
ndctl.spec.in | 23 +++++++++++++++++++++++
|
||||
rhel/meson.build | 23 +++++++++++++++++++++++
|
||||
rpmbuild.sh | 5 ++++-
|
||||
sles/meson.build | 36 ++++++++++++++++++++++++++++++++++++
|
||||
7 files changed, 95 insertions(+), 2 deletions(-)
|
||||
create mode 100644 rhel/meson.build
|
||||
create mode 100644 sles/meson.build
|
||||
|
||||
diff -up ndctl-71.1/.gitignore.orig ndctl-71.1/.gitignore
|
||||
--- ndctl-71.1/.gitignore.orig 2022-10-07 16:34:40.712445112 -0400
|
||||
+++ ndctl-71.1/.gitignore 2022-10-07 16:34:52.832486377 -0400
|
||||
@@ -35,7 +35,7 @@ daxctl/lib/libdaxctl.pc
|
||||
ndctl/config.h
|
||||
ndctl/lib/libndctl.pc
|
||||
ndctl/ndctl
|
||||
-rhel/
|
||||
+rhel/ndctl.spec
|
||||
sles/ndctl.spec
|
||||
version.m4
|
||||
*.swp
|
||||
diff -up ndctl-71.1/Makefile.am.orig ndctl-71.1/Makefile.am
|
||||
--- ndctl-71.1/Makefile.am.orig 2022-10-07 16:34:40.687445027 -0400
|
||||
+++ ndctl-71.1/Makefile.am 2022-10-07 16:34:52.832486377 -0400
|
||||
@@ -22,6 +22,7 @@ noinst_SCRIPTS = rhel/ndctl.spec sles/nd
|
||||
CLEANFILES += $(noinst_SCRIPTS)
|
||||
|
||||
do_rhel_subst = sed -e 's,VERSION,$(VERSION),g' \
|
||||
+ -e 's,MESON,0,g' \
|
||||
-e 's,DAX_DNAME,daxctl-devel,g' \
|
||||
-e 's,CXL_DNAME,cxl-devel,g' \
|
||||
-e 's,DNAME,ndctl-devel,g' \
|
||||
@@ -31,6 +32,7 @@ do_rhel_subst = sed -e 's,VERSION,$(VERS
|
||||
-e 's,LNAME,ndctl-libs,g'
|
||||
|
||||
do_sles_subst = sed -e 's,VERSION,$(VERSION),g' \
|
||||
+ -e 's,MESON,0,g' \
|
||||
-e 's,DAX_DNAME,libdaxctl-devel,g' \
|
||||
-e 's,CXL_DNAME,libcxl-devel,g' \
|
||||
-e 's,DNAME,libndctl-devel,g' \
|
||||
diff -up ndctl-71.1/meson.build.orig ndctl-71.1/meson.build
|
||||
--- ndctl-71.1/meson.build.orig 2022-10-07 16:34:40.715445122 -0400
|
||||
+++ ndctl-71.1/meson.build 2022-10-07 16:34:52.833486380 -0400
|
||||
@@ -278,3 +278,9 @@ if get_option('docs').enabled()
|
||||
endif
|
||||
subdir('test')
|
||||
subdir('contrib')
|
||||
+
|
||||
+# only support spec file generation from git builds
|
||||
+if version_tag == ''
|
||||
+ subdir('rhel')
|
||||
+ subdir('sles')
|
||||
+endif
|
||||
diff -up ndctl-71.1/ndctl.spec.in.orig ndctl-71.1/ndctl.spec.in
|
||||
--- ndctl-71.1/ndctl.spec.in.orig 2022-10-07 16:34:40.645444884 -0400
|
||||
+++ ndctl-71.1/ndctl.spec.in 2022-10-07 16:34:52.833486380 -0400
|
||||
@@ -6,14 +6,20 @@ License: GPLv2
|
||||
Url: https://github.com/pmem/ndctl
|
||||
Source0: https://github.com/pmem/%{name}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
|
||||
|
||||
+%define with_meson MESON
|
||||
Requires: LNAME%{?_isa} = %{version}-%{release}
|
||||
Requires: DAX_LNAME%{?_isa} = %{version}-%{release}
|
||||
Requires: CXL_LNAME%{?_isa} = %{version}-%{release}
|
||||
BuildRequires: autoconf
|
||||
%if 0%{?rhel} < 9
|
||||
BuildRequires: asciidoc
|
||||
+%if !%{with_meson}
|
||||
%define asciidoc --disable-asciidoctor
|
||||
+%endif
|
||||
%else
|
||||
+%if %{with_meson}
|
||||
+%define asciidoctor -Dasciidoctor=enabled
|
||||
+%endif
|
||||
BuildRequires: rubygem-asciidoctor
|
||||
%endif
|
||||
BuildRequires: xmlto
|
||||
@@ -28,6 +34,10 @@ BuildRequires: pkgconfig(bash-completion
|
||||
BuildRequires: pkgconfig(systemd)
|
||||
BuildRequires: keyutils-libs-devel
|
||||
|
||||
+%if %{with_meson}
|
||||
+BuildRequires: meson
|
||||
+%endif
|
||||
+
|
||||
%description
|
||||
Utility library for managing the "libnvdimm" subsystem. The "libnvdimm"
|
||||
subsystem defines a kernel device model and control message interface for
|
||||
@@ -115,17 +125,30 @@ libcxl is a library for enumerating and
|
||||
%setup -q ndctl-%{version}
|
||||
|
||||
%build
|
||||
+%if %{with_meson}
|
||||
+%meson %{?asciidoctor} -Dversion-tag=%{version}
|
||||
+%meson_build
|
||||
+%else
|
||||
echo %{version} > version
|
||||
./autogen.sh
|
||||
%configure --disable-static --disable-silent-rules %{?asciidoc}
|
||||
make %{?_smp_mflags}
|
||||
+%endif
|
||||
|
||||
%install
|
||||
+%if %{with_meson}
|
||||
+%meson_install
|
||||
+%else
|
||||
%make_install
|
||||
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
|
||||
+%endif
|
||||
|
||||
%check
|
||||
+%if %{with_meson}
|
||||
+%meson_test
|
||||
+%else
|
||||
make check
|
||||
+%endif
|
||||
|
||||
%ldconfig_scriptlets -n LNAME
|
||||
|
||||
diff -up ndctl-71.1/rhel/meson.build.orig ndctl-71.1/rhel/meson.build
|
||||
--- ndctl-71.1/rhel/meson.build.orig 2022-10-07 16:34:52.834486384 -0400
|
||||
+++ ndctl-71.1/rhel/meson.build 2022-10-07 16:34:52.834486384 -0400
|
||||
@@ -0,0 +1,23 @@
|
||||
+rhel_spec1 = vcs_tag(
|
||||
+ input : '../ndctl.spec.in',
|
||||
+ output : 'ndctl.spec.in',
|
||||
+ command: vcs_tagger,
|
||||
+ replace_string : 'VERSION',
|
||||
+)
|
||||
+
|
||||
+rhel_spec2 = custom_target('ndctl.spec',
|
||||
+ command : [
|
||||
+ 'sed', '-e', 's,MESON,1,g',
|
||||
+ '-e', 's,DAX_DNAME,daxctl-devel,g',
|
||||
+ '-e', 's,CXL_DNAME,cxl-devel,g',
|
||||
+ '-e', 's,DNAME,ndctl-devel,g',
|
||||
+ '-e', '/^%defattr.*/d',
|
||||
+ '-e', 's,DAX_LNAME,daxctl-libs,g',
|
||||
+ '-e', 's,CXL_LNAME,cxl-libs,g',
|
||||
+ '-e', 's,LNAME,ndctl-libs,g',
|
||||
+ '@INPUT@'
|
||||
+ ],
|
||||
+ input : rhel_spec1,
|
||||
+ output : 'ndctl.spec',
|
||||
+ capture : true,
|
||||
+)
|
||||
diff -up ndctl-71.1/rpmbuild.sh.orig ndctl-71.1/rpmbuild.sh
|
||||
--- ndctl-71.1/rpmbuild.sh.orig 2020-12-22 16:44:57.000000000 -0500
|
||||
+++ ndctl-71.1/rpmbuild.sh 2022-10-07 16:34:52.834486384 -0400
|
||||
@@ -1,6 +1,9 @@
|
||||
#!/bin/bash
|
||||
+
|
||||
+spec=${1:-$(dirname $0)/rhel/ndctl.spec)}
|
||||
+
|
||||
pushd $(dirname $0) >/dev/null
|
||||
[ ! -d ~/rpmbuild/SOURCES ] && echo "rpmdev tree not found" && exit 1
|
||||
./make-git-snapshot.sh
|
||||
popd > /dev/null
|
||||
-rpmbuild -ba $(dirname $0)/rhel/ndctl.spec
|
||||
+rpmbuild --nocheck -ba $spec
|
||||
diff -up ndctl-71.1/sles/meson.build.orig ndctl-71.1/sles/meson.build
|
||||
--- ndctl-71.1/sles/meson.build.orig 2022-10-07 16:34:52.836486391 -0400
|
||||
+++ ndctl-71.1/sles/meson.build 2022-10-07 16:34:52.835486387 -0400
|
||||
@@ -0,0 +1,36 @@
|
||||
+sles_spec1 = vcs_tag(
|
||||
+ input : '../ndctl.spec.in',
|
||||
+ output : 'ndctl.spec.sles.in',
|
||||
+ command: vcs_tagger,
|
||||
+ replace_string : 'VERSION',
|
||||
+)
|
||||
+
|
||||
+header = files('header')
|
||||
+
|
||||
+sles_spec2 = custom_target('ndctl.spec.in',
|
||||
+ command : [
|
||||
+ 'cat', header, '@INPUT@',
|
||||
+ ],
|
||||
+ input : sles_spec1,
|
||||
+ output : 'ndctl.spec.in',
|
||||
+ capture : true,
|
||||
+)
|
||||
+
|
||||
+sles_spec3 = custom_target('ndctl.spec',
|
||||
+ command : [
|
||||
+ 'sed', '-e', 's,MESON,1,g',
|
||||
+ '-e', 's,DAX_DNAME,libdaxctl-devel,g',
|
||||
+ '-e', 's,CXL_DNAME,libcxl-devel,g',
|
||||
+ '-e', 's,DNAME,libndctl-devel,g',
|
||||
+ '-e', 's,%license,%doc,g',
|
||||
+ '-e', 's,\(^License:.*GPL\)v2,\1-2.0,g',
|
||||
+ '-e', 's,DAX_LNAME,libdaxctl@0@,g'.format(LIBDAXCTL_CURRENT - LIBDAXCTL_AGE),
|
||||
+ '-e', 's,CXL_LNAME,libcxl@0@,g'.format(LIBCXL_CURRENT - LIBCXL_AGE),
|
||||
+ '-e', 's,LNAME,libndctl@0@,g'.format(LIBNDCTL_CURRENT - LIBNDCTL_AGE),
|
||||
+ '@INPUT@'
|
||||
+ ],
|
||||
+
|
||||
+ input : sles_spec2,
|
||||
+ output : 'ndctl.spec',
|
||||
+ capture : true,
|
||||
+)
|
1423
SOURCES/0084-ndctl-Jettison-autotools.patch
Normal file
1423
SOURCES/0084-ndctl-Jettison-autotools.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
||||
From 3a8d6e4bc90e899f751b881dc949e79daeeb04bb Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Fri, 7 Jan 2022 11:31:06 -0800
|
||||
Subject: [PATCH 085/217] ndctl/build: Default asciidoctor to enabled
|
||||
|
||||
The autotools build infra previously defaulted asciidoctor to enabled, do
|
||||
the same for Meson.
|
||||
|
||||
Link: https://lore.kernel.org/r/164158386600.302694.5479584050156277551.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Reported-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
meson_options.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index 95312bf..aa4a6dc 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -1,7 +1,7 @@
|
||||
option('version-tag', type : 'string',
|
||||
description : 'override the git version string')
|
||||
option('docs', type : 'feature', value : 'enabled')
|
||||
-option('asciidoctor', type : 'feature', value : 'disabled')
|
||||
+option('asciidoctor', type : 'feature', value : 'enabled')
|
||||
option('systemd', type : 'feature', value : 'enabled')
|
||||
option('keyutils', type : 'feature', value : 'enabled',
|
||||
description : 'enable nvdimm device passphrase management')
|
||||
--
|
||||
2.27.0
|
||||
|
88
SOURCES/0086-ndctl-update-README.md-for-meson-build.patch
Normal file
88
SOURCES/0086-ndctl-update-README.md-for-meson-build.patch
Normal file
@ -0,0 +1,88 @@
|
||||
From 351badda9e5b6454e56f31992e9325c4656680bd Mon Sep 17 00:00:00 2001
|
||||
From: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Date: Fri, 14 Jan 2022 18:32:29 -0700
|
||||
Subject: [PATCH 086/217] ndctl: update README.md for meson build
|
||||
|
||||
Update the README to replace the autotools build and test instructions
|
||||
with meson equivalents. Also provide an example for setting meson
|
||||
configuration options by illustrating the destructive unit tests use
|
||||
case.
|
||||
|
||||
Link: https://lore.kernel.org/r/20220115013229.1604139-1-vishal.l.verma@intel.com
|
||||
Cc: Dan Williams <dan.j.williams@intel.com>
|
||||
Reported-by: Alison Schofield <alison.schofield@intel.com>
|
||||
Reported-by: Jane Chu <jane.chu@oracle.com>
|
||||
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
README.md | 33 ++++++++++++++++++++++-----------
|
||||
1 file changed, 22 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/README.md b/README.md
|
||||
index 6f36a6d..f3fe65b 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -9,11 +9,14 @@ Build
|
||||
=====
|
||||
|
||||
```
|
||||
-./autogen.sh
|
||||
-./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
|
||||
-make
|
||||
-make check
|
||||
-sudo make install
|
||||
+meson setup build;
|
||||
+meson compile -C build;
|
||||
+```
|
||||
+
|
||||
+Optionally, to install:
|
||||
+
|
||||
+```
|
||||
+meson install -C build
|
||||
```
|
||||
|
||||
There are a number of packages required for the build steps that may not
|
||||
@@ -34,7 +37,7 @@ https://nvdimm.wiki.kernel.org/start
|
||||
|
||||
Unit Tests
|
||||
==========
|
||||
-The unit tests run by `make check` require the nfit_test.ko module to be
|
||||
+The unit tests run by `meson test` require the nfit_test.ko module to be
|
||||
loaded. To build and install nfit_test.ko:
|
||||
|
||||
1. Obtain the kernel source. For example,
|
||||
@@ -78,8 +81,16 @@ loaded. To build and install nfit_test.ko:
|
||||
sudo make modules_install
|
||||
```
|
||||
|
||||
-1. Now run `make check` in the ndctl source directory, or `ndctl test`,
|
||||
- if ndctl was built with `--enable-test`.
|
||||
+1. Now run `meson test -C build` in the ndctl source directory, or `ndctl test`,
|
||||
+ if ndctl was built with `-Dtest=enabled` as a configuration option to meson.
|
||||
+
|
||||
+1. To run the 'destructive' set of tests that may clobber existing pmem
|
||||
+ configurations and data, configure meson with the destructive option after the
|
||||
+ `meson setup` step:
|
||||
+
|
||||
+ ```
|
||||
+ meson configure -Dtest=enabled -Ddestructive=enabled build;
|
||||
+ ```
|
||||
|
||||
Troubleshooting
|
||||
===============
|
||||
@@ -87,9 +98,9 @@ Troubleshooting
|
||||
The unit tests will validate that the environment is set up correctly
|
||||
before they try to run. If the platform is misconfigured, i.e. the unit
|
||||
test modules are not available, or the test versions of the modules are
|
||||
-superseded by the "in-tree/production" version of the modules `make
|
||||
-check` will skip tests and report a message like the following in
|
||||
-test/test-suite.log:
|
||||
+superseded by the "in-tree/production" version of the modules `meson
|
||||
+test` will skip tests and report a message like the following in
|
||||
+`build/meson-logs/testlog.txt`
|
||||
|
||||
```
|
||||
SKIP: libndctl
|
||||
--
|
||||
2.27.0
|
||||
|
122
SOURCES/0087-test-Add-suite-identifiers-to-tests.patch
Normal file
122
SOURCES/0087-test-Add-suite-identifiers-to-tests.patch
Normal file
@ -0,0 +1,122 @@
|
||||
From a61377ecf015929de27a665d0b5c937315f9e4aa Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:51:54 -0800
|
||||
Subject: [PATCH 087/217] test: Add 'suite' identifiers to tests
|
||||
|
||||
In preparation for adding CXL tests, and in anticipation of wanting to only
|
||||
run the CXL tests, label each test with a suite id.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298551461.3021641.4591877842309963514.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
test/meson.build | 73 ++++++++++++++++++++++++------------------------
|
||||
1 file changed, 37 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/test/meson.build b/test/meson.build
|
||||
index 94287aa..07a5bb6 100644
|
||||
--- a/test/meson.build
|
||||
+++ b/test/meson.build
|
||||
@@ -152,28 +152,28 @@ pfn_meta_errors = find_program('pfn-meta-errors.sh')
|
||||
track_uuid = find_program('track-uuid.sh')
|
||||
|
||||
tests = [
|
||||
- [ 'libndctl', libndctl ],
|
||||
- [ 'dsm-fail', dsm_fail ],
|
||||
- [ 'create.sh', create ],
|
||||
- [ 'clear.sh', clear ],
|
||||
- [ 'pmem-errors.sh', pmem_errors ],
|
||||
- [ 'daxdev-errors.sh', daxdev_errors_sh ],
|
||||
- [ 'multi-dax.sh', multi_dax ],
|
||||
- [ 'btt-check.sh', btt_check ],
|
||||
- [ 'label-compat.sh', label_compat ],
|
||||
- [ 'sector-mode.sh', sector_mode ],
|
||||
- [ 'inject-error.sh', inject_error ],
|
||||
- [ 'btt-errors.sh', btt_errors ],
|
||||
- [ 'hugetlb', hugetlb ],
|
||||
- [ 'btt-pad-compat.sh', btt_pad_compat ],
|
||||
- [ 'firmware-update.sh', firmware_update ],
|
||||
- [ 'ack-shutdown-count-set', ack_shutdown_count ],
|
||||
- [ 'rescan-partitions.sh', rescan_partitions ],
|
||||
- [ 'inject-smart.sh', inject_smart ],
|
||||
- [ 'monitor.sh', monitor ],
|
||||
- [ 'max_extent_ns', max_extent ],
|
||||
- [ 'pfn-meta-errors.sh', pfn_meta_errors ],
|
||||
- [ 'track-uuid.sh', track_uuid ],
|
||||
+ [ 'libndctl', libndctl, 'ndctl' ],
|
||||
+ [ 'dsm-fail', dsm_fail, 'ndctl' ],
|
||||
+ [ 'create.sh', create, 'ndctl' ],
|
||||
+ [ 'clear.sh', clear, 'ndctl' ],
|
||||
+ [ 'pmem-errors.sh', pmem_errors, 'ndctl' ],
|
||||
+ [ 'daxdev-errors.sh', daxdev_errors_sh, 'dax' ],
|
||||
+ [ 'multi-dax.sh', multi_dax, 'dax' ],
|
||||
+ [ 'btt-check.sh', btt_check, 'ndctl' ],
|
||||
+ [ 'label-compat.sh', label_compat, 'ndctl' ],
|
||||
+ [ 'sector-mode.sh', sector_mode, 'ndctl' ],
|
||||
+ [ 'inject-error.sh', inject_error, 'ndctl' ],
|
||||
+ [ 'btt-errors.sh', btt_errors, 'ndctl' ],
|
||||
+ [ 'hugetlb', hugetlb, 'ndctl' ],
|
||||
+ [ 'btt-pad-compat.sh', btt_pad_compat, 'ndctl' ],
|
||||
+ [ 'firmware-update.sh', firmware_update, 'ndctl' ],
|
||||
+ [ 'ack-shutdown-count-set', ack_shutdown_count, 'ndctl' ],
|
||||
+ [ 'rescan-partitions.sh', rescan_partitions, 'ndctl' ],
|
||||
+ [ 'inject-smart.sh', inject_smart, 'ndctl' ],
|
||||
+ [ 'monitor.sh', monitor, 'ndctl' ],
|
||||
+ [ 'max_extent_ns', max_extent, 'ndctl' ],
|
||||
+ [ 'pfn-meta-errors.sh', pfn_meta_errors, 'ndctl' ],
|
||||
+ [ 'track-uuid.sh', track_uuid, 'ndctl' ],
|
||||
]
|
||||
|
||||
if get_option('destructive').enabled()
|
||||
@@ -188,26 +188,26 @@ if get_option('destructive').enabled()
|
||||
mmap_test = find_program('mmap.sh')
|
||||
|
||||
tests += [
|
||||
- [ 'pmem-ns', pmem_ns ],
|
||||
- [ 'sub-section.sh', sub_section ],
|
||||
- [ 'dax-dev', dax_dev ],
|
||||
- [ 'dax-ext4.sh', dax_ext4 ],
|
||||
- [ 'dax-xfs.sh', dax_xfs ],
|
||||
- [ 'align.sh', align ],
|
||||
- [ 'device-dax', device_dax ],
|
||||
- [ 'revoke-devmem', revoke_devmem ],
|
||||
- [ 'device-dax-fio.sh', device_dax_fio ],
|
||||
- [ 'daxctl-devices.sh', daxctl_devices ],
|
||||
- [ 'daxctl-create.sh', daxctl_create ],
|
||||
- [ 'dm.sh', dm ],
|
||||
- [ 'mmap.sh', mmap_test ],
|
||||
+ [ 'pmem-ns', pmem_ns, 'ndctl' ],
|
||||
+ [ 'sub-section.sh', sub_section, 'dax' ],
|
||||
+ [ 'dax-dev', dax_dev, 'dax' ],
|
||||
+ [ 'dax-ext4.sh', dax_ext4, 'dax' ],
|
||||
+ [ 'dax-xfs.sh', dax_xfs, 'dax' ],
|
||||
+ [ 'align.sh', align, 'ndctl' ],
|
||||
+ [ 'device-dax', device_dax, 'dax' ],
|
||||
+ [ 'revoke-devmem', revoke_devmem, 'dax' ],
|
||||
+ [ 'device-dax-fio.sh', device_dax_fio, 'dax' ],
|
||||
+ [ 'daxctl-devices.sh', daxctl_devices, 'dax' ],
|
||||
+ [ 'daxctl-create.sh', daxctl_create, 'dax' ],
|
||||
+ [ 'dm.sh', dm, 'dax' ],
|
||||
+ [ 'mmap.sh', mmap_test, 'dax' ],
|
||||
]
|
||||
endif
|
||||
|
||||
if get_option('keyutils').enabled()
|
||||
security = find_program('security.sh')
|
||||
tests += [
|
||||
- [ 'security.sh', security ]
|
||||
+ [ 'security.sh', security, 'ndctl' ]
|
||||
]
|
||||
endif
|
||||
|
||||
@@ -226,6 +226,7 @@ foreach t : tests
|
||||
dax_dev,
|
||||
mmap,
|
||||
],
|
||||
+ suite: t[2],
|
||||
timeout : 0,
|
||||
env : [
|
||||
'NDCTL=@0@'.format(ndctl_tool.full_path()),
|
||||
--
|
||||
2.27.0
|
||||
|
287
SOURCES/0088-ndctl-Rename-util_filter-to-ndctl_filter.patch
Normal file
287
SOURCES/0088-ndctl-Rename-util_filter-to-ndctl_filter.patch
Normal file
@ -0,0 +1,287 @@
|
||||
From d7c5fa695a91d66485ca1febd6f29c3a483e20f6 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:00 -0800
|
||||
Subject: [PATCH 088/217] ndctl: Rename util_filter to ndctl_filter
|
||||
|
||||
In preparation for introducing a cxl_filter_walk() implementation rename
|
||||
the current filter_walk infrastructure with an ndctl_ prefix.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298552014.3021641.16369576632179722489.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/filter.c | 4 ++--
|
||||
ndctl/filter.h | 21 +++++++++++----------
|
||||
ndctl/list.c | 14 +++++++-------
|
||||
ndctl/monitor.c | 12 ++++++------
|
||||
test/list-smart-dimm.c | 12 ++++++------
|
||||
5 files changed, 32 insertions(+), 31 deletions(-)
|
||||
|
||||
diff -up ndctl-71.1/ndctl/filter.c.orig ndctl-71.1/ndctl/filter.c
|
||||
--- ndctl-71.1/ndctl/filter.c.orig 2022-10-07 17:54:40.799788014 -0400
|
||||
+++ ndctl-71.1/ndctl/filter.c 2022-10-07 17:54:52.592828166 -0400
|
||||
@@ -338,8 +338,8 @@ const char *util_nsmode_name(enum ndctl_
|
||||
return modes[mode];
|
||||
}
|
||||
|
||||
-int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
|
||||
- struct util_filter_params *param)
|
||||
+int ndctl_filter_walk(struct ndctl_ctx *ctx, struct ndctl_filter_ctx *fctx,
|
||||
+ struct ndctl_filter_params *param)
|
||||
{
|
||||
struct ndctl_bus *bus;
|
||||
unsigned int type = 0;
|
||||
diff -up ndctl-71.1/ndctl/filter.h.orig ndctl-71.1/ndctl/filter.h
|
||||
--- ndctl-71.1/ndctl/filter.h.orig 2022-10-07 17:54:40.799788014 -0400
|
||||
+++ ndctl-71.1/ndctl/filter.h 2022-10-07 17:54:52.593828169 -0400
|
||||
@@ -31,7 +31,7 @@ const char *util_nsmode_name(enum ndctl_
|
||||
|
||||
struct json_object;
|
||||
|
||||
-/* json object hierarchy for the util_filter_walk() performed by cmd_list() */
|
||||
+/* json object hierarchy for the ndctl_filter_walk() performed by cmd_list() */
|
||||
struct list_filter_arg {
|
||||
struct json_object *jnamespaces;
|
||||
struct json_object *jregions;
|
||||
@@ -50,19 +50,20 @@ struct monitor_filter_arg {
|
||||
};
|
||||
|
||||
/*
|
||||
- * struct util_filter_ctx - control and callbacks for util_filter_walk()
|
||||
+ * struct ndctl_filter_ctx - control and callbacks for ndctl_filter_walk()
|
||||
* ->filter_bus() and ->filter_region() return bool because the
|
||||
* child-object filter routines can not be called if the parent context
|
||||
* is not established. ->filter_dimm() and ->filter_namespace() are leaf
|
||||
* objects, so no child dependencies to check.
|
||||
*/
|
||||
-struct util_filter_ctx {
|
||||
- bool (*filter_bus)(struct ndctl_bus *bus, struct util_filter_ctx *ctx);
|
||||
- void (*filter_dimm)(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx);
|
||||
+struct ndctl_filter_ctx {
|
||||
+ bool (*filter_bus)(struct ndctl_bus *bus, struct ndctl_filter_ctx *ctx);
|
||||
+ void (*filter_dimm)(struct ndctl_dimm *dimm,
|
||||
+ struct ndctl_filter_ctx *ctx);
|
||||
bool (*filter_region)(struct ndctl_region *region,
|
||||
- struct util_filter_ctx *ctx);
|
||||
+ struct ndctl_filter_ctx *ctx);
|
||||
void (*filter_namespace)(struct ndctl_namespace *ndns,
|
||||
- struct util_filter_ctx *ctx);
|
||||
+ struct ndctl_filter_ctx *ctx);
|
||||
union {
|
||||
void *arg;
|
||||
struct list_filter_arg *list;
|
||||
@@ -70,7 +71,7 @@ struct util_filter_ctx {
|
||||
};
|
||||
};
|
||||
|
||||
-struct util_filter_params {
|
||||
+struct ndctl_filter_params {
|
||||
const char *bus;
|
||||
const char *region;
|
||||
const char *type;
|
||||
@@ -81,6 +82,6 @@ struct util_filter_params {
|
||||
};
|
||||
|
||||
struct ndctl_ctx;
|
||||
-int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
|
||||
- struct util_filter_params *param);
|
||||
+int ndctl_filter_walk(struct ndctl_ctx *ctx, struct ndctl_filter_ctx *fctx,
|
||||
+ struct ndctl_filter_params *param);
|
||||
#endif /* _NDCTL_UTIL_FILTER_H_ */
|
||||
diff -up ndctl-71.1/ndctl/list.c.orig ndctl-71.1/ndctl/list.c
|
||||
--- ndctl-71.1/ndctl/list.c.orig 2022-10-07 17:54:40.806788038 -0400
|
||||
+++ ndctl-71.1/ndctl/list.c 2022-10-07 17:54:52.593828169 -0400
|
||||
@@ -55,7 +55,7 @@ static unsigned long listopts_to_flags(v
|
||||
return flags;
|
||||
}
|
||||
|
||||
-static struct util_filter_params param;
|
||||
+static struct ndctl_filter_params param;
|
||||
|
||||
static int did_fail;
|
||||
|
||||
@@ -234,7 +234,7 @@ static struct json_object *region_to_jso
|
||||
}
|
||||
|
||||
static void filter_namespace(struct ndctl_namespace *ndns,
|
||||
- struct util_filter_ctx *ctx)
|
||||
+ struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
struct json_object *jndns;
|
||||
struct list_filter_arg *lfa = ctx->list;
|
||||
@@ -272,7 +272,7 @@ static void filter_namespace(struct ndct
|
||||
}
|
||||
|
||||
static bool filter_region(struct ndctl_region *region,
|
||||
- struct util_filter_ctx *ctx)
|
||||
+ struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
struct list_filter_arg *lfa = ctx->list;
|
||||
struct json_object *jbus = lfa->jbus;
|
||||
@@ -318,7 +318,7 @@ static bool filter_region(struct ndctl_r
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx)
|
||||
+static void filter_dimm(struct ndctl_dimm *dimm, struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
struct list_filter_arg *lfa = ctx->list;
|
||||
struct json_object *jdimm;
|
||||
@@ -367,7 +367,7 @@ static void filter_dimm(struct ndctl_dim
|
||||
json_object_array_add(lfa->jdimms, jdimm);
|
||||
}
|
||||
|
||||
-static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *ctx)
|
||||
+static bool filter_bus(struct ndctl_bus *bus, struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
struct list_filter_arg *lfa = ctx->list;
|
||||
|
||||
@@ -489,7 +489,7 @@ int cmd_list(int argc, const char **argv
|
||||
NULL
|
||||
};
|
||||
bool lint = !!secure_getenv("NDCTL_LIST_LINT");
|
||||
- struct util_filter_ctx fctx = { 0 };
|
||||
+ struct ndctl_filter_ctx fctx = { 0 };
|
||||
struct list_filter_arg lfa = { 0 };
|
||||
int i, rc;
|
||||
|
||||
@@ -544,7 +544,7 @@ int cmd_list(int argc, const char **argv
|
||||
fctx.list = &lfa;
|
||||
lfa.flags = listopts_to_flags();
|
||||
|
||||
- rc = util_filter_walk(ctx, &fctx, ¶m);
|
||||
+ rc = ndctl_filter_walk(ctx, &fctx, ¶m);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
diff -up ndctl-71.1/ndctl/monitor.c.orig ndctl-71.1/ndctl/monitor.c
|
||||
--- ndctl-71.1/ndctl/monitor.c.orig 2022-10-07 17:54:40.824788100 -0400
|
||||
+++ ndctl-71.1/ndctl/monitor.c 2022-10-07 17:55:08.025880711 -0400
|
||||
@@ -48,7 +48,7 @@ struct monitor_dimm {
|
||||
struct list_node list;
|
||||
};
|
||||
|
||||
-static struct util_filter_params param;
|
||||
+static struct ndctl_filter_params param;
|
||||
|
||||
static int did_fail;
|
||||
|
||||
@@ -263,12 +263,12 @@ out:
|
||||
}
|
||||
|
||||
static bool filter_region(struct ndctl_region *region,
|
||||
- struct util_filter_ctx *fctx)
|
||||
+ struct ndctl_filter_ctx *fctx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *fctx)
|
||||
+static void filter_dimm(struct ndctl_dimm *dimm, struct ndctl_filter_ctx *fctx)
|
||||
{
|
||||
struct monitor_dimm *mdimm;
|
||||
struct monitor_filter_arg *mfa = fctx->monitor;
|
||||
@@ -316,7 +316,7 @@ static void filter_dimm(struct ndctl_dim
|
||||
return;
|
||||
}
|
||||
|
||||
-static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *fctx)
|
||||
+static bool filter_bus(struct ndctl_bus *bus, struct ndctl_filter_ctx *fctx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -481,7 +481,7 @@ static void parse_config(const char **ar
|
||||
}
|
||||
|
||||
static int read_config_file(struct ndctl_ctx *ctx, struct monitor *_monitor,
|
||||
- struct util_filter_params *_param)
|
||||
+ struct ndctl_filter_params *_param)
|
||||
{
|
||||
FILE *f;
|
||||
size_t len = 0;
|
||||
@@ -603,7 +603,7 @@ int cmd_monitor(int argc, const char **a
|
||||
NULL
|
||||
};
|
||||
const char *prefix = "./";
|
||||
- struct util_filter_ctx fctx = { 0 };
|
||||
+ struct ndctl_filter_ctx fctx = { 0 };
|
||||
struct monitor_filter_arg mfa = { 0 };
|
||||
int i, rc;
|
||||
|
||||
@@ -667,7 +667,7 @@ int cmd_monitor(int argc, const char **a
|
||||
mfa.maxfd_dimm = -1;
|
||||
mfa.flags = 0;
|
||||
|
||||
- rc = util_filter_walk(ctx, &fctx, ¶m);
|
||||
+ rc = ndctl_filter_walk(ctx, &fctx, ¶m);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
diff -up ndctl-71.1/test/list-smart-dimm.c.orig ndctl-71.1/test/list-smart-dimm.c
|
||||
--- ndctl-71.1/test/list-smart-dimm.c.orig 2022-10-07 17:54:40.813788062 -0400
|
||||
+++ ndctl-71.1/test/list-smart-dimm.c 2022-10-07 17:54:52.595828176 -0400
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <ndctl/ndctl.h>
|
||||
#include <ndctl/json.h>
|
||||
|
||||
-struct util_filter_params param;
|
||||
+struct ndctl_filter_params param;
|
||||
static int did_fail;
|
||||
static int jflag = JSON_C_TO_STRING_PRETTY;
|
||||
|
||||
@@ -23,12 +23,12 @@ do { \
|
||||
} while (0)
|
||||
|
||||
static bool filter_region(struct ndctl_region *region,
|
||||
- struct util_filter_ctx *ctx)
|
||||
+ struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx)
|
||||
+static void filter_dimm(struct ndctl_dimm *dimm, struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
struct list_filter_arg *lfa = ctx->list;
|
||||
struct json_object *jdimm;
|
||||
@@ -57,7 +57,7 @@ static void filter_dimm(struct ndctl_dim
|
||||
json_object_array_add(lfa->jdimms, jdimm);
|
||||
}
|
||||
|
||||
-static bool filter_bus(struct ndctl_bus *bus, struct util_filter_ctx *ctx)
|
||||
+static bool filter_bus(struct ndctl_bus *bus, struct ndctl_filter_ctx *ctx)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -89,7 +89,7 @@ int main(int argc, const char *argv[])
|
||||
"list-smart-dimm [<options>]",
|
||||
NULL
|
||||
};
|
||||
- struct util_filter_ctx fctx = { 0 };
|
||||
+ struct ndctl_filter_ctx fctx = { 0 };
|
||||
struct list_filter_arg lfa = { 0 };
|
||||
|
||||
rc = ndctl_new(&ctx);
|
||||
@@ -108,7 +108,7 @@ int main(int argc, const char *argv[])
|
||||
fctx.list = &lfa;
|
||||
lfa.flags = 0;
|
||||
|
||||
- rc = util_filter_walk(ctx, &fctx, ¶m);
|
||||
+ rc = ndctl_filter_walk(ctx, &fctx, ¶m);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
diff -up ndctl-71.1/util/filter.c.orig ndctl-71.1/util/filter.c
|
||||
--- ndctl-71.1/util/filter.c.orig 2022-10-07 17:55:48.192017464 -0400
|
||||
+++ ndctl-71.1/util/filter.c 2022-10-07 17:55:54.474038852 -0400
|
||||
@@ -394,8 +394,8 @@ const char *util_nsmode_name(enum ndctl_
|
||||
return modes[mode];
|
||||
}
|
||||
|
||||
-int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
|
||||
- struct util_filter_params *param)
|
||||
+int ndctl_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
|
||||
+ struct util_filter_params *param)
|
||||
{
|
||||
struct ndctl_bus *bus;
|
||||
unsigned int type = 0;
|
54
SOURCES/0089-build-Add-tags.patch
Normal file
54
SOURCES/0089-build-Add-tags.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 6dafb0baf8fda14f25e0a764fe8f89d8a4727b0c Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:05 -0800
|
||||
Subject: [PATCH 089/217] build: Add tags
|
||||
|
||||
Copy the systemd approach to generating tags with a file listing from git.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298552547.3021641.2951502977152843738.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
meson.build | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index b22fb2e..68f3d0c 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -82,6 +82,7 @@ project_source_root = meson.current_source_dir()
|
||||
# Cleanup the leftover config.h files to avoid conflicts with the meson
|
||||
# generated config.h
|
||||
git = find_program('git', required : false)
|
||||
+env = find_program('env')
|
||||
if git.found()
|
||||
run_command('clean_config.sh',
|
||||
env : 'GIT_DIR=@0@/.git'.format(project_source_root),
|
||||
@@ -111,6 +112,24 @@ else
|
||||
)
|
||||
endif
|
||||
|
||||
+if git.found()
|
||||
+ all_files = run_command(
|
||||
+ env, '-u', 'GIT_WORK_TREE',
|
||||
+ git, '--git-dir=@0@/.git'.format(project_source_root),
|
||||
+ 'ls-files', ':/*.[ch]',
|
||||
+ check : false)
|
||||
+ if all_files.returncode() == 0
|
||||
+ all_files = files(all_files.stdout().split())
|
||||
+ custom_target(
|
||||
+ 'tags',
|
||||
+ output : 'tags',
|
||||
+ command : [env, 'etags', '-o', '@0@/TAGS'.format(project_source_root)] + all_files)
|
||||
+ run_target(
|
||||
+ 'ctags',
|
||||
+ command : [env, 'ctags', '-o', '@0@/tags'.format(project_source_root)] + all_files)
|
||||
+ endif
|
||||
+endif
|
||||
+
|
||||
versiondep = declare_dependency(
|
||||
compile_args: ['-include', 'version.h'],
|
||||
sources: version_h
|
||||
--
|
||||
2.27.0
|
||||
|
194
SOURCES/0090-json-Add-support-for-json_object_new_uint64.patch
Normal file
194
SOURCES/0090-json-Add-support-for-json_object_new_uint64.patch
Normal file
@ -0,0 +1,194 @@
|
||||
From 691cd249750b505753680d2a766280698ce25b75 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:10 -0800
|
||||
Subject: [PATCH 090/217] json: Add support for json_object_new_uint64()
|
||||
|
||||
Recent versions of json-c add a proper u64 type. However since ndctl still
|
||||
needs to build against older json-c add build infrastructure to fallback to
|
||||
s64.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298553057.3021641.17232869374733997747.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
config.h.meson | 3 +++
|
||||
cxl/json.c | 6 +++---
|
||||
daxctl/json.c | 2 +-
|
||||
meson.build | 6 ++++++
|
||||
ndctl/dimm.c | 2 +-
|
||||
ndctl/json.c | 10 +++++-----
|
||||
util/json.c | 2 +-
|
||||
util/json.h | 13 ++++++++++++-
|
||||
8 files changed, 32 insertions(+), 12 deletions(-)
|
||||
|
||||
diff -up ndctl-71.1/config.h.meson.orig ndctl-71.1/config.h.meson
|
||||
--- ndctl-71.1/config.h.meson.orig 2022-10-07 17:40:36.698914113 -0400
|
||||
+++ ndctl-71.1/config.h.meson 2022-10-07 17:41:24.043075305 -0400
|
||||
@@ -88,6 +88,9 @@
|
||||
/* Define to 1 if you have the `__secure_getenv' function. */
|
||||
#mesondefine HAVE___SECURE_GETENV
|
||||
|
||||
+/* Define to 1 if you have json_object_new_uint64 in json-c */
|
||||
+#mesondefine HAVE_JSON_U64
|
||||
+
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#mesondefine LT_OBJDIR
|
||||
|
||||
diff -up ndctl-71.1/cxl/json.c.orig ndctl-71.1/cxl/json.c
|
||||
--- ndctl-71.1/cxl/json.c.orig 2022-10-07 17:40:36.668914011 -0400
|
||||
+++ ndctl-71.1/cxl/json.c 2022-10-07 17:41:24.043075305 -0400
|
||||
@@ -159,17 +159,17 @@ static struct json_object *util_cxl_memd
|
||||
}
|
||||
|
||||
field = cxl_cmd_health_info_get_dirty_shutdowns(cmd);
|
||||
- jobj = json_object_new_int64(field);
|
||||
+ jobj = util_json_new_u64(field);
|
||||
if (jobj)
|
||||
json_object_object_add(jhealth, "dirty_shutdowns", jobj);
|
||||
|
||||
field = cxl_cmd_health_info_get_volatile_errors(cmd);
|
||||
- jobj = json_object_new_int64(field);
|
||||
+ jobj = util_json_new_u64(field);
|
||||
if (jobj)
|
||||
json_object_object_add(jhealth, "volatile_errors", jobj);
|
||||
|
||||
field = cxl_cmd_health_info_get_pmem_errors(cmd);
|
||||
- jobj = json_object_new_int64(field);
|
||||
+ jobj = util_json_new_u64(field);
|
||||
if (jobj)
|
||||
json_object_object_add(jhealth, "pmem_errors", jobj);
|
||||
|
||||
diff -up ndctl-71.1/daxctl/json.c.orig ndctl-71.1/daxctl/json.c
|
||||
--- ndctl-71.1/daxctl/json.c.orig 2022-10-07 17:40:36.671914021 -0400
|
||||
+++ ndctl-71.1/daxctl/json.c 2022-10-07 17:41:24.043075305 -0400
|
||||
@@ -190,7 +190,7 @@ struct json_object *util_daxctl_region_t
|
||||
|
||||
align = daxctl_region_get_align(region);
|
||||
if (align < ULONG_MAX) {
|
||||
- jobj = json_object_new_int64(align);
|
||||
+ jobj = util_json_new_u64(align);
|
||||
if (!jobj)
|
||||
goto err;
|
||||
json_object_object_add(jregion, "align", jobj);
|
||||
diff -up ndctl-71.1/meson.build.orig ndctl-71.1/meson.build
|
||||
--- ndctl-71.1/meson.build.orig 2022-10-07 17:40:36.720914188 -0400
|
||||
+++ ndctl-71.1/meson.build 2022-10-07 17:41:24.044075308 -0400
|
||||
@@ -240,6 +240,12 @@ foreach ident : ['secure_getenv', '__sec
|
||||
conf.set10('HAVE_' + ident.to_upper(), cc.has_function(ident))
|
||||
endforeach
|
||||
|
||||
+conf.set10('HAVE_JSON_U64',
|
||||
+ cc.has_function('json_object_new_uint64',
|
||||
+ prefix : '''#include <json-c/json.h>''',
|
||||
+ dependencies : json,
|
||||
+ )
|
||||
+)
|
||||
|
||||
ndctlconf_dir = sysconfdir / 'ndctl'
|
||||
ndctlconf = ndctlconf_dir / 'monitor.conf'
|
||||
diff -up ndctl-71.1/ndctl/dimm.c.orig ndctl-71.1/ndctl/dimm.c
|
||||
--- ndctl-71.1/ndctl/dimm.c.orig 2022-10-07 17:40:36.673914028 -0400
|
||||
+++ ndctl-71.1/ndctl/dimm.c 2022-10-07 17:41:24.044075308 -0400
|
||||
@@ -168,7 +168,7 @@ static struct json_object *dump_label_js
|
||||
break;
|
||||
json_object_object_add(jlabel, "isetcookie", jobj);
|
||||
|
||||
- jobj = json_object_new_int64(le64_to_cpu(nslabel.lbasize));
|
||||
+ jobj = util_json_new_u64(le64_to_cpu(nslabel.lbasize));
|
||||
if (!jobj)
|
||||
break;
|
||||
json_object_object_add(jlabel, "lbasize", jobj);
|
||||
diff -up ndctl-71.1/ndctl/json.c.orig ndctl-71.1/ndctl/json.c
|
||||
--- ndctl-71.1/ndctl/json.c.orig 2022-10-07 17:40:36.675914034 -0400
|
||||
+++ ndctl-71.1/ndctl/json.c 2022-10-07 17:41:24.044075308 -0400
|
||||
@@ -357,7 +357,7 @@ static struct json_object *util_##type##
|
||||
int64_t align; \
|
||||
\
|
||||
align = get_elem(arg, i); \
|
||||
- jobj = json_object_new_int64(align); \
|
||||
+ jobj = util_json_new_u64(align); \
|
||||
if (!jobj) \
|
||||
goto err; \
|
||||
json_object_array_add(arr, jobj); \
|
||||
@@ -550,7 +550,7 @@ struct json_object *util_region_badblock
|
||||
if (!jbb)
|
||||
goto err_array;
|
||||
|
||||
- jobj = json_object_new_int64(bb->offset);
|
||||
+ jobj = util_json_new_u64(bb->offset);
|
||||
if (!jobj)
|
||||
goto err;
|
||||
json_object_object_add(jbb, "offset", jobj);
|
||||
@@ -604,7 +604,7 @@ static struct json_object *util_namespac
|
||||
if (!jbb)
|
||||
goto err_array;
|
||||
|
||||
- jobj = json_object_new_int64(bb->offset);
|
||||
+ jobj = util_json_new_u64(bb->offset);
|
||||
if (!jobj)
|
||||
goto err;
|
||||
json_object_object_add(jbb, "offset", jobj);
|
||||
@@ -682,7 +682,7 @@ static struct json_object *dev_badblocks
|
||||
if (!jbb)
|
||||
goto err_array;
|
||||
|
||||
- jobj = json_object_new_int64(offset);
|
||||
+ jobj = util_json_new_u64(offset);
|
||||
if (!jobj)
|
||||
goto err;
|
||||
json_object_object_add(jbb, "offset", jobj);
|
||||
@@ -972,7 +972,7 @@ struct json_object *util_namespace_to_js
|
||||
}
|
||||
|
||||
if (align) {
|
||||
- jobj = json_object_new_int64(align);
|
||||
+ jobj = util_json_new_u64(align);
|
||||
if (!jobj)
|
||||
goto err;
|
||||
json_object_object_add(jndns, "align", jobj);
|
||||
diff -up ndctl-71.1/util/json.c.orig ndctl-71.1/util/json.c
|
||||
--- ndctl-71.1/util/json.c.orig 2022-10-07 17:40:36.682914058 -0400
|
||||
+++ ndctl-71.1/util/json.c 2022-10-07 17:41:24.045075312 -0400
|
||||
@@ -82,7 +82,7 @@ struct json_object *util_json_object_siz
|
||||
struct json_object *util_json_object_hex(unsigned long long val,
|
||||
unsigned long flags)
|
||||
{
|
||||
- struct json_object *jobj = json_object_new_int64(val);
|
||||
+ struct json_object *jobj = util_json_new_u64(val);
|
||||
|
||||
if (jobj && (flags & UTIL_JSON_HUMAN))
|
||||
json_object_set_serializer(jobj, display_hex, NULL, NULL);
|
||||
diff -up ndctl-71.1/util/json.h.orig ndctl-71.1/util/json.h
|
||||
--- ndctl-71.1/util/json.h.orig 2022-10-07 17:40:36.683914062 -0400
|
||||
+++ ndctl-71.1/util/json.h 2022-10-07 17:41:24.046075315 -0400
|
||||
@@ -4,6 +4,7 @@
|
||||
#define __UTIL_JSON_H__
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
+#include <json-c/json.h>
|
||||
|
||||
enum util_json_flags {
|
||||
UTIL_JSON_IDLE = (1 << 0),
|
||||
@@ -19,11 +20,21 @@ enum util_json_flags {
|
||||
UTIL_JSON_HEALTH = (1 << 10),
|
||||
};
|
||||
|
||||
-struct json_object;
|
||||
void util_display_json_array(FILE *f_out, struct json_object *jarray,
|
||||
unsigned long flags);
|
||||
struct json_object *util_json_object_size(unsigned long long size,
|
||||
unsigned long flags);
|
||||
struct json_object *util_json_object_hex(unsigned long long val,
|
||||
unsigned long flags);
|
||||
+#if HAVE_JSON_U64
|
||||
+static inline struct json_object *util_json_new_u64(unsigned long long val)
|
||||
+{
|
||||
+ return json_object_new_uint64(val);
|
||||
+}
|
||||
+#else /* fallback to signed */
|
||||
+static inline struct json_object *util_json_new_u64(unsigned long long val)
|
||||
+{
|
||||
+ return json_object_new_int64(val);
|
||||
+}
|
||||
+#endif /* HAVE_JSON_U64 */
|
||||
#endif /* __UTIL_JSON_H__ */
|
@ -0,0 +1,32 @@
|
||||
From 8f457dc414ec27178828c86533910958542ce73d Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:15 -0800
|
||||
Subject: [PATCH 091/217] cxl/json: Cleanup object leak false positive
|
||||
|
||||
As written it is a leak of the json object to return if devname is NULL.
|
||||
However, the devname can not be NULL because the memdev would not have been
|
||||
enumerated. Drop the error checking.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298553566.3021641.11858634436119663877.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/json.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index 97ed76b..3ef9f76 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -190,7 +190,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
struct json_object *jdev, *jobj;
|
||||
|
||||
jdev = json_object_new_object();
|
||||
- if (!devname || !jdev)
|
||||
+ if (!jdev)
|
||||
return NULL;
|
||||
|
||||
jobj = json_object_new_string(devname);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,118 @@
|
||||
From 0ce0152d8e29f85325a3a59f94051228540abf6a Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:20 -0800
|
||||
Subject: [PATCH 092/217] cxl/list: Support multiple memdev device name filter
|
||||
arguments
|
||||
|
||||
Similar to 'ndctl list', allow for a syntax like:
|
||||
|
||||
cxl list -m "$(seq -s ' ' 2 5)"
|
||||
|
||||
...to filter the output to just those 4 memdevs.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298554075.3021641.17678360870961637912.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 21 ++++++++++++++++++-
|
||||
cxl/filter.c | 38 ++++++++++++++++++++++++----------
|
||||
2 files changed, 47 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index c8d10fb..686e0ea 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -30,7 +30,7 @@ OPTIONS
|
||||
-------
|
||||
-m::
|
||||
--memdev=::
|
||||
- Specify a cxl memory device name to filter the listing. For example:
|
||||
+ Specify CXL memory device name(s), or device id(s), to filter the listing. For example:
|
||||
----
|
||||
# cxl list --memdev=mem0
|
||||
{
|
||||
@@ -38,6 +38,25 @@ OPTIONS
|
||||
"pmem_size":268435456,
|
||||
"ram_size":0,
|
||||
}
|
||||
+
|
||||
+# cxl list -m "0 mem1 2"
|
||||
+[
|
||||
+ {
|
||||
+ "memdev":"mem0",
|
||||
+ "pmem_size":268435456,
|
||||
+ "ram_size":0
|
||||
+ },
|
||||
+ {
|
||||
+ "memdev":"mem2",
|
||||
+ "pmem_size":268435456,
|
||||
+ "ram_size":268435456
|
||||
+ },
|
||||
+ {
|
||||
+ "memdev":"mem1",
|
||||
+ "pmem_size":268435456,
|
||||
+ "ram_size":268435456
|
||||
+ }
|
||||
+]
|
||||
----
|
||||
|
||||
-M::
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 21322ed..efafaf5 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -2,24 +2,40 @@
|
||||
// Copyright (C) 2015-2020 Intel Corporation. All rights reserved.
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
+#include <stdlib.h>
|
||||
#include <cxl/libcxl.h>
|
||||
#include "filter.h"
|
||||
|
||||
struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
- const char *ident)
|
||||
+ const char *__ident)
|
||||
{
|
||||
- int memdev_id;
|
||||
+ char *ident, *save;
|
||||
+ const char *name;
|
||||
+ int memdev_id;
|
||||
|
||||
- if (!ident || strcmp(ident, "all") == 0)
|
||||
- return memdev;
|
||||
+ if (!__ident)
|
||||
+ return memdev;
|
||||
|
||||
- if (strcmp(ident, cxl_memdev_get_devname(memdev)) == 0)
|
||||
- return memdev;
|
||||
+ ident = strdup(__ident);
|
||||
+ if (!ident)
|
||||
+ return NULL;
|
||||
|
||||
- if ((sscanf(ident, "%d", &memdev_id) == 1
|
||||
- || sscanf(ident, "mem%d", &memdev_id) == 1)
|
||||
- && cxl_memdev_get_id(memdev) == memdev_id)
|
||||
- return memdev;
|
||||
+ for (name = strtok_r(ident, " ", &save); name;
|
||||
+ name = strtok_r(NULL, " ", &save)) {
|
||||
+ if (strcmp(name, "all") == 0)
|
||||
+ break;
|
||||
|
||||
- return NULL;
|
||||
+ if ((sscanf(name, "%d", &memdev_id) == 1 ||
|
||||
+ sscanf(name, "mem%d", &memdev_id) == 1) &&
|
||||
+ cxl_memdev_get_id(memdev) == memdev_id)
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(name, cxl_memdev_get_devname(memdev)) == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ free(ident);
|
||||
+ if (name)
|
||||
+ return memdev;
|
||||
+ return NULL;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
55
SOURCES/0093-cxl-list-Support-comma-separated-lists.patch
Normal file
55
SOURCES/0093-cxl-list-Support-comma-separated-lists.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From a36b8b815d2e8bfd8438b44d4775bdf3ffc3a6d8 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:26 -0800
|
||||
Subject: [PATCH 093/217] cxl/list: Support comma separated lists
|
||||
|
||||
In addition to supporting a syntax like:
|
||||
|
||||
cxl list -m "0 1 2"
|
||||
|
||||
...support:
|
||||
|
||||
cxl list -m 0,1,2
|
||||
|
||||
Link: https://lore.kernel.org/r/164298554612.3021641.3315920699556984273.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Reported-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/filter.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index efafaf5..405b653 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -6,6 +6,15 @@
|
||||
#include <cxl/libcxl.h>
|
||||
#include "filter.h"
|
||||
|
||||
+static const char *which_sep(const char *filter)
|
||||
+{
|
||||
+ if (strchr(filter, ' '))
|
||||
+ return " ";
|
||||
+ if (strchr(filter, ','))
|
||||
+ return ",";
|
||||
+ return " ";
|
||||
+}
|
||||
+
|
||||
struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
const char *__ident)
|
||||
{
|
||||
@@ -20,8 +29,8 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
if (!ident)
|
||||
return NULL;
|
||||
|
||||
- for (name = strtok_r(ident, " ", &save); name;
|
||||
- name = strtok_r(NULL, " ", &save)) {
|
||||
+ for (name = strtok_r(ident, which_sep(__ident), &save); name;
|
||||
+ name = strtok_r(NULL, which_sep(__ident), &save)) {
|
||||
if (strcmp(name, "all") == 0)
|
||||
break;
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
292
SOURCES/0094-cxl-list-Introduce-cxl_filter_walk.patch
Normal file
292
SOURCES/0094-cxl-list-Introduce-cxl_filter_walk.patch
Normal file
@ -0,0 +1,292 @@
|
||||
From f833845ce72490e4c80b3ccc9972d5329f69a381 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:31 -0800
|
||||
Subject: [PATCH 094/217] cxl/list: Introduce cxl_filter_walk()
|
||||
|
||||
In preparation for introducing more objects and filtering options for 'cxl
|
||||
list' introduce cxl_filter_walk() to centralize CXL topology walks. It
|
||||
fills the same role as ndctl_filter_walk() as a way to distribute topology
|
||||
interrogation beyond 'cxl list' to other commands, and serve as the
|
||||
template for CXL object hierarchy in JSON output payloads.
|
||||
|
||||
Use the common dbg() logger for log messages.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298555121.3021641.16127840206319352254.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 2 +
|
||||
cxl/filter.c | 50 ++++++++++++++++
|
||||
cxl/filter.h | 18 +++++-
|
||||
cxl/list.c | 102 +++++++--------------------------
|
||||
cxl/meson.build | 1 +
|
||||
5 files changed, 90 insertions(+), 83 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 686e0ea..4d409ba 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -15,6 +15,8 @@ SYNOPSIS
|
||||
Walk the CXL capable device hierarchy in the system and list all device
|
||||
instances along with some of their major attributes.
|
||||
|
||||
+Options can be specified to limit the output to specific objects.
|
||||
+
|
||||
EXAMPLE
|
||||
-------
|
||||
----
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 405b653..d1ff4b6 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -1,10 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2015-2020 Intel Corporation. All rights reserved.
|
||||
+#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
+#include <util/log.h>
|
||||
+#include <util/json.h>
|
||||
#include <cxl/libcxl.h>
|
||||
+#include <json-c/json.h>
|
||||
+
|
||||
#include "filter.h"
|
||||
+#include "json.h"
|
||||
|
||||
static const char *which_sep(const char *filter)
|
||||
{
|
||||
@@ -48,3 +54,47 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
return memdev;
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
+static unsigned long params_to_flags(struct cxl_filter_params *param)
|
||||
+{
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ if (param->idle)
|
||||
+ flags |= UTIL_JSON_IDLE;
|
||||
+ if (param->human)
|
||||
+ flags |= UTIL_JSON_HUMAN;
|
||||
+ if (param->health)
|
||||
+ flags |= UTIL_JSON_HEALTH;
|
||||
+ return flags;
|
||||
+}
|
||||
+
|
||||
+int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
+{
|
||||
+ struct json_object *jplatform = json_object_new_array();
|
||||
+ unsigned long flags = params_to_flags(p);
|
||||
+ struct cxl_memdev *memdev;
|
||||
+
|
||||
+ if (!jplatform) {
|
||||
+ dbg(p, "platform object allocation failure\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ cxl_memdev_foreach(ctx, memdev) {
|
||||
+ struct json_object *jdev;
|
||||
+
|
||||
+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter))
|
||||
+ continue;
|
||||
+ if (p->memdevs) {
|
||||
+ jdev = util_cxl_memdev_to_json(memdev, flags);
|
||||
+ if (!jdev) {
|
||||
+ dbg(p, "memdev object allocation failure\n");
|
||||
+ continue;
|
||||
+ }
|
||||
+ json_object_array_add(jplatform, jdev);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ util_display_json_array(stdout, jplatform, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/cxl/filter.h b/cxl/filter.h
|
||||
index da80033..664b74b 100644
|
||||
--- a/cxl/filter.h
|
||||
+++ b/cxl/filter.h
|
||||
@@ -1,7 +1,21 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
-/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */
|
||||
+/* Copyright (C) 2021 Intel Corporation. All rights reserved. */
|
||||
#ifndef _CXL_UTIL_FILTER_H_
|
||||
#define _CXL_UTIL_FILTER_H_
|
||||
+
|
||||
+#include <stdbool.h>
|
||||
+#include <util/log.h>
|
||||
+
|
||||
+struct cxl_filter_params {
|
||||
+ const char *memdev_filter;
|
||||
+ bool memdevs;
|
||||
+ bool idle;
|
||||
+ bool human;
|
||||
+ bool health;
|
||||
+ struct log_ctx ctx;
|
||||
+};
|
||||
+
|
||||
struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
- const char *ident);
|
||||
+ const char *ident);
|
||||
+int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param);
|
||||
#endif /* _CXL_UTIL_FILTER_H_ */
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 7f7a04d..1730307 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -9,60 +9,27 @@
|
||||
#include <json-c/json.h>
|
||||
#include <cxl/libcxl.h>
|
||||
#include <util/parse-options.h>
|
||||
-#include <ccan/array_size/array_size.h>
|
||||
|
||||
-#include "json.h"
|
||||
#include "filter.h"
|
||||
|
||||
-static struct {
|
||||
- bool memdevs;
|
||||
- bool idle;
|
||||
- bool human;
|
||||
- bool health;
|
||||
-} list;
|
||||
-
|
||||
-static unsigned long listopts_to_flags(void)
|
||||
-{
|
||||
- unsigned long flags = 0;
|
||||
-
|
||||
- if (list.idle)
|
||||
- flags |= UTIL_JSON_IDLE;
|
||||
- if (list.human)
|
||||
- flags |= UTIL_JSON_HUMAN;
|
||||
- if (list.health)
|
||||
- flags |= UTIL_JSON_HEALTH;
|
||||
- return flags;
|
||||
-}
|
||||
-
|
||||
-static struct {
|
||||
- const char *memdev;
|
||||
-} param;
|
||||
-
|
||||
-static int did_fail;
|
||||
-
|
||||
-#define fail(fmt, ...) \
|
||||
-do { \
|
||||
- did_fail = 1; \
|
||||
- fprintf(stderr, "cxl-%s:%s:%d: " fmt, \
|
||||
- VERSION, __func__, __LINE__, ##__VA_ARGS__); \
|
||||
-} while (0)
|
||||
+static struct cxl_filter_params param;
|
||||
|
||||
static int num_list_flags(void)
|
||||
{
|
||||
- return list.memdevs;
|
||||
+ return param.memdevs;
|
||||
}
|
||||
|
||||
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
{
|
||||
const struct option options[] = {
|
||||
- OPT_STRING('m', "memdev", ¶m.memdev, "memory device name",
|
||||
+ OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name",
|
||||
"filter by CXL memory device name"),
|
||||
- OPT_BOOLEAN('M', "memdevs", &list.memdevs,
|
||||
+ OPT_BOOLEAN('M', "memdevs", ¶m.memdevs,
|
||||
"include CXL memory device info"),
|
||||
- OPT_BOOLEAN('i', "idle", &list.idle, "include idle devices"),
|
||||
- OPT_BOOLEAN('u', "human", &list.human,
|
||||
+ OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
+ OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
"use human friendly number formats "),
|
||||
- OPT_BOOLEAN('H', "health", &list.health,
|
||||
+ OPT_BOOLEAN('H', "health", ¶m.health,
|
||||
"include memory device health information "),
|
||||
OPT_END(),
|
||||
};
|
||||
@@ -70,9 +37,6 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
"cxl list [<options>]",
|
||||
NULL
|
||||
};
|
||||
- struct json_object *jdevs = NULL;
|
||||
- unsigned long list_flags;
|
||||
- struct cxl_memdev *memdev;
|
||||
int i;
|
||||
|
||||
argc = parse_options(argc, argv, options, u, 0);
|
||||
@@ -83,46 +47,22 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
usage_with_options(u, options);
|
||||
|
||||
if (num_list_flags() == 0) {
|
||||
- /*
|
||||
- * TODO: We likely want to list regions by default if nothing
|
||||
- * was explicitly asked for. But until we have region support,
|
||||
- * print this error asking for devices explicitly.
|
||||
- * Once region support is added, this TODO can be removed.
|
||||
- */
|
||||
- error("please specify entities to list, e.g. using -m/-M\n");
|
||||
- usage_with_options(u, options);
|
||||
- }
|
||||
-
|
||||
- list_flags = listopts_to_flags();
|
||||
-
|
||||
- cxl_memdev_foreach(ctx, memdev) {
|
||||
- struct json_object *jdev = NULL;
|
||||
-
|
||||
- if (!util_cxl_memdev_filter(memdev, param.memdev))
|
||||
- continue;
|
||||
-
|
||||
- if (list.memdevs) {
|
||||
- if (!jdevs) {
|
||||
- jdevs = json_object_new_array();
|
||||
- if (!jdevs) {
|
||||
- fail("\n");
|
||||
- continue;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- jdev = util_cxl_memdev_to_json(memdev, list_flags);
|
||||
- if (!jdev) {
|
||||
- fail("\n");
|
||||
- continue;
|
||||
- }
|
||||
- json_object_array_add(jdevs, jdev);
|
||||
+ if (param.memdev_filter)
|
||||
+ param.memdevs = true;
|
||||
+ else {
|
||||
+ /*
|
||||
+ * TODO: We likely want to list regions by default if
|
||||
+ * nothing was explicitly asked for. But until we have
|
||||
+ * region support, print this error asking for devices
|
||||
+ * explicitly. Once region support is added, this TODO
|
||||
+ * can be removed.
|
||||
+ */
|
||||
+ error("please specify entities to list, e.g. using -m/-M\n");
|
||||
+ usage_with_options(u, options);
|
||||
}
|
||||
}
|
||||
|
||||
- if (jdevs)
|
||||
- util_display_json_array(stdout, jdevs, list_flags);
|
||||
+ log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG");
|
||||
|
||||
- if (did_fail)
|
||||
- return -ENOMEM;
|
||||
- return 0;
|
||||
+ return cxl_filter_walk(ctx, ¶m);
|
||||
}
|
||||
diff --git a/cxl/meson.build b/cxl/meson.build
|
||||
index 805924b..fc7ee71 100644
|
||||
--- a/cxl/meson.build
|
||||
+++ b/cxl/meson.build
|
||||
@@ -3,6 +3,7 @@ cxl_src = [
|
||||
'list.c',
|
||||
'memdev.c',
|
||||
'../util/json.c',
|
||||
+ '../util/log.c',
|
||||
'json.c',
|
||||
'filter.c',
|
||||
]
|
||||
--
|
||||
2.27.0
|
||||
|
159
SOURCES/0095-cxl-list-Emit-device-serial-numbers.patch
Normal file
159
SOURCES/0095-cxl-list-Emit-device-serial-numbers.patch
Normal file
@ -0,0 +1,159 @@
|
||||
From 2d1b8cea119ca2bb0eec8ebb2dfb1b6c4d844ddd Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:36 -0800
|
||||
Subject: [PATCH 095/217] cxl/list: Emit device serial numbers
|
||||
|
||||
Starting with the v5.17 kernel the CXL driver emits the mandatory device
|
||||
serial number for each memory device. Include it in the memory device
|
||||
listing.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298555630.3021641.3246226448369816200.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 15 +++++++++------
|
||||
cxl/json.c | 11 ++++++++++-
|
||||
cxl/lib/libcxl.c | 11 +++++++++++
|
||||
cxl/lib/libcxl.sym | 5 +++++
|
||||
cxl/lib/private.h | 1 +
|
||||
cxl/libcxl.h | 1 +
|
||||
6 files changed, 37 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 4d409ba..bd0207e 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -41,22 +41,25 @@ OPTIONS
|
||||
"ram_size":0,
|
||||
}
|
||||
|
||||
-# cxl list -m "0 mem1 2"
|
||||
+# cxl list -M --memdev="0 mem3 5"
|
||||
[
|
||||
{
|
||||
"memdev":"mem0",
|
||||
"pmem_size":268435456,
|
||||
- "ram_size":0
|
||||
+ "ram_size":0,
|
||||
+ "serial":0
|
||||
},
|
||||
{
|
||||
- "memdev":"mem2",
|
||||
+ "memdev":"mem3",
|
||||
"pmem_size":268435456,
|
||||
- "ram_size":268435456
|
||||
+ "ram_size":268435456,
|
||||
+ "serial":2
|
||||
},
|
||||
{
|
||||
- "memdev":"mem1",
|
||||
+ "memdev":"mem5",
|
||||
"pmem_size":268435456,
|
||||
- "ram_size":268435456
|
||||
+ "ram_size":268435456,
|
||||
+ "serial":4
|
||||
}
|
||||
]
|
||||
----
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index 3ef9f76..d8e65df 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
-// Copyright (C) 2015-2020 Intel Corporation. All rights reserved.
|
||||
+// Copyright (C) 2015-2021 Intel Corporation. All rights reserved.
|
||||
+#include <limits.h>
|
||||
#include <util/json.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <cxl/libcxl.h>
|
||||
@@ -188,6 +189,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
{
|
||||
const char *devname = cxl_memdev_get_devname(memdev);
|
||||
struct json_object *jdev, *jobj;
|
||||
+ unsigned long long serial;
|
||||
|
||||
jdev = json_object_new_object();
|
||||
if (!jdev)
|
||||
@@ -210,5 +212,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
if (jobj)
|
||||
json_object_object_add(jdev, "health", jobj);
|
||||
}
|
||||
+
|
||||
+ serial = cxl_memdev_get_serial(memdev);
|
||||
+ if (serial < ULLONG_MAX) {
|
||||
+ jobj = util_json_object_hex(serial, flags);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdev, "serial", jobj);
|
||||
+ }
|
||||
return jdev;
|
||||
}
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 3390eb9..8d3cf80 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -296,6 +296,12 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
||||
if (memdev->lsa_size == ULLONG_MAX)
|
||||
goto err_read;
|
||||
|
||||
+ sprintf(path, "%s/serial", cxlmem_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
+ memdev->serial = ULLONG_MAX;
|
||||
+ else
|
||||
+ memdev->serial = strtoull(buf, NULL, 0);
|
||||
+
|
||||
memdev->dev_path = strdup(cxlmem_base);
|
||||
if (!memdev->dev_path)
|
||||
goto err_read;
|
||||
@@ -371,6 +377,11 @@ CXL_EXPORT int cxl_memdev_get_id(struct cxl_memdev *memdev)
|
||||
return memdev->id;
|
||||
}
|
||||
|
||||
+CXL_EXPORT unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ return memdev->serial;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev)
|
||||
{
|
||||
return devpath_to_devname(memdev->dev_path);
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 077d104..4411035 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -73,3 +73,8 @@ global:
|
||||
local:
|
||||
*;
|
||||
};
|
||||
+
|
||||
+LIBCXL_2 {
|
||||
+global:
|
||||
+ cxl_memdev_get_serial;
|
||||
+} LIBCXL_1;
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index a1b8b50..28f7e16 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -31,6 +31,7 @@ struct cxl_memdev {
|
||||
size_t lsa_size;
|
||||
struct kmod_module *module;
|
||||
struct cxl_nvdimm_bridge *bridge;
|
||||
+ unsigned long long serial;
|
||||
};
|
||||
|
||||
enum cxl_cmd_query_status {
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 89d35ba..bcdede8 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -35,6 +35,7 @@ struct cxl_memdev;
|
||||
struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx);
|
||||
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);
|
||||
int cxl_memdev_get_major(struct cxl_memdev *memdev);
|
||||
int cxl_memdev_get_minor(struct cxl_memdev *memdev);
|
||||
--
|
||||
2.27.0
|
||||
|
163
SOURCES/0096-cxl-list-Add-filter-by-serial-support.patch
Normal file
163
SOURCES/0096-cxl-list-Add-filter-by-serial-support.patch
Normal file
@ -0,0 +1,163 @@
|
||||
From d7854adcd1e517d2372ec51f4a1ede2d549975e8 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:41 -0800
|
||||
Subject: [PATCH 096/217] cxl/list: Add filter by serial support
|
||||
|
||||
Given that serial numbers are intended to be unique device identifiers,
|
||||
enable them as a memdev filter option.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298556167.3021641.5470955268978068465.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 4 ++++
|
||||
cxl/filter.c | 38 ++++++++++++++++++++++++++++++----
|
||||
cxl/filter.h | 4 +++-
|
||||
cxl/list.c | 4 +++-
|
||||
cxl/memdev.c | 2 +-
|
||||
5 files changed, 45 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index bd0207e..224c972 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -64,6 +64,10 @@ OPTIONS
|
||||
]
|
||||
----
|
||||
|
||||
+-s::
|
||||
+--serial=::
|
||||
+ Specify CXL memory device serial number(s) to filter the listing
|
||||
+
|
||||
-M::
|
||||
--memdevs::
|
||||
Include CXL memory devices in the listing
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index d1ff4b6..26efc65 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -21,15 +21,45 @@ static const char *which_sep(const char *filter)
|
||||
return " ";
|
||||
}
|
||||
|
||||
+static struct cxl_memdev *
|
||||
+util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials)
|
||||
+{
|
||||
+ unsigned long long serial = 0;
|
||||
+ char *serials, *save, *end;
|
||||
+ const char *arg;
|
||||
+
|
||||
+ if (!__serials)
|
||||
+ return memdev;
|
||||
+
|
||||
+ serials = strdup(__serials);
|
||||
+ if (!serials)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (arg = strtok_r(serials, which_sep(__serials), &save); arg;
|
||||
+ arg = strtok_r(NULL, which_sep(__serials), &save)) {
|
||||
+ serial = strtoull(arg, &end, 0);
|
||||
+ if (!arg[0] || end[0] != 0)
|
||||
+ continue;
|
||||
+ if (cxl_memdev_get_serial(memdev) == serial)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ free(serials);
|
||||
+ if (arg)
|
||||
+ return memdev;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
- const char *__ident)
|
||||
+ const char *__ident,
|
||||
+ const char *serials)
|
||||
{
|
||||
char *ident, *save;
|
||||
const char *name;
|
||||
int memdev_id;
|
||||
|
||||
if (!__ident)
|
||||
- return memdev;
|
||||
+ return util_cxl_memdev_serial_filter(memdev, serials);
|
||||
|
||||
ident = strdup(__ident);
|
||||
if (!ident)
|
||||
@@ -51,7 +81,7 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
|
||||
free(ident);
|
||||
if (name)
|
||||
- return memdev;
|
||||
+ return util_cxl_memdev_serial_filter(memdev, serials);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -82,7 +112,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
struct json_object *jdev;
|
||||
|
||||
- if (!util_cxl_memdev_filter(memdev, p->memdev_filter))
|
||||
+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter, p->serial_filter))
|
||||
continue;
|
||||
if (p->memdevs) {
|
||||
jdev = util_cxl_memdev_to_json(memdev, flags);
|
||||
diff --git a/cxl/filter.h b/cxl/filter.h
|
||||
index 664b74b..12d9344 100644
|
||||
--- a/cxl/filter.h
|
||||
+++ b/cxl/filter.h
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
struct cxl_filter_params {
|
||||
const char *memdev_filter;
|
||||
+ const char *serial_filter;
|
||||
bool memdevs;
|
||||
bool idle;
|
||||
bool human;
|
||||
@@ -16,6 +17,7 @@ struct cxl_filter_params {
|
||||
};
|
||||
|
||||
struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
- const char *ident);
|
||||
+ const char *__ident,
|
||||
+ const char *serials);
|
||||
int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param);
|
||||
#endif /* _CXL_UTIL_FILTER_H_ */
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 1730307..6bc48df 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -24,6 +24,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
const struct option options[] = {
|
||||
OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name",
|
||||
"filter by CXL memory device name"),
|
||||
+ OPT_STRING('s', "serial", ¶m.serial_filter, "memory device serial",
|
||||
+ "filter by CXL memory device serial number"),
|
||||
OPT_BOOLEAN('M', "memdevs", ¶m.memdevs,
|
||||
"include CXL memory device info"),
|
||||
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
@@ -47,7 +49,7 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
usage_with_options(u, options);
|
||||
|
||||
if (num_list_flags() == 0) {
|
||||
- if (param.memdev_filter)
|
||||
+ if (param.memdev_filter || param.serial_filter)
|
||||
param.memdevs = true;
|
||||
else {
|
||||
/*
|
||||
diff --git a/cxl/memdev.c b/cxl/memdev.c
|
||||
index d063d51..b9141be 100644
|
||||
--- a/cxl/memdev.c
|
||||
+++ b/cxl/memdev.c
|
||||
@@ -248,7 +248,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
continue;
|
||||
|
||||
cxl_memdev_foreach (ctx, memdev) {
|
||||
- if (!util_cxl_memdev_filter(memdev, argv[i]))
|
||||
+ if (!util_cxl_memdev_filter(memdev, argv[i], NULL))
|
||||
continue;
|
||||
|
||||
if (action == action_write) {
|
||||
--
|
||||
2.27.0
|
||||
|
164
SOURCES/0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch
Normal file
164
SOURCES/0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch
Normal file
@ -0,0 +1,164 @@
|
||||
From 0be46d9c6638903978d16388c765a1907d5970bc Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:47 -0800
|
||||
Subject: [PATCH 097/217] cxl/lib: Rename nvdimm bridge to pmem
|
||||
|
||||
The kernel has 2 object classes for connecting CXL to NVDIMM. There is an
|
||||
'nvdimm-bridge' object (one per root CXL port) that represents a CXL NVDIMM
|
||||
Bus, and there are 'pmem' object that represent CXL NVDIMM DIMM devices.
|
||||
The object that the library is currently calling an nvdimm-bridge is
|
||||
actually the 'pmem' object. Rename accordingly.
|
||||
|
||||
The exported function cxl_memdev_nvdimm_bridge_active() is not renamed, but
|
||||
since it is a cxl_memdev operation and 'struct cxl_pmem' is an
|
||||
implementation detail it is fine as is.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298556712.3021641.15612755067301105130.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/lib/libcxl.c | 56 +++++++++++++++++++++++------------------------
|
||||
cxl/lib/private.h | 4 ++--
|
||||
2 files changed, 30 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 8d3cf80..9839f26 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -45,11 +45,11 @@ struct cxl_ctx {
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
-static void free_bridge(struct cxl_nvdimm_bridge *bridge)
|
||||
+static void free_pmem(struct cxl_pmem *pmem)
|
||||
{
|
||||
- free(bridge->dev_buf);
|
||||
- free(bridge->dev_path);
|
||||
- free(bridge);
|
||||
+ free(pmem->dev_buf);
|
||||
+ free(pmem->dev_path);
|
||||
+ free(pmem);
|
||||
}
|
||||
|
||||
static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
@@ -57,7 +57,7 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
if (head)
|
||||
list_del_from(head, &memdev->list);
|
||||
kmod_module_unref(memdev->module);
|
||||
- free_bridge(memdev->bridge);
|
||||
+ free_pmem(memdev->pmem);
|
||||
free(memdev->firmware_version);
|
||||
free(memdev->dev_buf);
|
||||
free(memdev->dev_path);
|
||||
@@ -213,36 +213,36 @@ CXL_EXPORT void cxl_set_log_priority(struct cxl_ctx *ctx, int priority)
|
||||
ctx->ctx.log_priority = priority;
|
||||
}
|
||||
|
||||
-static void *add_cxl_bridge(void *parent, int id, const char *br_base)
|
||||
+static void *add_cxl_pmem(void *parent, int id, const char *br_base)
|
||||
{
|
||||
const char *devname = devpath_to_devname(br_base);
|
||||
struct cxl_memdev *memdev = parent;
|
||||
struct cxl_ctx *ctx = memdev->ctx;
|
||||
- struct cxl_nvdimm_bridge *bridge;
|
||||
+ struct cxl_pmem *pmem;
|
||||
|
||||
- dbg(ctx, "%s: bridge_base: \'%s\'\n", devname, br_base);
|
||||
+ dbg(ctx, "%s: pmem_base: \'%s\'\n", devname, br_base);
|
||||
|
||||
- bridge = calloc(1, sizeof(*bridge));
|
||||
- if (!bridge)
|
||||
+ pmem = calloc(1, sizeof(*pmem));
|
||||
+ if (!pmem)
|
||||
goto err_dev;
|
||||
- bridge->id = id;
|
||||
+ pmem->id = id;
|
||||
|
||||
- bridge->dev_path = strdup(br_base);
|
||||
- if (!bridge->dev_path)
|
||||
+ pmem->dev_path = strdup(br_base);
|
||||
+ if (!pmem->dev_path)
|
||||
goto err_read;
|
||||
|
||||
- bridge->dev_buf = calloc(1, strlen(br_base) + 50);
|
||||
- if (!bridge->dev_buf)
|
||||
+ pmem->dev_buf = calloc(1, strlen(br_base) + 50);
|
||||
+ if (!pmem->dev_buf)
|
||||
goto err_read;
|
||||
- bridge->buf_len = strlen(br_base) + 50;
|
||||
+ pmem->buf_len = strlen(br_base) + 50;
|
||||
|
||||
- memdev->bridge = bridge;
|
||||
- return bridge;
|
||||
+ memdev->pmem = pmem;
|
||||
+ return pmem;
|
||||
|
||||
err_read:
|
||||
- free(bridge->dev_buf);
|
||||
- free(bridge->dev_path);
|
||||
- free(bridge);
|
||||
+ free(pmem->dev_buf);
|
||||
+ free(pmem->dev_path);
|
||||
+ free(pmem);
|
||||
err_dev:
|
||||
return NULL;
|
||||
}
|
||||
@@ -319,7 +319,7 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
||||
goto err_read;
|
||||
memdev->buf_len = strlen(cxlmem_base) + 50;
|
||||
|
||||
- sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_bridge);
|
||||
+ sysfs_device_parse(ctx, cxlmem_base, "pmem", memdev, add_cxl_pmem);
|
||||
|
||||
cxl_memdev_foreach(ctx, memdev_dup)
|
||||
if (memdev_dup->id == memdev->id) {
|
||||
@@ -430,18 +430,18 @@ static int is_enabled(const char *drvpath)
|
||||
CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
||||
{
|
||||
struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
- struct cxl_nvdimm_bridge *bridge = memdev->bridge;
|
||||
+ struct cxl_pmem *pmem = memdev->pmem;
|
||||
char *path;
|
||||
int len;
|
||||
|
||||
- if (!bridge)
|
||||
+ if (!pmem)
|
||||
return 0;
|
||||
|
||||
- path = bridge->dev_buf;
|
||||
- len = bridge->buf_len;
|
||||
+ path = pmem->dev_buf;
|
||||
+ len = pmem->buf_len;
|
||||
|
||||
- if (snprintf(path, len, "%s/driver", bridge->dev_path) >= len) {
|
||||
- err(ctx, "%s: nvdimm bridge buffer too small!\n",
|
||||
+ if (snprintf(path, len, "%s/driver", pmem->dev_path) >= len) {
|
||||
+ err(ctx, "%s: nvdimm pmem buffer too small!\n",
|
||||
cxl_memdev_get_devname(memdev));
|
||||
return 0;
|
||||
}
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 28f7e16..7c81e24 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
#define CXL_EXPORT __attribute__ ((visibility("default")))
|
||||
|
||||
-struct cxl_nvdimm_bridge {
|
||||
+struct cxl_pmem {
|
||||
int id;
|
||||
void *dev_buf;
|
||||
size_t buf_len;
|
||||
@@ -30,7 +30,7 @@ struct cxl_memdev {
|
||||
int payload_max;
|
||||
size_t lsa_size;
|
||||
struct kmod_module *module;
|
||||
- struct cxl_nvdimm_bridge *bridge;
|
||||
+ struct cxl_pmem *pmem;
|
||||
unsigned long long serial;
|
||||
};
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
61
SOURCES/0098-cxl-list-Cleanup-options-definitions.patch
Normal file
61
SOURCES/0098-cxl-list-Cleanup-options-definitions.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 5d20a4d2cca923e63cb1604da51788c0fd078ce1 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:52 -0800
|
||||
Subject: [PATCH 098/217] cxl/list: Cleanup options definitions
|
||||
|
||||
Clarify which options take lists by adding a "(s)" to the object name, and
|
||||
move the option block out of cmd_list() to reduce the column-80 collisions.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298557263.3021641.8121105326167408001.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/list.c | 30 ++++++++++++++++--------------
|
||||
1 file changed, 16 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 6bc48df..7e2744d 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -19,22 +19,24 @@ static int num_list_flags(void)
|
||||
return param.memdevs;
|
||||
}
|
||||
|
||||
+static const struct option options[] = {
|
||||
+ OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name(s)",
|
||||
+ "filter by CXL memory device name(s)"),
|
||||
+ OPT_STRING('s', "serial", ¶m.serial_filter,
|
||||
+ "memory device serial(s)",
|
||||
+ "filter by CXL memory device serial number(s)"),
|
||||
+ OPT_BOOLEAN('M', "memdevs", ¶m.memdevs,
|
||||
+ "include CXL memory device info"),
|
||||
+ OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
+ OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
+ "use human friendly number formats "),
|
||||
+ OPT_BOOLEAN('H', "health", ¶m.health,
|
||||
+ "include memory device health information "),
|
||||
+ OPT_END(),
|
||||
+};
|
||||
+
|
||||
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
{
|
||||
- const struct option options[] = {
|
||||
- OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name",
|
||||
- "filter by CXL memory device name"),
|
||||
- OPT_STRING('s', "serial", ¶m.serial_filter, "memory device serial",
|
||||
- "filter by CXL memory device serial number"),
|
||||
- OPT_BOOLEAN('M', "memdevs", ¶m.memdevs,
|
||||
- "include CXL memory device info"),
|
||||
- OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
- OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
- "use human friendly number formats "),
|
||||
- OPT_BOOLEAN('H', "health", ¶m.health,
|
||||
- "include memory device health information "),
|
||||
- OPT_END(),
|
||||
- };
|
||||
const char * const u[] = {
|
||||
"cxl list [<options>]",
|
||||
NULL
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,170 @@
|
||||
From 7b9ed7e065c6de029385d40de1f7cb0aed3a9108 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:52:57 -0800
|
||||
Subject: [PATCH 099/217] Documentation: Enhance libcxl memdev API
|
||||
documentation
|
||||
|
||||
In preparation for adding documentation for more objects, organize the
|
||||
current into subsections and flesh out descriptions for the current APIs.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298557771.3021641.14904324834528700206.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/copyright.txt | 2 +-
|
||||
Documentation/cxl/lib/libcxl.txt | 111 +++++++++++++++++++++++++++----
|
||||
2 files changed, 99 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/Documentation/copyright.txt b/Documentation/copyright.txt
|
||||
index a9380e1..af9caf7 100644
|
||||
--- a/Documentation/copyright.txt
|
||||
+++ b/Documentation/copyright.txt
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
COPYRIGHT
|
||||
---------
|
||||
-Copyright (C) 2016 - 2020, Intel Corporation. License GPLv2: GNU GPL
|
||||
+Copyright (C) 2016 - 2022, Intel Corporation. License GPLv2: GNU GPL
|
||||
version 2 <http://gnu.org/licenses/gpl.html>. This is free software:
|
||||
you are free to change and redistribute it. There is NO WARRANTY, to
|
||||
the extent permitted by law.
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index 2539369..c127326 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -20,27 +20,100 @@ libcxl provides interfaces to interact with CXL devices in Linux, using sysfs
|
||||
interfaces for most kernel interactions, and the ioctl() interface for command
|
||||
submission.
|
||||
|
||||
-The starting point for all library interfaces is a 'cxl_ctx' object, returned
|
||||
-by linklibcxl:cxl_new[3]. CXL 'Type 3' memory devices are children of the
|
||||
-cxl_ctx object, and can be iterated through using an iterator API.
|
||||
+The starting point for all library interfaces is a 'cxl_ctx' object,
|
||||
+returned by linklibcxl:cxl_new[3]. CXL 'Type 3' memory devices and other
|
||||
+CXL device objects are descendants of the cxl_ctx object, and can be
|
||||
+iterated via an object an iterator API of the form
|
||||
+cxl_<object>_foreach(<parent object>, <object iterator>).
|
||||
|
||||
-Library level interfaces that are agnostic to any device, or a specific
|
||||
-subclass of operations have the prefix 'cxl_'
|
||||
+MEMDEVS
|
||||
+-------
|
||||
+The object representing a CXL memory expander (Type 3 device) is 'struct
|
||||
+cxl_memdev'. Library interfaces related to these devices have the prefix
|
||||
+'cxl_memdev_'. These interfaces are mostly associated with sysfs
|
||||
+interactions (unless otherwise noted in their respective documentation
|
||||
+sections). They are typically used to retrieve data published by the
|
||||
+kernel, or to send data or trigger kernel operations for a given device.
|
||||
|
||||
-The object representing a CXL Type 3 device is 'cxl_memdev'. Library interfaces
|
||||
-related to these devices have the prefix 'cxl_memdev_'. These interfaces are
|
||||
-mostly associated with sysfs interactions (unless otherwise noted in their
|
||||
-respective documentation pages). They are typically used to retrieve data
|
||||
-published by the kernel, or to send data or trigger kernel operations for a
|
||||
-given device.
|
||||
+=== MEMDEV: Enumeration
|
||||
+----
|
||||
+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);
|
||||
+
|
||||
+#define cxl_memdev_foreach(ctx, memdev) \
|
||||
+ for (memdev = cxl_memdev_get_first(ctx); \
|
||||
+ memdev != NULL; \
|
||||
+ memdev = cxl_memdev_get_next(memdev))
|
||||
+
|
||||
+----
|
||||
+
|
||||
+CXL memdev instances are enumerated from the global library context
|
||||
+'struct cxl_ctx'. By default a memdev only offers a portal to submit
|
||||
+memory device commands, see the port, decoder, and endpoint APIs to
|
||||
+determine what if any CXL Memory Resources are reachable given a
|
||||
+specific memdev.
|
||||
+
|
||||
+=== MEMDEV: Attributes
|
||||
+----
|
||||
+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);
|
||||
+int cxl_memdev_get_major(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_get_minor(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);
|
||||
+const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
+size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
||||
+----
|
||||
+
|
||||
+A memdev is given a kernel device name of the form "mem%d" where an id
|
||||
+(cxl_memdev_get_id()) is dynamically allocated as devices are
|
||||
+discovered. Note that there are no guarantees that ids / kernel device
|
||||
+names for memdevs are stable from one boot to the next, devices are
|
||||
+enumerated asynchronously. If a stable identifier is use
|
||||
+cxl_memdev_get_serial() which returns a value according to the 'Device
|
||||
+Serial Number Extended Capability' in the PCIe 5.0 Base Specification.
|
||||
+
|
||||
+The character device node for command submission can be found by default
|
||||
+at /dev/cxl/mem%d, or created with a major / minor returned from
|
||||
+cxl_memdev_get_{major,minor}().
|
||||
+
|
||||
+The 'pmem_size' and 'ram_size' attributes return the current
|
||||
+provisioning of DPA (Device Physical Address / local capacity) in the
|
||||
+device.
|
||||
+
|
||||
+=== MEMDEV: Commands
|
||||
+----
|
||||
+struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
+struct cxl_cmd *cxl_cmd_new_identify(struct cxl_memdev *memdev);
|
||||
+struct cxl_cmd *cxl_cmd_new_get_health_info(struct cxl_memdev *memdev);
|
||||
+struct cxl_cmd *cxl_cmd_new_read_label(struct cxl_memdev *memdev,
|
||||
+ unsigned int offset, unsigned int length);
|
||||
+struct cxl_cmd *cxl_cmd_new_write_label(struct cxl_memdev *memdev, void *buf,
|
||||
+ unsigned int offset, unsigned int length);
|
||||
+int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length,
|
||||
+ size_t offset);
|
||||
+int cxl_memdev_read_label(struct cxl_memdev *memdev, void *buf, size_t length,
|
||||
+ size_t offset);
|
||||
+int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
|
||||
+ size_t offset);
|
||||
+
|
||||
+----
|
||||
|
||||
A 'cxl_cmd' is a reference counted object which is used to perform 'Mailbox'
|
||||
commands as described in the CXL Specification. A 'cxl_cmd' object is tied to a
|
||||
'cxl_memdev'. Associated library interfaces have the prefix 'cxl_cmd_'. Within
|
||||
this sub-class of interfaces, there are:
|
||||
|
||||
- * 'cxl_cmd_new_*' interfaces that allocate a new cxl_cmd object for a given
|
||||
- command type.
|
||||
+ * 'cxl_cmd_new_*()' interfaces that allocate a new cxl_cmd object for a given
|
||||
+ command type targeted at a given memdev. As part of the command
|
||||
+ instantiation process the library validates that the command is
|
||||
+ supported by the memory device, otherwise it returns NULL to indicate
|
||||
+ 'no support'. The libcxl command id is translated by the kernel into
|
||||
+ a CXL standard opcode. See the potential command ids in
|
||||
+ /usr/include/linux/cxl_mem.h.
|
||||
|
||||
* 'cxl_cmd_submit' which submits the command via ioctl()
|
||||
|
||||
@@ -49,6 +122,18 @@ this sub-class of interfaces, there are:
|
||||
|
||||
* 'cxl_cmd_get_*' interfaces to get general command related information.
|
||||
|
||||
+cxl_cmd_new_raw() supports so called 'RAW' commands where the command id
|
||||
+is 'RAW' and it carries an unmodified CXL memory device command payload
|
||||
+associated with the 'opcode' argument. Given the kernel does minimal
|
||||
+input validation on these commands typically raw commands are not
|
||||
+supported by the kernel outside debug build scenarios. libcxl is limited
|
||||
+to supporting commands that appear in the CXL standard / public
|
||||
+specifications.
|
||||
+
|
||||
+cxl_memdev{read,write,zero}_label() are helpers for marshaling multiple
|
||||
+label access commands over an arbitrary extent of the device's label
|
||||
+area.
|
||||
+
|
||||
include::../../copyright.txt[]
|
||||
|
||||
SEE ALSO
|
||||
--
|
||||
2.27.0
|
||||
|
739
SOURCES/0100-cxl-list-Add-bus-objects.patch
Normal file
739
SOURCES/0100-cxl-list-Add-bus-objects.patch
Normal file
@ -0,0 +1,739 @@
|
||||
From 9dce91c303720a336c55ecdc2e01e423589b85b2 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:02 -0800
|
||||
Subject: [PATCH 100/217] cxl/list: Add bus objects
|
||||
|
||||
A 'struct cxl_bus' represents a CXL.mem domain. It is the root of a
|
||||
Host-managed Device Memory (HDM) hierarchy. When memory devices are enabled
|
||||
for CXL operation they appear underneath a bus in a 'cxl list -BM' listing,
|
||||
otherwise they display as disconnected.
|
||||
|
||||
A 'bus' is identical to the kernel's CXL root port object, but given the
|
||||
confusion between CXL root ports, and PCIe root ports, the 'bus' name is
|
||||
less ambiguous. It also serves a similar role in the object hierarchy as a
|
||||
'struct ndctl_bus' object. It is also the case that the "root" name will
|
||||
appear as the kernel device-name, so the association will be clear.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298558278.3021641.16323855851736615358.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.clang-format | 1 +
|
||||
Documentation/cxl/cxl-list.txt | 88 ++++++++++++++++---
|
||||
Documentation/cxl/lib/libcxl.txt | 30 +++++++
|
||||
cxl/filter.c | 117 ++++++++++++++++++++++++-
|
||||
cxl/filter.h | 2 +
|
||||
cxl/json.c | 21 +++++
|
||||
cxl/json.h | 5 +-
|
||||
cxl/lib/libcxl.c | 142 +++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 5 ++
|
||||
cxl/lib/private.h | 14 +++
|
||||
cxl/libcxl.h | 11 +++
|
||||
cxl/list.c | 19 +++--
|
||||
12 files changed, 431 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/.clang-format b/.clang-format
|
||||
index d2e77d0..1154c76 100644
|
||||
--- a/.clang-format
|
||||
+++ b/.clang-format
|
||||
@@ -78,6 +78,7 @@ ExperimentalAutoDetectBinPacking: false
|
||||
# | sort -u)
|
||||
ForEachMacros:
|
||||
- 'cxl_memdev_foreach'
|
||||
+ - 'cxl_bus_foreach'
|
||||
- 'daxctl_dev_foreach'
|
||||
- 'daxctl_mapping_foreach'
|
||||
- 'daxctl_region_foreach'
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 224c972..be131ae 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -15,17 +15,60 @@ SYNOPSIS
|
||||
Walk the CXL capable device hierarchy in the system and list all device
|
||||
instances along with some of their major attributes.
|
||||
|
||||
-Options can be specified to limit the output to specific objects.
|
||||
+Options can be specified to limit the output to specific objects. When a
|
||||
+single object type is specified the return json object is an array of
|
||||
+just those objects, when multiple objects types are specified the
|
||||
+returned the returned object may be an array of arrays with the inner
|
||||
+array named for the given object type.
|
||||
+
|
||||
+Filters can by specifed as either a single identidier, a space separated
|
||||
+quoted string, or a comma separated list. When multiple filter
|
||||
+identifiers are specified within a filter string, like "-m
|
||||
+mem0,mem1,mem2", they are combined as an 'OR' filter. When multiple
|
||||
+filter string types are specified, like "-m mem0,mem1,mem2 -p port10",
|
||||
+they are combined as an 'AND' filter. So, "-m mem0,mem1,mem2 -p port10"
|
||||
+would only list objects that are beneath port10 AND map mem0, mem1, OR
|
||||
+mem2.
|
||||
+
|
||||
+The --human option in addition to reformatting some fields to more human
|
||||
+friendly strings also unwraps the array to reduce the number of lines of
|
||||
+output.
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
----
|
||||
# cxl list --memdevs
|
||||
-{
|
||||
- "memdev":"mem0",
|
||||
- "pmem_size":268435456,
|
||||
- "ram_size":0,
|
||||
-}
|
||||
+[
|
||||
+ {
|
||||
+ "memdev":"mem0",
|
||||
+ "pmem_size":268435456,
|
||||
+ "ram_size":0,
|
||||
+ "serial":0
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
+# cxl list -BMu
|
||||
+[
|
||||
+ {
|
||||
+ "anon memdevs":[
|
||||
+ {
|
||||
+ "memdev":"mem0",
|
||||
+ "pmem_size":"256.00 MiB (268.44 MB)",
|
||||
+ "ram_size":0,
|
||||
+ "serial":"0"
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ {
|
||||
+ "buses":[
|
||||
+ {
|
||||
+ "bus":"root0",
|
||||
+ "provider":"ACPI.CXL"
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+]
|
||||
+
|
||||
----
|
||||
|
||||
OPTIONS
|
||||
@@ -34,13 +77,6 @@ OPTIONS
|
||||
--memdev=::
|
||||
Specify CXL memory device name(s), or device id(s), to filter the listing. For example:
|
||||
----
|
||||
-# cxl list --memdev=mem0
|
||||
-{
|
||||
- "memdev":"mem0",
|
||||
- "pmem_size":268435456,
|
||||
- "ram_size":0,
|
||||
-}
|
||||
-
|
||||
# cxl list -M --memdev="0 mem3 5"
|
||||
[
|
||||
{
|
||||
@@ -114,6 +150,32 @@ OPTIONS
|
||||
]
|
||||
----
|
||||
|
||||
+-B::
|
||||
+--buses::
|
||||
+ Include 'bus' / CXL root object(s) in the listing. Typically, on ACPI
|
||||
+ systems the bus object is a singleton associated with the ACPI0017
|
||||
+ device, but there are test scenerios where there may be multiple CXL
|
||||
+ memory hierarchies.
|
||||
+----
|
||||
+# cxl list -B
|
||||
+[
|
||||
+ {
|
||||
+ "bus":"root3",
|
||||
+ "provider":"cxl_test"
|
||||
+ },
|
||||
+ {
|
||||
+ "bus":"root0",
|
||||
+ "provider":"ACPI.CXL"
|
||||
+ }
|
||||
+]
|
||||
+----
|
||||
+
|
||||
+-b::
|
||||
+--bus=::
|
||||
+ Specify CXL root device name(s), device id(s), and / or CXL bus provider
|
||||
+ names to filter the listing. The supported provider names are "ACPI.CXL"
|
||||
+ and "cxl_test".
|
||||
+
|
||||
include::human-option.txt[]
|
||||
|
||||
include::verbose-option.txt[]
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index c127326..84af66a 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -134,6 +134,36 @@ cxl_memdev{read,write,zero}_label() are helpers for marshaling multiple
|
||||
label access commands over an arbitrary extent of the device's label
|
||||
area.
|
||||
|
||||
+BUSES
|
||||
+-----
|
||||
+The CXL Memory space is CPU and Device coherent. The address ranges that
|
||||
+support coherent access are described by platform firmware and
|
||||
+communicated to the operating system via a CXL root object 'struct
|
||||
+cxl_bus'.
|
||||
+
|
||||
+=== BUS: Enumeration
|
||||
+----
|
||||
+struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx);
|
||||
+struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus);
|
||||
+
|
||||
+#define cxl_bus_foreach(ctx, bus) \
|
||||
+ for (bus = cxl_bus_get_first(ctx); bus != NULL; \
|
||||
+ bus = cxl_bus_get_next(bus))
|
||||
+----
|
||||
+
|
||||
+=== BUS: Attributes
|
||||
+----
|
||||
+const char *cxl_bus_get_provider(struct cxl_bus *bus);
|
||||
+const char *cxl_bus_get_devname(struct cxl_bus *bus);
|
||||
+int cxl_bus_get_id(struct cxl_bus *bus);
|
||||
+----
|
||||
+
|
||||
+The provider name of a bus is a persistent name that is independent of
|
||||
+discovery order. The possible provider names are 'ACPI.CXL' and
|
||||
+'cxl_test'. The devname and id attributes, like other objects, are just
|
||||
+the kernel device names that are subject to change based on discovery
|
||||
+order.
|
||||
+
|
||||
include::../../copyright.txt[]
|
||||
|
||||
SEE ALSO
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 26efc65..5f4844b 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
-// Copyright (C) 2015-2020 Intel Corporation. All rights reserved.
|
||||
+// Copyright (C) 2015-2022 Intel Corporation. All rights reserved.
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -21,6 +21,43 @@ static const char *which_sep(const char *filter)
|
||||
return " ";
|
||||
}
|
||||
|
||||
+static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus,
|
||||
+ const char *__ident)
|
||||
+{
|
||||
+ char *ident, *save;
|
||||
+ const char *arg;
|
||||
+ int bus_id;
|
||||
+
|
||||
+ if (!__ident)
|
||||
+ return bus;
|
||||
+
|
||||
+ ident = strdup(__ident);
|
||||
+ if (!ident)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg;
|
||||
+ arg = strtok_r(NULL, which_sep(__ident), &save)) {
|
||||
+ if (strcmp(arg, "all") == 0)
|
||||
+ break;
|
||||
+
|
||||
+ if ((sscanf(arg, "%d", &bus_id) == 1 ||
|
||||
+ sscanf(arg, "root%d", &bus_id) == 1) &&
|
||||
+ cxl_bus_get_id(bus) == bus_id)
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(arg, cxl_bus_get_devname(bus)) == 0)
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(arg, cxl_bus_get_provider(bus)) == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ free(ident);
|
||||
+ if (arg)
|
||||
+ return bus;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static struct cxl_memdev *
|
||||
util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials)
|
||||
{
|
||||
@@ -98,21 +135,67 @@ static unsigned long params_to_flags(struct cxl_filter_params *param)
|
||||
return flags;
|
||||
}
|
||||
|
||||
+static void splice_array(struct cxl_filter_params *p, struct json_object *jobjs,
|
||||
+ struct json_object *platform,
|
||||
+ const char *container_name, bool do_container)
|
||||
+{
|
||||
+ size_t count;
|
||||
+
|
||||
+ if (!json_object_array_length(jobjs)) {
|
||||
+ json_object_put(jobjs);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (do_container) {
|
||||
+ struct json_object *container = json_object_new_object();
|
||||
+
|
||||
+ if (!container) {
|
||||
+ err(p, "failed to list: %s\n", container_name);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ json_object_object_add(container, container_name, jobjs);
|
||||
+ json_object_array_add(platform, container);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (count = json_object_array_length(jobjs); count; count--) {
|
||||
+ struct json_object *jobj = json_object_array_get_idx(jobjs, 0);
|
||||
+
|
||||
+ json_object_get(jobj);
|
||||
+ json_object_array_del_idx(jobjs, 0, 1);
|
||||
+ json_object_array_add(platform, jobj);
|
||||
+ }
|
||||
+ json_object_put(jobjs);
|
||||
+}
|
||||
+
|
||||
int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
{
|
||||
struct json_object *jplatform = json_object_new_array();
|
||||
+ struct json_object *jdevs = NULL, *jbuses = NULL;
|
||||
unsigned long flags = params_to_flags(p);
|
||||
struct cxl_memdev *memdev;
|
||||
+ int top_level_objs = 0;
|
||||
+ struct cxl_bus *bus;
|
||||
|
||||
if (!jplatform) {
|
||||
dbg(p, "platform object allocation failure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+ jdevs = json_object_new_array();
|
||||
+ if (!jdevs)
|
||||
+ goto err;
|
||||
+
|
||||
+ jbuses = json_object_new_array();
|
||||
+ if (!jbuses)
|
||||
+ goto err;
|
||||
+
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
struct json_object *jdev;
|
||||
|
||||
- if (!util_cxl_memdev_filter(memdev, p->memdev_filter, p->serial_filter))
|
||||
+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter,
|
||||
+ p->serial_filter))
|
||||
continue;
|
||||
if (p->memdevs) {
|
||||
jdev = util_cxl_memdev_to_json(memdev, flags);
|
||||
@@ -120,11 +203,39 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
dbg(p, "memdev object allocation failure\n");
|
||||
continue;
|
||||
}
|
||||
- json_object_array_add(jplatform, jdev);
|
||||
+ json_object_array_add(jdevs, jdev);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cxl_bus_foreach(ctx, bus) {
|
||||
+ struct json_object *jbus;
|
||||
+
|
||||
+ if (!util_cxl_bus_filter(bus, p->bus_filter))
|
||||
+ continue;
|
||||
+ if (p->buses) {
|
||||
+ jbus = util_cxl_bus_to_json(bus, flags);
|
||||
+ if (!jbus) {
|
||||
+ dbg(p, "bus object allocation failure\n");
|
||||
+ continue;
|
||||
+ }
|
||||
+ json_object_array_add(jbuses, jbus);
|
||||
}
|
||||
}
|
||||
|
||||
+ if (json_object_array_length(jdevs))
|
||||
+ top_level_objs++;
|
||||
+ if (json_object_array_length(jbuses))
|
||||
+ top_level_objs++;
|
||||
+
|
||||
+ splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1);
|
||||
+ splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1);
|
||||
+
|
||||
util_display_json_array(stdout, jplatform, flags);
|
||||
|
||||
return 0;
|
||||
+err:
|
||||
+ json_object_put(jdevs);
|
||||
+ json_object_put(jbuses);
|
||||
+ json_object_put(jplatform);
|
||||
+ return -ENOMEM;
|
||||
}
|
||||
diff --git a/cxl/filter.h b/cxl/filter.h
|
||||
index 12d9344..d41e757 100644
|
||||
--- a/cxl/filter.h
|
||||
+++ b/cxl/filter.h
|
||||
@@ -9,7 +9,9 @@
|
||||
struct cxl_filter_params {
|
||||
const char *memdev_filter;
|
||||
const char *serial_filter;
|
||||
+ const char *bus_filter;
|
||||
bool memdevs;
|
||||
+ bool buses;
|
||||
bool idle;
|
||||
bool human;
|
||||
bool health;
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index d8e65df..a584594 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -221,3 +221,24 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
}
|
||||
return jdev;
|
||||
}
|
||||
+
|
||||
+struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ const char *devname = cxl_bus_get_devname(bus);
|
||||
+ struct json_object *jbus, *jobj;
|
||||
+
|
||||
+ jbus = json_object_new_object();
|
||||
+ if (!jbus)
|
||||
+ return NULL;
|
||||
+
|
||||
+ jobj = json_object_new_string(devname);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jbus, "bus", jobj);
|
||||
+
|
||||
+ jobj = json_object_new_string(cxl_bus_get_provider(bus));
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jbus, "provider", jobj);
|
||||
+
|
||||
+ return jbus;
|
||||
+}
|
||||
diff --git a/cxl/json.h b/cxl/json.h
|
||||
index 3abcfe6..4abf6e5 100644
|
||||
--- a/cxl/json.h
|
||||
+++ b/cxl/json.h
|
||||
@@ -1,8 +1,11 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
-/* Copyright (C) 2015-2020 Intel Corporation. All rights reserved. */
|
||||
+/* Copyright (C) 2015-2022 Intel Corporation. All rights reserved. */
|
||||
#ifndef __CXL_UTIL_JSON_H__
|
||||
#define __CXL_UTIL_JSON_H__
|
||||
struct cxl_memdev;
|
||||
struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
unsigned long flags);
|
||||
+struct cxl_bus;
|
||||
+struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
|
||||
+ unsigned long flags);
|
||||
#endif /* __CXL_UTIL_JSON_H__ */
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 9839f26..8548a45 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -40,7 +40,9 @@ struct cxl_ctx {
|
||||
int refcount;
|
||||
void *userdata;
|
||||
int memdevs_init;
|
||||
+ int buses_init;
|
||||
struct list_head memdevs;
|
||||
+ struct list_head buses;
|
||||
struct kmod_ctx *kmod_ctx;
|
||||
void *private_data;
|
||||
};
|
||||
@@ -64,6 +66,21 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
free(memdev);
|
||||
}
|
||||
|
||||
+static void __free_port(struct cxl_port *port, struct list_head *head)
|
||||
+{
|
||||
+ if (head)
|
||||
+ list_del_from(head, &port->list);
|
||||
+ free(port->dev_buf);
|
||||
+ free(port->dev_path);
|
||||
+ free(port->uport);
|
||||
+}
|
||||
+
|
||||
+static void free_bus(struct cxl_bus *bus, struct list_head *head)
|
||||
+{
|
||||
+ __free_port(&bus->port, head);
|
||||
+ free(bus);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* cxl_get_userdata - retrieve stored data pointer from library context
|
||||
* @ctx: cxl library context
|
||||
@@ -130,6 +147,7 @@ CXL_EXPORT int cxl_new(struct cxl_ctx **ctx)
|
||||
dbg(c, "log_priority=%d\n", c->ctx.log_priority);
|
||||
*ctx = c;
|
||||
list_head_init(&c->memdevs);
|
||||
+ list_head_init(&c->buses);
|
||||
c->kmod_ctx = kmod_ctx;
|
||||
|
||||
return 0;
|
||||
@@ -160,6 +178,7 @@ CXL_EXPORT struct cxl_ctx *cxl_ref(struct cxl_ctx *ctx)
|
||||
CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
|
||||
{
|
||||
struct cxl_memdev *memdev, *_d;
|
||||
+ struct cxl_bus *bus, *_b;
|
||||
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
@@ -170,6 +189,9 @@ CXL_EXPORT void cxl_unref(struct cxl_ctx *ctx)
|
||||
list_for_each_safe(&ctx->memdevs, memdev, _d, list)
|
||||
free_memdev(memdev, &ctx->memdevs);
|
||||
|
||||
+ list_for_each_safe(&ctx->buses, bus, _b, port.list)
|
||||
+ free_bus(bus, &ctx->buses);
|
||||
+
|
||||
kmod_unref(ctx->kmod_ctx);
|
||||
info(ctx, "context %p released\n", ctx);
|
||||
free(ctx);
|
||||
@@ -449,6 +471,126 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
||||
return is_enabled(path);
|
||||
}
|
||||
|
||||
+static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id,
|
||||
+ const char *cxlport_base)
|
||||
+{
|
||||
+ char *path = calloc(1, strlen(cxlport_base) + 100);
|
||||
+ size_t rc;
|
||||
+
|
||||
+ if (!path)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ port->id = id;
|
||||
+ port->ctx = ctx;
|
||||
+
|
||||
+ port->dev_path = strdup(cxlport_base);
|
||||
+ if (!port->dev_path)
|
||||
+ goto err;
|
||||
+
|
||||
+ port->dev_buf = calloc(1, strlen(cxlport_base) + 50);
|
||||
+ if (!port->dev_buf)
|
||||
+ goto err;
|
||||
+ port->buf_len = strlen(cxlport_base) + 50;
|
||||
+
|
||||
+ rc = snprintf(port->dev_buf, port->buf_len, "%s/uport", cxlport_base);
|
||||
+ if (rc >= port->buf_len)
|
||||
+ goto err;
|
||||
+ port->uport = realpath(port->dev_buf, NULL);
|
||||
+ if (!port->uport)
|
||||
+ goto err;
|
||||
+
|
||||
+ return 0;
|
||||
+err:
|
||||
+ free(port->dev_path);
|
||||
+ free(port->dev_buf);
|
||||
+ free(path);
|
||||
+ return -ENOMEM;
|
||||
+}
|
||||
+
|
||||
+static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base)
|
||||
+{
|
||||
+ const char *devname = devpath_to_devname(cxlbus_base);
|
||||
+ struct cxl_bus *bus, *bus_dup;
|
||||
+ struct cxl_ctx *ctx = parent;
|
||||
+ struct cxl_port *port;
|
||||
+ int rc;
|
||||
+
|
||||
+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlbus_base);
|
||||
+
|
||||
+ bus = calloc(1, sizeof(*bus));
|
||||
+ if (!bus)
|
||||
+ return NULL;
|
||||
+
|
||||
+ port = &bus->port;
|
||||
+ rc = cxl_port_init(port, ctx, id, cxlbus_base);
|
||||
+ if (rc)
|
||||
+ goto err;
|
||||
+
|
||||
+ cxl_bus_foreach(ctx, bus_dup)
|
||||
+ if (bus_dup->port.id == bus->port.id) {
|
||||
+ free_bus(bus, NULL);
|
||||
+ return bus_dup;
|
||||
+ }
|
||||
+
|
||||
+ list_add(&ctx->buses, &port->list);
|
||||
+ return bus;
|
||||
+
|
||||
+err:
|
||||
+ free(bus);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void cxl_buses_init(struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ if (ctx->buses_init)
|
||||
+ return;
|
||||
+
|
||||
+ ctx->buses_init = 1;
|
||||
+
|
||||
+ sysfs_device_parse(ctx, "/sys/bus/cxl/devices", "root", ctx,
|
||||
+ add_cxl_bus);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ cxl_buses_init(ctx);
|
||||
+
|
||||
+ return list_top(&ctx->buses, struct cxl_bus, port.list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = bus->port.ctx;
|
||||
+
|
||||
+ return list_next(&ctx->buses, bus, port.list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT const char *cxl_bus_get_devname(struct cxl_bus *bus)
|
||||
+{
|
||||
+ struct cxl_port *port = &bus->port;
|
||||
+
|
||||
+ return devpath_to_devname(port->dev_path);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_bus_get_id(struct cxl_bus *bus)
|
||||
+{
|
||||
+ struct cxl_port *port = &bus->port;
|
||||
+
|
||||
+ return port->id;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus)
|
||||
+{
|
||||
+ struct cxl_port *port = &bus->port;
|
||||
+ const char *devname = devpath_to_devname(port->uport);
|
||||
+
|
||||
+ if (strcmp(devname, "ACPI0017:00") == 0)
|
||||
+ return "ACPI.CXL";
|
||||
+ if (strcmp(devname, "cxl_acpi.0") == 0)
|
||||
+ return "cxl_test";
|
||||
+ return devname;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
|
||||
{
|
||||
if (!cmd)
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 4411035..781ff99 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -77,4 +77,9 @@ local:
|
||||
LIBCXL_2 {
|
||||
global:
|
||||
cxl_memdev_get_serial;
|
||||
+ cxl_bus_get_first;
|
||||
+ cxl_bus_get_next;
|
||||
+ cxl_bus_get_provider;
|
||||
+ cxl_bus_get_devname;
|
||||
+ cxl_bus_get_id;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 7c81e24..0758d05 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -34,6 +34,20 @@ struct cxl_memdev {
|
||||
unsigned long long serial;
|
||||
};
|
||||
|
||||
+struct cxl_port {
|
||||
+ int id;
|
||||
+ void *dev_buf;
|
||||
+ size_t buf_len;
|
||||
+ char *dev_path;
|
||||
+ char *uport;
|
||||
+ struct cxl_ctx *ctx;
|
||||
+ struct list_node list;
|
||||
+};
|
||||
+
|
||||
+struct cxl_bus {
|
||||
+ struct cxl_port port;
|
||||
+};
|
||||
+
|
||||
enum cxl_cmd_query_status {
|
||||
CXL_CMD_QUERY_NOT_RUN = 0,
|
||||
CXL_CMD_QUERY_OK,
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index bcdede8..da66eb2 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -57,6 +57,17 @@ int cxl_memdev_write_label(struct cxl_memdev *memdev, void *buf, size_t length,
|
||||
memdev != NULL; \
|
||||
memdev = cxl_memdev_get_next(memdev))
|
||||
|
||||
+struct cxl_bus;
|
||||
+struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx);
|
||||
+struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus);
|
||||
+const char *cxl_bus_get_provider(struct cxl_bus *bus);
|
||||
+const char *cxl_bus_get_devname(struct cxl_bus *bus);
|
||||
+int cxl_bus_get_id(struct cxl_bus *bus);
|
||||
+
|
||||
+#define cxl_bus_foreach(ctx, bus) \
|
||||
+ for (bus = cxl_bus_get_first(ctx); bus != NULL; \
|
||||
+ bus = cxl_bus_get_next(bus))
|
||||
+
|
||||
struct cxl_cmd;
|
||||
const char *cxl_cmd_get_devname(struct cxl_cmd *cmd);
|
||||
struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 7e2744d..9500e61 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -1,5 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
-/* Copyright (C) 2020-2021 Intel Corporation. All rights reserved. */
|
||||
+/* Copyright (C) 2020-2022 Intel Corporation. All rights reserved. */
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
@@ -14,11 +14,6 @@
|
||||
|
||||
static struct cxl_filter_params param;
|
||||
|
||||
-static int num_list_flags(void)
|
||||
-{
|
||||
- return param.memdevs;
|
||||
-}
|
||||
-
|
||||
static const struct option options[] = {
|
||||
OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name(s)",
|
||||
"filter by CXL memory device name(s)"),
|
||||
@@ -27,6 +22,9 @@ static const struct option options[] = {
|
||||
"filter by CXL memory device serial number(s)"),
|
||||
OPT_BOOLEAN('M', "memdevs", ¶m.memdevs,
|
||||
"include CXL memory device info"),
|
||||
+ OPT_STRING('b', "bus", ¶m.bus_filter, "bus device name",
|
||||
+ "filter by CXL bus device name(s)"),
|
||||
+ OPT_BOOLEAN('B', "buses", ¶m.buses, "include CXL bus info"),
|
||||
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
"use human friendly number formats "),
|
||||
@@ -35,6 +33,11 @@ static const struct option options[] = {
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
+static int num_list_flags(void)
|
||||
+{
|
||||
+ return !!param.memdevs + !!param.buses;
|
||||
+}
|
||||
+
|
||||
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
{
|
||||
const char * const u[] = {
|
||||
@@ -53,7 +56,9 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
if (num_list_flags() == 0) {
|
||||
if (param.memdev_filter || param.serial_filter)
|
||||
param.memdevs = true;
|
||||
- else {
|
||||
+ if (param.bus_filter)
|
||||
+ param.buses = true;
|
||||
+ if (num_list_flags() == 0) {
|
||||
/*
|
||||
* TODO: We likely want to list regions by default if
|
||||
* nothing was explicitly asked for. But until we have
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 91f78bbcda7fc644041dfabfa679c6a627f90e76 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:08 -0800
|
||||
Subject: [PATCH 101/217] util/json: Warn on stderr about empty list results
|
||||
|
||||
Help interactive users notice something is wrong with the list parameters
|
||||
by warning that no devices matched the specified filter settings.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298558814.3021641.13051269428355986099.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
util/json.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/util/json.c b/util/json.c
|
||||
index bd5f8fc..f8cc81f 100644
|
||||
--- a/util/json.c
|
||||
+++ b/util/json.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
+#include <util/util.h>
|
||||
#include <util/json.h>
|
||||
#include <json-c/json.h>
|
||||
#include <json-c/printbuf.h>
|
||||
@@ -95,9 +96,11 @@ void util_display_json_array(FILE *f_out, struct json_object *jarray,
|
||||
int len = json_object_array_length(jarray);
|
||||
int jflag = JSON_C_TO_STRING_PRETTY;
|
||||
|
||||
- if (json_object_array_length(jarray) > 1 || !(flags & UTIL_JSON_HUMAN))
|
||||
+ if (len > 1 || !(flags & UTIL_JSON_HUMAN)) {
|
||||
+ if (len == 0)
|
||||
+ warning("no matching devices found\n");
|
||||
fprintf(f_out, "%s\n", json_object_to_json_string_ext(jarray, jflag));
|
||||
- else if (len) {
|
||||
+ } else if (len) {
|
||||
struct json_object *jobj;
|
||||
|
||||
jobj = json_object_array_get_idx(jarray, 0);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,165 @@
|
||||
From ecd7e6e7aabfa2592f3f739a725d135eb43d6314 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:13 -0800
|
||||
Subject: [PATCH 102/217] util/sysfs: Uplevel modalias lookup helper to util/
|
||||
|
||||
The to_module() helper looks up modules relative to a modalias. Uplevel
|
||||
this to share with libcxl.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298559346.3021641.11059026790676662837.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 33 +++++----------------------------
|
||||
util/sysfs.c | 27 +++++++++++++++++++++++++++
|
||||
util/sysfs.h | 8 ++++++++
|
||||
3 files changed, 40 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 47a234c..1374ad9 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -1668,7 +1668,6 @@ static enum ndctl_fwa_result fwa_result_to_result(const char *result)
|
||||
static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module,
|
||||
const char *devname);
|
||||
static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath);
|
||||
-static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias);
|
||||
|
||||
static int populate_dimm_attributes(struct ndctl_dimm *dimm,
|
||||
const char *dimm_base,
|
||||
@@ -1878,7 +1877,7 @@ static void *add_dimm(void *parent, int id, const char *dimm_base)
|
||||
sprintf(path, "%s/modalias", dimm_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
goto err_read;
|
||||
- dimm->module = to_module(ctx, buf);
|
||||
+ dimm->module = util_modalias_to_module(ctx, buf);
|
||||
|
||||
dimm->handle = -1;
|
||||
dimm->phys_id = -1;
|
||||
@@ -2597,7 +2596,7 @@ static void *add_region(void *parent, int id, const char *region_base)
|
||||
sprintf(path, "%s/modalias", region_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
goto err_read;
|
||||
- region->module = to_module(ctx, buf);
|
||||
+ region->module = util_modalias_to_module(ctx, buf);
|
||||
|
||||
sprintf(path, "%s/numa_node", region_base);
|
||||
if ((rc = sysfs_read_attr(ctx, path, buf)) == 0)
|
||||
@@ -3885,28 +3884,6 @@ NDCTL_EXPORT struct ndctl_ctx *ndctl_mapping_get_ctx(
|
||||
return ndctl_mapping_get_bus(mapping)->ctx;
|
||||
}
|
||||
|
||||
-static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias)
|
||||
-{
|
||||
- struct kmod_list *list = NULL;
|
||||
- struct kmod_module *mod;
|
||||
- int rc;
|
||||
-
|
||||
- if (!ctx->kmod_ctx)
|
||||
- return NULL;
|
||||
-
|
||||
- rc = kmod_module_new_from_lookup(ctx->kmod_ctx, alias, &list);
|
||||
- if (rc < 0 || !list) {
|
||||
- dbg(ctx, "failed to find module for alias: %s %d list: %s\n",
|
||||
- alias, rc, list ? "populated" : "empty");
|
||||
- return NULL;
|
||||
- }
|
||||
- mod = kmod_module_get_module(list);
|
||||
- dbg(ctx, "alias: %s module: %s\n", alias, kmod_module_get_name(mod));
|
||||
- kmod_module_unref_list(list);
|
||||
-
|
||||
- return mod;
|
||||
-}
|
||||
-
|
||||
static char *get_block_device(struct ndctl_ctx *ctx, const char *block_path)
|
||||
{
|
||||
char *bdev_name = NULL;
|
||||
@@ -4069,7 +4046,7 @@ static void *add_namespace(void *parent, int id, const char *ndns_base)
|
||||
sprintf(path, "%s/modalias", ndns_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
goto err_read;
|
||||
- ndns->module = to_module(ctx, buf);
|
||||
+ ndns->module = util_modalias_to_module(ctx, buf);
|
||||
|
||||
ndctl_namespace_foreach(region, ndns_dup)
|
||||
if (ndns_dup->id == ndns->id) {
|
||||
@@ -5182,7 +5159,7 @@ static void *add_btt(void *parent, int id, const char *btt_base)
|
||||
sprintf(path, "%s/modalias", btt_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
goto err_read;
|
||||
- btt->module = to_module(ctx, buf);
|
||||
+ btt->module = util_modalias_to_module(ctx, buf);
|
||||
|
||||
sprintf(path, "%s/uuid", btt_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
@@ -5533,7 +5510,7 @@ static void *__add_pfn(struct ndctl_pfn *pfn, const char *pfn_base)
|
||||
sprintf(path, "%s/modalias", pfn_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
goto err_read;
|
||||
- pfn->module = to_module(ctx, buf);
|
||||
+ pfn->module = util_modalias_to_module(ctx, buf);
|
||||
|
||||
sprintf(path, "%s/uuid", pfn_base);
|
||||
if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
diff --git a/util/sysfs.c b/util/sysfs.c
|
||||
index cfbab7d..23330cb 100644
|
||||
--- a/util/sysfs.c
|
||||
+++ b/util/sysfs.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
+#include <libkmod.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -118,3 +119,29 @@ int __sysfs_device_parse(struct log_ctx *ctx, const char *base_path,
|
||||
|
||||
return add_errors;
|
||||
}
|
||||
+
|
||||
+struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx,
|
||||
+ const char *alias,
|
||||
+ struct log_ctx *log)
|
||||
+{
|
||||
+ struct kmod_list *list = NULL;
|
||||
+ struct kmod_module *mod;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (!kmod_ctx)
|
||||
+ return NULL;
|
||||
+
|
||||
+ rc = kmod_module_new_from_lookup(kmod_ctx, alias, &list);
|
||||
+ if (rc < 0 || !list) {
|
||||
+ log_dbg(log,
|
||||
+ "failed to find module for alias: %s %d list: %s\n",
|
||||
+ alias, rc, list ? "populated" : "empty");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ mod = kmod_module_get_module(list);
|
||||
+ log_dbg(log, "alias: %s module: %s\n", alias,
|
||||
+ kmod_module_get_name(mod));
|
||||
+ kmod_module_unref_list(list);
|
||||
+
|
||||
+ return mod;
|
||||
+}
|
||||
diff --git a/util/sysfs.h b/util/sysfs.h
|
||||
index 6485a73..bdee4f5 100644
|
||||
--- a/util/sysfs.h
|
||||
+++ b/util/sysfs.h
|
||||
@@ -27,4 +27,12 @@ static inline const char *devpath_to_devname(const char *devpath)
|
||||
{
|
||||
return strrchr(devpath, '/') + 1;
|
||||
}
|
||||
+
|
||||
+struct kmod_ctx;
|
||||
+struct kmod_module;
|
||||
+struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx,
|
||||
+ const char *alias,
|
||||
+ struct log_ctx *log);
|
||||
+#define util_modalias_to_module(ctx, buf) \
|
||||
+ __util_modalias_to_module((ctx)->kmod_ctx, buf, &(ctx)->ctx)
|
||||
#endif /* __UTIL_SYSFS_H__ */
|
||||
--
|
||||
2.27.0
|
||||
|
862
SOURCES/0103-cxl-list-Add-port-enumeration.patch
Normal file
862
SOURCES/0103-cxl-list-Add-port-enumeration.patch
Normal file
@ -0,0 +1,862 @@
|
||||
From fef3f05ca8cdfd8d783162042d5cf20325c8b64b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:18 -0800
|
||||
Subject: [PATCH 103/217] cxl/list: Add port enumeration
|
||||
|
||||
Between a cxl_bus (root port) and an endpoint there can be an arbitrary
|
||||
level of switches. Add enumeration for these ports at each level of the
|
||||
hierarchy.
|
||||
|
||||
However, given the CXL root ports are also "ports" infer that if the port
|
||||
filter argument is the word "root" or "root%d" then include root ports in
|
||||
the listing. The keyword "switch" is also provided to filter only the ports
|
||||
beneath the root that are not endpoint ports.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298559854.3021641.17724828997703051001.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.clang-format | 1 +
|
||||
Documentation/cxl/cxl-list.txt | 24 ++++
|
||||
Documentation/cxl/lib/libcxl.txt | 42 ++++++
|
||||
cxl/filter.c | 224 ++++++++++++++++++++++++++++++-
|
||||
cxl/filter.h | 4 +
|
||||
cxl/json.c | 23 ++++
|
||||
cxl/json.h | 3 +
|
||||
cxl/lib/libcxl.c | 160 +++++++++++++++++++++-
|
||||
cxl/lib/libcxl.sym | 12 ++
|
||||
cxl/lib/private.h | 11 ++
|
||||
cxl/libcxl.h | 19 +++
|
||||
cxl/list.c | 17 ++-
|
||||
12 files changed, 534 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/.clang-format b/.clang-format
|
||||
index 1154c76..391cd34 100644
|
||||
--- a/.clang-format
|
||||
+++ b/.clang-format
|
||||
@@ -79,6 +79,7 @@ ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros:
|
||||
- 'cxl_memdev_foreach'
|
||||
- 'cxl_bus_foreach'
|
||||
+ - 'cxl_port_foreach'
|
||||
- 'daxctl_dev_foreach'
|
||||
- 'daxctl_mapping_foreach'
|
||||
- 'daxctl_region_foreach'
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index be131ae..3076deb 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -176,6 +176,30 @@ OPTIONS
|
||||
names to filter the listing. The supported provider names are "ACPI.CXL"
|
||||
and "cxl_test".
|
||||
|
||||
+-P::
|
||||
+--ports::
|
||||
+ Include port objects (CXL / PCIe root ports + Upstream Switch Ports) in
|
||||
+ the listing.
|
||||
+
|
||||
+-p::
|
||||
+--port=::
|
||||
+ Specify CXL Port device name(s), device id(s), and or port type
|
||||
+ names to filter the listing. The supported port type names are "root"
|
||||
+ and "switch". Note that since a bus object is also a port, the following
|
||||
+ two syntaxes are equivalent:
|
||||
+----
|
||||
+# cxl list -B
|
||||
+# cxl list -P -p root
|
||||
+----
|
||||
+ By default, only 'switch' ports are listed.
|
||||
+
|
||||
+-S::
|
||||
+--single::
|
||||
+ Specify whether the listing should emit all the objects that are
|
||||
+ descendants of a port that matches the port filter, or only direct
|
||||
+ descendants of the individual ports that match the filter. By default
|
||||
+ all descendant objects are listed.
|
||||
+
|
||||
include::human-option.txt[]
|
||||
|
||||
include::verbose-option.txt[]
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index 84af66a..804e9ca 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -164,6 +164,48 @@ discovery order. The possible provider names are 'ACPI.CXL' and
|
||||
the kernel device names that are subject to change based on discovery
|
||||
order.
|
||||
|
||||
+PORTS
|
||||
+-----
|
||||
+CXL ports track the PCIe hierarchy between a platform firmware CXL root
|
||||
+object, through CXL / PCIe Host Bridges, CXL / PCIe Root Ports, and CXL
|
||||
+/ PCIe Switch Ports.
|
||||
+
|
||||
+=== PORT: Enumeration
|
||||
+----
|
||||
+struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus);
|
||||
+struct cxl_port *cxl_port_get_first(struct cxl_port *parent);
|
||||
+struct cxl_port *cxl_port_get_next(struct cxl_port *port);
|
||||
+struct cxl_port *cxl_port_get_parent(struct cxl_port *port);
|
||||
+struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
|
||||
+struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port);
|
||||
+
|
||||
+#define cxl_port_foreach(parent, port) \
|
||||
+ for (port = cxl_port_get_first(parent); port != NULL; \
|
||||
+ port = cxl_port_get_next(port))
|
||||
+----
|
||||
+A bus object encapsulates a CXL port object. Use cxl_bus_get_port() to
|
||||
+use generic port APIs on root objects.
|
||||
+
|
||||
+Ports are hierarchical. All but the a root object have another CXL port
|
||||
+as a parent object retrievable via cxl_port_get_parent().
|
||||
+
|
||||
+The root port of a hiearchy can be retrieved via any port instance in
|
||||
+that hierarchy via cxl_port_get_bus().
|
||||
+
|
||||
+=== PORT: Attributes
|
||||
+----
|
||||
+const char *cxl_port_get_devname(struct cxl_port *port);
|
||||
+int cxl_port_get_id(struct cxl_port *port);
|
||||
+int cxl_port_is_enabled(struct cxl_port *port);
|
||||
+bool cxl_port_is_root(struct cxl_port *port);
|
||||
+bool cxl_port_is_switch(struct cxl_port *port);
|
||||
+----
|
||||
+The port type is communicated via cxl_port_is_<type>(). An 'enabled' port
|
||||
+is one that has succeeded in discovering the CXL component registers in
|
||||
+the host device and has enumerated its downstream ports. In order for a
|
||||
+memdev to be enabled for CXL memory operation all CXL ports in its
|
||||
+ancestry must also be enabled.
|
||||
+
|
||||
include::../../copyright.txt[]
|
||||
|
||||
SEE ALSO
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 5f4844b..8b79db3 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -21,6 +21,101 @@ static const char *which_sep(const char *filter)
|
||||
return " ";
|
||||
}
|
||||
|
||||
+bool cxl_filter_has(const char *__filter, const char *needle)
|
||||
+{
|
||||
+ char *filter, *save;
|
||||
+ const char *arg;
|
||||
+
|
||||
+ if (!needle)
|
||||
+ return true;
|
||||
+
|
||||
+ if (!__filter)
|
||||
+ return false;
|
||||
+
|
||||
+ filter = strdup(__filter);
|
||||
+ if (!filter)
|
||||
+ return false;
|
||||
+
|
||||
+ for (arg = strtok_r(filter, which_sep(__filter), &save); arg;
|
||||
+ arg = strtok_r(NULL, which_sep(__filter), &save))
|
||||
+ if (strstr(arg, needle))
|
||||
+ break;
|
||||
+
|
||||
+ free(filter);
|
||||
+ if (arg)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port,
|
||||
+ const char *__ident)
|
||||
+{
|
||||
+ char *ident, *save;
|
||||
+ const char *arg;
|
||||
+ int port_id;
|
||||
+
|
||||
+ if (!__ident)
|
||||
+ return port;
|
||||
+
|
||||
+ ident = strdup(__ident);
|
||||
+ if (!ident)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg;
|
||||
+ arg = strtok_r(NULL, which_sep(__ident), &save)) {
|
||||
+ if (strcmp(arg, "all") == 0)
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(arg, "root") == 0 && cxl_port_is_root(port))
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(arg, "switch") == 0 && cxl_port_is_switch(port))
|
||||
+ break;
|
||||
+
|
||||
+ if ((sscanf(arg, "%d", &port_id) == 1 ||
|
||||
+ sscanf(arg, "port%d", &port_id) == 1) &&
|
||||
+ cxl_port_get_id(port) == port_id)
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(arg, cxl_port_get_devname(port)) == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ free(ident);
|
||||
+ if (arg)
|
||||
+ return port;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+enum cxl_port_filter_mode {
|
||||
+ CXL_PF_SINGLE,
|
||||
+ CXL_PF_ANCESTRY,
|
||||
+};
|
||||
+
|
||||
+static enum cxl_port_filter_mode pf_mode(struct cxl_filter_params *p)
|
||||
+{
|
||||
+ if (p->single)
|
||||
+ return CXL_PF_SINGLE;
|
||||
+ return CXL_PF_ANCESTRY;
|
||||
+}
|
||||
+
|
||||
+static struct cxl_port *util_cxl_port_filter(struct cxl_port *port,
|
||||
+ const char *ident,
|
||||
+ enum cxl_port_filter_mode mode)
|
||||
+{
|
||||
+ struct cxl_port *iter = port;
|
||||
+
|
||||
+ while (iter) {
|
||||
+ if (__util_cxl_port_filter(iter, ident))
|
||||
+ return port;
|
||||
+ if (mode == CXL_PF_SINGLE)
|
||||
+ return NULL;
|
||||
+ iter = cxl_port_get_parent(iter);
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus,
|
||||
const char *__ident)
|
||||
{
|
||||
@@ -58,6 +153,31 @@ static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct cxl_port *util_cxl_port_filter_by_bus(struct cxl_port *port,
|
||||
+ const char *__ident)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
+ struct cxl_bus *bus;
|
||||
+
|
||||
+ if (!__ident)
|
||||
+ return port;
|
||||
+
|
||||
+ if (cxl_port_is_root(port)) {
|
||||
+ bus = cxl_port_to_bus(port);
|
||||
+ bus = util_cxl_bus_filter(bus, __ident);
|
||||
+ return bus ? port : NULL;
|
||||
+ }
|
||||
+
|
||||
+ cxl_bus_foreach(ctx, bus) {
|
||||
+ if (!util_cxl_bus_filter(bus, __ident))
|
||||
+ continue;
|
||||
+ if (bus == cxl_port_get_bus(port))
|
||||
+ return port;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static struct cxl_memdev *
|
||||
util_cxl_memdev_serial_filter(struct cxl_memdev *memdev, const char *__serials)
|
||||
{
|
||||
@@ -169,10 +289,82 @@ static void splice_array(struct cxl_filter_params *p, struct json_object *jobjs,
|
||||
json_object_put(jobjs);
|
||||
}
|
||||
|
||||
+static bool cond_add_put_array(struct json_object *jobj, const char *key,
|
||||
+ struct json_object *array)
|
||||
+{
|
||||
+ if (jobj && array && json_object_array_length(array) > 0) {
|
||||
+ json_object_object_add(jobj, key, array);
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ json_object_put(array);
|
||||
+ return false;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static bool cond_add_put_array_suffix(struct json_object *jobj, const char *key,
|
||||
+ const char *suffix,
|
||||
+ struct json_object *array)
|
||||
+{
|
||||
+ char *name;
|
||||
+ bool rc;
|
||||
+
|
||||
+ if (asprintf(&name, "%s:%s", key, suffix) < 0)
|
||||
+ return false;
|
||||
+ rc = cond_add_put_array(jobj, name, array);
|
||||
+ free(name);
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static struct json_object *pick_array(struct json_object *child,
|
||||
+ struct json_object *container)
|
||||
+{
|
||||
+ if (child)
|
||||
+ return child;
|
||||
+ if (container)
|
||||
+ return container;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void walk_child_ports(struct cxl_port *parent_port,
|
||||
+ struct cxl_filter_params *p,
|
||||
+ struct json_object *jports,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ struct cxl_port *port;
|
||||
+
|
||||
+ cxl_port_foreach(parent_port, port) {
|
||||
+ const char *devname = cxl_port_get_devname(port);
|
||||
+ struct json_object *jport = NULL;
|
||||
+ struct json_object *jchildports = NULL;
|
||||
+
|
||||
+ if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
|
||||
+ goto walk_children;
|
||||
+ if (!util_cxl_port_filter_by_bus(port, p->bus_filter))
|
||||
+ goto walk_children;
|
||||
+ if (!p->idle && !cxl_port_is_enabled(port))
|
||||
+ continue;
|
||||
+ if (p->ports)
|
||||
+ jport = util_cxl_port_to_json(port, flags);
|
||||
+ if (!jport)
|
||||
+ continue;
|
||||
+ json_object_array_add(jports, jport);
|
||||
+ jchildports = json_object_new_array();
|
||||
+ if (!jchildports) {
|
||||
+ err(p, "%s: failed to enumerate child ports\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+walk_children:
|
||||
+ walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
+ flags);
|
||||
+ cond_add_put_array_suffix(jport, "ports", devname, jchildports);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
{
|
||||
+ struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL;
|
||||
struct json_object *jplatform = json_object_new_array();
|
||||
- struct json_object *jdevs = NULL, *jbuses = NULL;
|
||||
unsigned long flags = params_to_flags(p);
|
||||
struct cxl_memdev *memdev;
|
||||
int top_level_objs = 0;
|
||||
@@ -191,6 +383,10 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
if (!jbuses)
|
||||
goto err;
|
||||
|
||||
+ jports = json_object_new_array();
|
||||
+ if (!jports)
|
||||
+ goto err;
|
||||
+
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
struct json_object *jdev;
|
||||
|
||||
@@ -208,10 +404,15 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
}
|
||||
|
||||
cxl_bus_foreach(ctx, bus) {
|
||||
- struct json_object *jbus;
|
||||
+ struct json_object *jbus = NULL;
|
||||
+ struct json_object *jchildports = NULL;
|
||||
+ struct cxl_port *port = cxl_bus_get_port(bus);
|
||||
+ const char *devname = cxl_bus_get_devname(bus);
|
||||
|
||||
if (!util_cxl_bus_filter(bus, p->bus_filter))
|
||||
- continue;
|
||||
+ goto walk_children;
|
||||
+ if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
|
||||
+ goto walk_children;
|
||||
if (p->buses) {
|
||||
jbus = util_cxl_bus_to_json(bus, flags);
|
||||
if (!jbus) {
|
||||
@@ -219,16 +420,32 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
continue;
|
||||
}
|
||||
json_object_array_add(jbuses, jbus);
|
||||
+ if (p->ports) {
|
||||
+ jchildports = json_object_new_array();
|
||||
+ if (!jchildports) {
|
||||
+ err(p,
|
||||
+ "%s: failed to enumerate child ports\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+walk_children:
|
||||
+ walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
+ flags);
|
||||
+ cond_add_put_array_suffix(jbus, "ports", devname, jchildports);
|
||||
}
|
||||
|
||||
if (json_object_array_length(jdevs))
|
||||
top_level_objs++;
|
||||
if (json_object_array_length(jbuses))
|
||||
top_level_objs++;
|
||||
+ if (json_object_array_length(jports))
|
||||
+ top_level_objs++;
|
||||
|
||||
splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1);
|
||||
splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1);
|
||||
+ splice_array(p, jports, jplatform, "ports", top_level_objs > 1);
|
||||
|
||||
util_display_json_array(stdout, jplatform, flags);
|
||||
|
||||
@@ -236,6 +453,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
err:
|
||||
json_object_put(jdevs);
|
||||
json_object_put(jbuses);
|
||||
+ json_object_put(jports);
|
||||
json_object_put(jplatform);
|
||||
return -ENOMEM;
|
||||
}
|
||||
diff --git a/cxl/filter.h b/cxl/filter.h
|
||||
index d41e757..0d83304 100644
|
||||
--- a/cxl/filter.h
|
||||
+++ b/cxl/filter.h
|
||||
@@ -10,7 +10,10 @@ struct cxl_filter_params {
|
||||
const char *memdev_filter;
|
||||
const char *serial_filter;
|
||||
const char *bus_filter;
|
||||
+ const char *port_filter;
|
||||
+ bool single;
|
||||
bool memdevs;
|
||||
+ bool ports;
|
||||
bool buses;
|
||||
bool idle;
|
||||
bool human;
|
||||
@@ -22,4 +25,5 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
const char *__ident,
|
||||
const char *serials);
|
||||
int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *param);
|
||||
+bool cxl_filter_has(const char *needle, const char *__filter);
|
||||
#endif /* _CXL_UTIL_FILTER_H_ */
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index a584594..d9f864e 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -242,3 +242,26 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
|
||||
|
||||
return jbus;
|
||||
}
|
||||
+
|
||||
+struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ const char *devname = cxl_port_get_devname(port);
|
||||
+ struct json_object *jport, *jobj;
|
||||
+
|
||||
+ jport = json_object_new_object();
|
||||
+ if (!jport)
|
||||
+ return NULL;
|
||||
+
|
||||
+ jobj = json_object_new_string(devname);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jport, "port", jobj);
|
||||
+
|
||||
+ if (!cxl_port_is_enabled(port)) {
|
||||
+ jobj = json_object_new_string("disabled");
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jport, "state", jobj);
|
||||
+ }
|
||||
+
|
||||
+ return jport;
|
||||
+}
|
||||
diff --git a/cxl/json.h b/cxl/json.h
|
||||
index 4abf6e5..36653db 100644
|
||||
--- a/cxl/json.h
|
||||
+++ b/cxl/json.h
|
||||
@@ -8,4 +8,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
struct cxl_bus;
|
||||
struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
|
||||
unsigned long flags);
|
||||
+struct cxl_port;
|
||||
+struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
+ unsigned long flags);
|
||||
#endif /* __CXL_UTIL_JSON_H__ */
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 8548a45..03eff3c 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -66,15 +66,27 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
free(memdev);
|
||||
}
|
||||
|
||||
+static void free_port(struct cxl_port *port, struct list_head *head);
|
||||
static void __free_port(struct cxl_port *port, struct list_head *head)
|
||||
{
|
||||
+ struct cxl_port *child, *_c;
|
||||
+
|
||||
if (head)
|
||||
list_del_from(head, &port->list);
|
||||
+ list_for_each_safe(&port->child_ports, child, _c, list)
|
||||
+ free_port(child, &port->child_ports);
|
||||
+ kmod_module_unref(port->module);
|
||||
free(port->dev_buf);
|
||||
free(port->dev_path);
|
||||
free(port->uport);
|
||||
}
|
||||
|
||||
+static void free_port(struct cxl_port *port, struct list_head *head)
|
||||
+{
|
||||
+ __free_port(port, head);
|
||||
+ free(port);
|
||||
+}
|
||||
+
|
||||
static void free_bus(struct cxl_bus *bus, struct list_head *head)
|
||||
{
|
||||
__free_port(&bus->port, head);
|
||||
@@ -471,10 +483,12 @@ CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
||||
return is_enabled(path);
|
||||
}
|
||||
|
||||
-static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id,
|
||||
+static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port,
|
||||
+ enum cxl_port_type type, struct cxl_ctx *ctx, int id,
|
||||
const char *cxlport_base)
|
||||
{
|
||||
char *path = calloc(1, strlen(cxlport_base) + 100);
|
||||
+ char buf[SYSFS_ATTR_SIZE];
|
||||
size_t rc;
|
||||
|
||||
if (!path)
|
||||
@@ -482,6 +496,10 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id,
|
||||
|
||||
port->id = id;
|
||||
port->ctx = ctx;
|
||||
+ port->type = type;
|
||||
+ port->parent = parent_port;
|
||||
+
|
||||
+ list_head_init(&port->child_ports);
|
||||
|
||||
port->dev_path = strdup(cxlport_base);
|
||||
if (!port->dev_path)
|
||||
@@ -499,6 +517,10 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_ctx *ctx, int id,
|
||||
if (!port->uport)
|
||||
goto err;
|
||||
|
||||
+ sprintf(path, "%s/modalias", cxlport_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) == 0)
|
||||
+ port->module = util_modalias_to_module(ctx, buf);
|
||||
+
|
||||
return 0;
|
||||
err:
|
||||
free(port->dev_path);
|
||||
@@ -507,6 +529,135 @@ err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+static void *add_cxl_port(void *parent, int id, const char *cxlport_base)
|
||||
+{
|
||||
+ const char *devname = devpath_to_devname(cxlport_base);
|
||||
+ struct cxl_port *port, *port_dup;
|
||||
+ struct cxl_port *parent_port = parent;
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(parent_port);
|
||||
+ int rc;
|
||||
+
|
||||
+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlport_base);
|
||||
+
|
||||
+ port = calloc(1, sizeof(*port));
|
||||
+ if (!port)
|
||||
+ return NULL;
|
||||
+
|
||||
+ rc = cxl_port_init(port, parent_port, CXL_PORT_SWITCH, ctx, id,
|
||||
+ cxlport_base);
|
||||
+ if (rc)
|
||||
+ goto err;
|
||||
+
|
||||
+ cxl_port_foreach(parent_port, port_dup)
|
||||
+ if (port_dup->id == port->id) {
|
||||
+ free_port(port, NULL);
|
||||
+ return port_dup;
|
||||
+ }
|
||||
+
|
||||
+ list_add(&parent_port->child_ports, &port->list);
|
||||
+ return port;
|
||||
+
|
||||
+err:
|
||||
+ free(port);
|
||||
+ return NULL;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void cxl_ports_init(struct cxl_port *port)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
+
|
||||
+ if (port->ports_init)
|
||||
+ return;
|
||||
+
|
||||
+ port->ports_init = 1;
|
||||
+
|
||||
+ sysfs_device_parse(ctx, port->dev_path, "port", port, add_cxl_port);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port)
|
||||
+{
|
||||
+ return port->ctx;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_port *cxl_port_get_first(struct cxl_port *port)
|
||||
+{
|
||||
+ cxl_ports_init(port);
|
||||
+
|
||||
+ return list_top(&port->child_ports, struct cxl_port, list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_port *cxl_port_get_next(struct cxl_port *port)
|
||||
+{
|
||||
+ struct cxl_port *parent_port = port->parent;
|
||||
+
|
||||
+ return list_next(&parent_port->child_ports, port, list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT const char *cxl_port_get_devname(struct cxl_port *port)
|
||||
+{
|
||||
+ return devpath_to_devname(port->dev_path);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_port_get_id(struct cxl_port *port)
|
||||
+{
|
||||
+ return port->id;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_port *cxl_port_get_parent(struct cxl_port *port)
|
||||
+{
|
||||
+ return port->parent;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT bool cxl_port_is_root(struct cxl_port *port)
|
||||
+{
|
||||
+ return port->type == CXL_PORT_ROOT;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT bool cxl_port_is_switch(struct cxl_port *port)
|
||||
+{
|
||||
+ return port->type == CXL_PORT_SWITCH;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port)
|
||||
+{
|
||||
+ struct cxl_bus *bus;
|
||||
+
|
||||
+ if (!cxl_port_is_enabled(port))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (port->bus)
|
||||
+ return port->bus;
|
||||
+
|
||||
+ while (port->parent)
|
||||
+ port = port->parent;
|
||||
+
|
||||
+ bus = container_of(port, typeof(*bus), port);
|
||||
+ port->bus = bus;
|
||||
+ return bus;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
+ char *path = port->dev_buf;
|
||||
+ int len = port->buf_len;
|
||||
+
|
||||
+ if (snprintf(path, len, "%s/driver", port->dev_path) >= len) {
|
||||
+ err(ctx, "%s: buffer too small!\n", cxl_port_get_devname(port));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return is_enabled(path);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_bus *cxl_port_to_bus(struct cxl_port *port)
|
||||
+{
|
||||
+ if (!cxl_port_is_root(port))
|
||||
+ return NULL;
|
||||
+ return container_of(port, struct cxl_bus, port);
|
||||
+}
|
||||
+
|
||||
static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base)
|
||||
{
|
||||
const char *devname = devpath_to_devname(cxlbus_base);
|
||||
@@ -522,7 +673,7 @@ static void *add_cxl_bus(void *parent, int id, const char *cxlbus_base)
|
||||
return NULL;
|
||||
|
||||
port = &bus->port;
|
||||
- rc = cxl_port_init(port, ctx, id, cxlbus_base);
|
||||
+ rc = cxl_port_init(port, NULL, CXL_PORT_ROOT, ctx, id, cxlbus_base);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
@@ -579,6 +730,11 @@ CXL_EXPORT int cxl_bus_get_id(struct cxl_bus *bus)
|
||||
return port->id;
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus)
|
||||
+{
|
||||
+ return &bus->port;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus)
|
||||
{
|
||||
struct cxl_port *port = &bus->port;
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 781ff99..a7e923f 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -82,4 +82,16 @@ global:
|
||||
cxl_bus_get_provider;
|
||||
cxl_bus_get_devname;
|
||||
cxl_bus_get_id;
|
||||
+ cxl_bus_get_port;
|
||||
+ cxl_port_get_first;
|
||||
+ cxl_port_get_next;
|
||||
+ cxl_port_get_devname;
|
||||
+ cxl_port_get_id;
|
||||
+ cxl_port_get_ctx;
|
||||
+ cxl_port_is_enabled;
|
||||
+ cxl_port_get_parent;
|
||||
+ cxl_port_is_root;
|
||||
+ cxl_port_is_switch;
|
||||
+ cxl_port_to_bus;
|
||||
+ cxl_port_get_bus;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 0758d05..637f90d 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -34,14 +34,25 @@ struct cxl_memdev {
|
||||
unsigned long long serial;
|
||||
};
|
||||
|
||||
+enum cxl_port_type {
|
||||
+ CXL_PORT_ROOT,
|
||||
+ CXL_PORT_SWITCH,
|
||||
+};
|
||||
+
|
||||
struct cxl_port {
|
||||
int id;
|
||||
void *dev_buf;
|
||||
size_t buf_len;
|
||||
char *dev_path;
|
||||
char *uport;
|
||||
+ int ports_init;
|
||||
struct cxl_ctx *ctx;
|
||||
+ struct cxl_bus *bus;
|
||||
+ enum cxl_port_type type;
|
||||
+ struct cxl_port *parent;
|
||||
+ struct kmod_module *module;
|
||||
struct list_node list;
|
||||
+ struct list_head child_ports;
|
||||
};
|
||||
|
||||
struct cxl_bus {
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index da66eb2..efbb397 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
+#include <stdbool.h>
|
||||
|
||||
#ifdef HAVE_UUID
|
||||
#include <uuid/uuid.h>
|
||||
@@ -63,11 +64,29 @@ struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus);
|
||||
const char *cxl_bus_get_provider(struct cxl_bus *bus);
|
||||
const char *cxl_bus_get_devname(struct cxl_bus *bus);
|
||||
int cxl_bus_get_id(struct cxl_bus *bus);
|
||||
+struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus);
|
||||
|
||||
#define cxl_bus_foreach(ctx, bus) \
|
||||
for (bus = cxl_bus_get_first(ctx); bus != NULL; \
|
||||
bus = cxl_bus_get_next(bus))
|
||||
|
||||
+struct cxl_port;
|
||||
+struct cxl_port *cxl_port_get_first(struct cxl_port *parent);
|
||||
+struct cxl_port *cxl_port_get_next(struct cxl_port *port);
|
||||
+const char *cxl_port_get_devname(struct cxl_port *port);
|
||||
+int cxl_port_get_id(struct cxl_port *port);
|
||||
+struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port);
|
||||
+int cxl_port_is_enabled(struct cxl_port *port);
|
||||
+struct cxl_port *cxl_port_get_parent(struct cxl_port *port);
|
||||
+bool cxl_port_is_root(struct cxl_port *port);
|
||||
+bool cxl_port_is_switch(struct cxl_port *port);
|
||||
+struct cxl_bus *cxl_port_to_bus(struct cxl_port *port);
|
||||
+struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
|
||||
+
|
||||
+#define cxl_port_foreach(parent, port) \
|
||||
+ for (port = cxl_port_get_first(parent); port != NULL; \
|
||||
+ port = cxl_port_get_next(port))
|
||||
+
|
||||
struct cxl_cmd;
|
||||
const char *cxl_cmd_get_devname(struct cxl_cmd *cmd);
|
||||
struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 9500e61..1ef91b4 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -25,6 +25,11 @@ static const struct option options[] = {
|
||||
OPT_STRING('b', "bus", ¶m.bus_filter, "bus device name",
|
||||
"filter by CXL bus device name(s)"),
|
||||
OPT_BOOLEAN('B', "buses", ¶m.buses, "include CXL bus info"),
|
||||
+ OPT_STRING('p', "port", ¶m.port_filter, "port device name",
|
||||
+ "filter by CXL port device name(s)"),
|
||||
+ OPT_BOOLEAN('P', "ports", ¶m.ports, "include CXL port info"),
|
||||
+ OPT_BOOLEAN('S', "single", ¶m.single,
|
||||
+ "skip listing descendant objects"),
|
||||
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
"use human friendly number formats "),
|
||||
@@ -35,7 +40,7 @@ static const struct option options[] = {
|
||||
|
||||
static int num_list_flags(void)
|
||||
{
|
||||
- return !!param.memdevs + !!param.buses;
|
||||
+ return !!param.memdevs + !!param.buses + !!param.ports;
|
||||
}
|
||||
|
||||
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
@@ -53,11 +58,18 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
if (argc)
|
||||
usage_with_options(u, options);
|
||||
|
||||
+ if (param.single && !param.port_filter) {
|
||||
+ error("-S/--single expects a port filter: -p/--port=\n");
|
||||
+ usage_with_options(u, options);
|
||||
+ }
|
||||
+
|
||||
if (num_list_flags() == 0) {
|
||||
if (param.memdev_filter || param.serial_filter)
|
||||
param.memdevs = true;
|
||||
if (param.bus_filter)
|
||||
param.buses = true;
|
||||
+ if (param.port_filter)
|
||||
+ param.ports = true;
|
||||
if (num_list_flags() == 0) {
|
||||
/*
|
||||
* TODO: We likely want to list regions by default if
|
||||
@@ -73,5 +85,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
|
||||
log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG");
|
||||
|
||||
+ if (cxl_filter_has(param.port_filter, "root") && param.ports)
|
||||
+ param.buses = true;
|
||||
+
|
||||
return cxl_filter_walk(ctx, ¶m);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
103
SOURCES/0104-cxl-list-Add-debug-option.patch
Normal file
103
SOURCES/0104-cxl-list-Add-debug-option.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From 2a43dce3913b392a13a5ee918c8ee831a25d720e Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:24 -0800
|
||||
Subject: [PATCH 104/217] cxl/list: Add --debug option
|
||||
|
||||
Add an option to turn on libray and cxl_filter_walk() messages. Gate it
|
||||
based on the global ENABLE_DEBUG configuration setting.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298560409.3021641.11040422738199381922.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 6 ++++--
|
||||
cxl/filter.c | 3 +++
|
||||
cxl/list.c | 9 +++++++++
|
||||
3 files changed, 16 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 3076deb..42b6de6 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -200,9 +200,11 @@ OPTIONS
|
||||
descendants of the individual ports that match the filter. By default
|
||||
all descendant objects are listed.
|
||||
|
||||
-include::human-option.txt[]
|
||||
+--debug::
|
||||
+ If the cxl tool was built with debug enabled, turn on debug
|
||||
+ messages.
|
||||
|
||||
-include::verbose-option.txt[]
|
||||
+include::human-option.txt[]
|
||||
|
||||
include::../copyright.txt[]
|
||||
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 8b79db3..32171a4 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -387,6 +387,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
if (!jports)
|
||||
goto err;
|
||||
|
||||
+ dbg(p, "walk memdevs\n");
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
struct json_object *jdev;
|
||||
|
||||
@@ -403,6 +404,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
}
|
||||
}
|
||||
|
||||
+ dbg(p, "walk buses\n");
|
||||
cxl_bus_foreach(ctx, bus) {
|
||||
struct json_object *jbus = NULL;
|
||||
struct json_object *jchildports = NULL;
|
||||
@@ -431,6 +433,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
}
|
||||
}
|
||||
walk_children:
|
||||
+ dbg(p, "walk ports\n");
|
||||
walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
flags);
|
||||
cond_add_put_array_suffix(jbus, "ports", devname, jchildports);
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 1ef91b4..01ab19b 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "filter.h"
|
||||
|
||||
static struct cxl_filter_params param;
|
||||
+static bool debug;
|
||||
|
||||
static const struct option options[] = {
|
||||
OPT_STRING('m', "memdev", ¶m.memdev_filter, "memory device name(s)",
|
||||
@@ -35,6 +36,9 @@ static const struct option options[] = {
|
||||
"use human friendly number formats "),
|
||||
OPT_BOOLEAN('H', "health", ¶m.health,
|
||||
"include memory device health information "),
|
||||
+#ifdef ENABLE_DEBUG
|
||||
+ OPT_BOOLEAN(0, "debug", &debug, "debug list walk"),
|
||||
+#endif
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
@@ -84,9 +88,14 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
}
|
||||
|
||||
log_init(¶m.ctx, "cxl list", "CXL_LIST_LOG");
|
||||
+ if (debug) {
|
||||
+ cxl_set_log_priority(ctx, LOG_DEBUG);
|
||||
+ param.ctx.log_priority = LOG_DEBUG;
|
||||
+ }
|
||||
|
||||
if (cxl_filter_has(param.port_filter, "root") && param.ports)
|
||||
param.buses = true;
|
||||
|
||||
+ dbg(¶m, "walk topology\n");
|
||||
return cxl_filter_walk(ctx, ¶m);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
746
SOURCES/0105-cxl-list-Add-endpoints.patch
Normal file
746
SOURCES/0105-cxl-list-Add-endpoints.patch
Normal file
@ -0,0 +1,746 @@
|
||||
From 7eb06a5293531854e7a28666e955106094d3552b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:29 -0800
|
||||
Subject: [PATCH 105/217] cxl/list: Add endpoints
|
||||
|
||||
Endpoints are port-like objects that represent the HDM decoders at terminal
|
||||
end of a decode chain. Unlike port decoders that route to downstream ports,
|
||||
endpoint decoders route to endpoint DPA (Device Physical Address) ranges.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298560917.3021641.13753578554905796298.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
.clang-format | 1 +
|
||||
Documentation/cxl/cxl-list.txt | 16 ++++
|
||||
Documentation/cxl/lib/libcxl.txt | 31 ++++++-
|
||||
cxl/filter.c | 147 ++++++++++++++++++++++++++++---
|
||||
cxl/filter.h | 2 +
|
||||
cxl/json.c | 20 ++++-
|
||||
cxl/json.h | 2 +
|
||||
cxl/lib/libcxl.c | 107 ++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 9 ++
|
||||
cxl/lib/private.h | 10 +++
|
||||
cxl/libcxl.h | 15 ++++
|
||||
cxl/list.c | 13 ++-
|
||||
12 files changed, 355 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/.clang-format b/.clang-format
|
||||
index 391cd34..106bc5e 100644
|
||||
--- a/.clang-format
|
||||
+++ b/.clang-format
|
||||
@@ -80,6 +80,7 @@ ForEachMacros:
|
||||
- 'cxl_memdev_foreach'
|
||||
- 'cxl_bus_foreach'
|
||||
- 'cxl_port_foreach'
|
||||
+ - 'cxl_endpoint_foreach'
|
||||
- 'daxctl_dev_foreach'
|
||||
- 'daxctl_mapping_foreach'
|
||||
- 'daxctl_region_foreach'
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 42b6de6..d342da2 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -190,6 +190,12 @@ OPTIONS
|
||||
----
|
||||
# cxl list -B
|
||||
# cxl list -P -p root
|
||||
+----
|
||||
+ Additionally, endpoint objects are also ports so the following commands
|
||||
+ are also equivalent.
|
||||
+----
|
||||
+# cxl list -E
|
||||
+# cxl list -P -p endpoint
|
||||
----
|
||||
By default, only 'switch' ports are listed.
|
||||
|
||||
@@ -200,6 +206,16 @@ OPTIONS
|
||||
descendants of the individual ports that match the filter. By default
|
||||
all descendant objects are listed.
|
||||
|
||||
+-E::
|
||||
+--endpoints::
|
||||
+ Include endpoint objects (CXL Memory Device decoders) in the
|
||||
+ listing.
|
||||
+
|
||||
+-e::
|
||||
+--endpoint::
|
||||
+ Specify CXL endpoint device name(s), or device id(s) to filter
|
||||
+ the emitted endpoint(s).
|
||||
+
|
||||
--debug::
|
||||
If the cxl tool was built with debug enabled, turn on debug
|
||||
messages.
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index 804e9ca..eebab37 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -199,12 +199,41 @@ int cxl_port_get_id(struct cxl_port *port);
|
||||
int cxl_port_is_enabled(struct cxl_port *port);
|
||||
bool cxl_port_is_root(struct cxl_port *port);
|
||||
bool cxl_port_is_switch(struct cxl_port *port);
|
||||
+bool cxl_port_is_endpoint(struct cxl_port *port);
|
||||
----
|
||||
The port type is communicated via cxl_port_is_<type>(). An 'enabled' port
|
||||
is one that has succeeded in discovering the CXL component registers in
|
||||
the host device and has enumerated its downstream ports. In order for a
|
||||
memdev to be enabled for CXL memory operation all CXL ports in its
|
||||
-ancestry must also be enabled.
|
||||
+ancestry must also be enabled including a root port, an arbitrary number
|
||||
+of intervening switch ports, and a terminal endpoint port.
|
||||
+
|
||||
+ENDPOINTS
|
||||
+---------
|
||||
+CXL endpoint objects encapsulate the set of host-managed device-memory
|
||||
+(HDM) decoders in a physical memory device. The endpoint is the last hop
|
||||
+in a decoder chain that translate SPA to DPA (system-physical-address to
|
||||
+device-local-physical-address).
|
||||
+
|
||||
+=== ENDPOINT: Enumeration
|
||||
+----
|
||||
+struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *parent);
|
||||
+struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
+
|
||||
+#define cxl_endpoint_foreach(port, endpoint) \
|
||||
+ for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \
|
||||
+ endpoint = cxl_endpoint_get_next(endpoint))
|
||||
+----
|
||||
+
|
||||
+=== ENDPOINT: Attributes
|
||||
+----
|
||||
+const char *cxl_endpoint_get_devname(struct cxl_endpoint *endpoint);
|
||||
+int cxl_endpoint_get_id(struct cxl_endpoint *endpoint);
|
||||
+int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint);
|
||||
+----
|
||||
|
||||
include::../../copyright.txt[]
|
||||
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 32171a4..5d80d1b 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -47,8 +47,42 @@ bool cxl_filter_has(const char *__filter, const char *needle)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static struct cxl_endpoint *
|
||||
+util_cxl_endpoint_filter(struct cxl_endpoint *endpoint, const char *__ident)
|
||||
+{
|
||||
+ char *ident, *save;
|
||||
+ const char *arg;
|
||||
+ int endpoint_id;
|
||||
+
|
||||
+ if (!__ident)
|
||||
+ return endpoint;
|
||||
+
|
||||
+ ident = strdup(__ident);
|
||||
+ if (!ident)
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (arg = strtok_r(ident, which_sep(__ident), &save); arg;
|
||||
+ arg = strtok_r(NULL, which_sep(__ident), &save)) {
|
||||
+ if (strcmp(arg, "all") == 0)
|
||||
+ break;
|
||||
+
|
||||
+ if ((sscanf(arg, "%d", &endpoint_id) == 1 ||
|
||||
+ sscanf(arg, "endpoint%d", &endpoint_id) == 1) &&
|
||||
+ cxl_endpoint_get_id(endpoint) == endpoint_id)
|
||||
+ break;
|
||||
+
|
||||
+ if (strcmp(arg, cxl_endpoint_get_devname(endpoint)) == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ free(ident);
|
||||
+ if (arg)
|
||||
+ return endpoint;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port,
|
||||
- const char *__ident)
|
||||
+ const char *__ident)
|
||||
{
|
||||
char *ident, *save;
|
||||
const char *arg;
|
||||
@@ -72,6 +106,9 @@ static struct cxl_port *__util_cxl_port_filter(struct cxl_port *port,
|
||||
if (strcmp(arg, "switch") == 0 && cxl_port_is_switch(port))
|
||||
break;
|
||||
|
||||
+ if (strcmp(arg, "endpoint") == 0 && cxl_port_is_endpoint(port))
|
||||
+ break;
|
||||
+
|
||||
if ((sscanf(arg, "%d", &port_id) == 1 ||
|
||||
sscanf(arg, "port%d", &port_id) == 1) &&
|
||||
cxl_port_get_id(port) == port_id)
|
||||
@@ -116,6 +153,24 @@ static struct cxl_port *util_cxl_port_filter(struct cxl_port *port,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct cxl_endpoint *
|
||||
+util_cxl_endpoint_filter_by_port(struct cxl_endpoint *endpoint,
|
||||
+ const char *ident,
|
||||
+ enum cxl_port_filter_mode mode)
|
||||
+{
|
||||
+ struct cxl_port *iter = cxl_endpoint_get_port(endpoint);
|
||||
+
|
||||
+ if (util_cxl_port_filter(iter, ident, CXL_PF_SINGLE))
|
||||
+ return endpoint;
|
||||
+ iter = cxl_port_get_parent(iter);
|
||||
+ if (!iter)
|
||||
+ return NULL;
|
||||
+ if (util_cxl_port_filter(iter, ident, mode))
|
||||
+ return endpoint;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static struct cxl_bus *util_cxl_bus_filter(struct cxl_bus *bus,
|
||||
const char *__ident)
|
||||
{
|
||||
@@ -325,10 +380,34 @@ static struct json_object *pick_array(struct json_object *child,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
|
||||
+ struct json_object *jeps, unsigned long flags)
|
||||
+{
|
||||
+ struct cxl_endpoint *endpoint;
|
||||
+
|
||||
+ cxl_endpoint_foreach(port, endpoint) {
|
||||
+ struct cxl_port *ep_port = cxl_endpoint_get_port(endpoint);
|
||||
+ struct json_object *jendpoint;
|
||||
+
|
||||
+ if (!util_cxl_endpoint_filter(endpoint, p->endpoint_filter))
|
||||
+ continue;
|
||||
+ if (!util_cxl_port_filter_by_bus(ep_port, p->bus_filter))
|
||||
+ continue;
|
||||
+ if (!util_cxl_endpoint_filter_by_port(endpoint, p->port_filter,
|
||||
+ pf_mode(p)))
|
||||
+ continue;
|
||||
+ if (!p->idle && !cxl_endpoint_is_enabled(endpoint))
|
||||
+ continue;
|
||||
+ jendpoint = util_cxl_endpoint_to_json(endpoint, flags);
|
||||
+ if (jendpoint)
|
||||
+ json_object_array_add(jeps, jendpoint);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void walk_child_ports(struct cxl_port *parent_port,
|
||||
struct cxl_filter_params *p,
|
||||
struct json_object *jports,
|
||||
- unsigned long flags)
|
||||
+ struct json_object *jeps, unsigned long flags)
|
||||
{
|
||||
struct cxl_port *port;
|
||||
|
||||
@@ -336,6 +415,7 @@ static void walk_child_ports(struct cxl_port *parent_port,
|
||||
const char *devname = cxl_port_get_devname(port);
|
||||
struct json_object *jport = NULL;
|
||||
struct json_object *jchildports = NULL;
|
||||
+ struct json_object *jchildendpoints = NULL;
|
||||
|
||||
if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
|
||||
goto walk_children;
|
||||
@@ -343,21 +423,41 @@ static void walk_child_ports(struct cxl_port *parent_port,
|
||||
goto walk_children;
|
||||
if (!p->idle && !cxl_port_is_enabled(port))
|
||||
continue;
|
||||
- if (p->ports)
|
||||
+ if (p->ports) {
|
||||
jport = util_cxl_port_to_json(port, flags);
|
||||
- if (!jport)
|
||||
- continue;
|
||||
- json_object_array_add(jports, jport);
|
||||
- jchildports = json_object_new_array();
|
||||
- if (!jchildports) {
|
||||
- err(p, "%s: failed to enumerate child ports\n",
|
||||
- devname);
|
||||
- continue;
|
||||
+ if (!jport) {
|
||||
+ err(p, "%s: failed to list\n", devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+ json_object_array_add(jports, jport);
|
||||
+ jchildports = json_object_new_array();
|
||||
+ if (!jchildports) {
|
||||
+ err(p, "%s: failed to enumerate child ports\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (p->ports && p->endpoints) {
|
||||
+ jchildendpoints = json_object_new_array();
|
||||
+ if (!jchildendpoints) {
|
||||
+ err(p,
|
||||
+ "%s: failed to enumerate child endpoints\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
+
|
||||
walk_children:
|
||||
+ if (p->endpoints)
|
||||
+ walk_endpoints(port, p, pick_array(jchildendpoints, jeps),
|
||||
+ flags);
|
||||
+
|
||||
walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
- flags);
|
||||
+ pick_array(jchildendpoints, jeps), flags);
|
||||
cond_add_put_array_suffix(jport, "ports", devname, jchildports);
|
||||
+ cond_add_put_array_suffix(jport, "endpoints", devname,
|
||||
+ jchildendpoints);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +466,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL;
|
||||
struct json_object *jplatform = json_object_new_array();
|
||||
unsigned long flags = params_to_flags(p);
|
||||
+ struct json_object *jeps = NULL;
|
||||
struct cxl_memdev *memdev;
|
||||
int top_level_objs = 0;
|
||||
struct cxl_bus *bus;
|
||||
@@ -387,6 +488,10 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
if (!jports)
|
||||
goto err;
|
||||
|
||||
+ jeps = json_object_new_array();
|
||||
+ if (!jeps)
|
||||
+ goto err;
|
||||
+
|
||||
dbg(p, "walk memdevs\n");
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
struct json_object *jdev;
|
||||
@@ -408,6 +513,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
cxl_bus_foreach(ctx, bus) {
|
||||
struct json_object *jbus = NULL;
|
||||
struct json_object *jchildports = NULL;
|
||||
+ struct json_object *jchildeps = NULL;
|
||||
struct cxl_port *port = cxl_bus_get_port(bus);
|
||||
const char *devname = cxl_bus_get_devname(bus);
|
||||
|
||||
@@ -431,12 +537,23 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
+ if (p->endpoints) {
|
||||
+ jchildeps = json_object_new_array();
|
||||
+ if (!jchildeps) {
|
||||
+ err(p,
|
||||
+ "%s: failed to enumerate child endpoints\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
walk_children:
|
||||
dbg(p, "walk ports\n");
|
||||
walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
- flags);
|
||||
+ pick_array(jchildeps, jeps), flags);
|
||||
cond_add_put_array_suffix(jbus, "ports", devname, jchildports);
|
||||
+ cond_add_put_array_suffix(jbus, "endpoints", devname,
|
||||
+ jchildeps);
|
||||
}
|
||||
|
||||
if (json_object_array_length(jdevs))
|
||||
@@ -445,10 +562,13 @@ walk_children:
|
||||
top_level_objs++;
|
||||
if (json_object_array_length(jports))
|
||||
top_level_objs++;
|
||||
+ if (json_object_array_length(jeps))
|
||||
+ top_level_objs++;
|
||||
|
||||
splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1);
|
||||
splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1);
|
||||
splice_array(p, jports, jplatform, "ports", top_level_objs > 1);
|
||||
+ splice_array(p, jeps, jplatform, "endpoints", top_level_objs > 1);
|
||||
|
||||
util_display_json_array(stdout, jplatform, flags);
|
||||
|
||||
@@ -457,6 +577,7 @@ err:
|
||||
json_object_put(jdevs);
|
||||
json_object_put(jbuses);
|
||||
json_object_put(jports);
|
||||
+ json_object_put(jeps);
|
||||
json_object_put(jplatform);
|
||||
return -ENOMEM;
|
||||
}
|
||||
diff --git a/cxl/filter.h b/cxl/filter.h
|
||||
index 0d83304..bbd341c 100644
|
||||
--- a/cxl/filter.h
|
||||
+++ b/cxl/filter.h
|
||||
@@ -11,7 +11,9 @@ struct cxl_filter_params {
|
||||
const char *serial_filter;
|
||||
const char *bus_filter;
|
||||
const char *port_filter;
|
||||
+ const char *endpoint_filter;
|
||||
bool single;
|
||||
+ bool endpoints;
|
||||
bool memdevs;
|
||||
bool ports;
|
||||
bool buses;
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index d9f864e..08f6192 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -243,8 +243,9 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
|
||||
return jbus;
|
||||
}
|
||||
|
||||
-struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
- unsigned long flags)
|
||||
+static struct json_object *__util_cxl_port_to_json(struct cxl_port *port,
|
||||
+ const char *name_key,
|
||||
+ unsigned long flags)
|
||||
{
|
||||
const char *devname = cxl_port_get_devname(port);
|
||||
struct json_object *jport, *jobj;
|
||||
@@ -255,7 +256,7 @@ struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
|
||||
jobj = json_object_new_string(devname);
|
||||
if (jobj)
|
||||
- json_object_object_add(jport, "port", jobj);
|
||||
+ json_object_object_add(jport, name_key, jobj);
|
||||
|
||||
if (!cxl_port_is_enabled(port)) {
|
||||
jobj = json_object_new_string("disabled");
|
||||
@@ -265,3 +266,16 @@ struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
|
||||
return jport;
|
||||
}
|
||||
+
|
||||
+struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ return __util_cxl_port_to_json(port, "port", flags);
|
||||
+}
|
||||
+
|
||||
+struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint,
|
||||
+ unsigned long flags)
|
||||
+{
|
||||
+ return __util_cxl_port_to_json(cxl_endpoint_get_port(endpoint),
|
||||
+ "endpoint", flags);
|
||||
+}
|
||||
diff --git a/cxl/json.h b/cxl/json.h
|
||||
index 36653db..8f45190 100644
|
||||
--- a/cxl/json.h
|
||||
+++ b/cxl/json.h
|
||||
@@ -11,4 +11,6 @@ struct json_object *util_cxl_bus_to_json(struct cxl_bus *bus,
|
||||
struct cxl_port;
|
||||
struct json_object *util_cxl_port_to_json(struct cxl_port *port,
|
||||
unsigned long flags);
|
||||
+struct json_object *util_cxl_endpoint_to_json(struct cxl_endpoint *endpoint,
|
||||
+ unsigned long flags);
|
||||
#endif /* __CXL_UTIL_JSON_H__ */
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 03eff3c..a25e715 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -67,14 +67,18 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
}
|
||||
|
||||
static void free_port(struct cxl_port *port, struct list_head *head);
|
||||
+static void free_endpoint(struct cxl_endpoint *endpoint, struct list_head *head);
|
||||
static void __free_port(struct cxl_port *port, struct list_head *head)
|
||||
{
|
||||
struct cxl_port *child, *_c;
|
||||
+ struct cxl_endpoint *endpoint, *_e;
|
||||
|
||||
if (head)
|
||||
list_del_from(head, &port->list);
|
||||
list_for_each_safe(&port->child_ports, child, _c, list)
|
||||
free_port(child, &port->child_ports);
|
||||
+ list_for_each_safe(&port->endpoints, endpoint, _e, port.list)
|
||||
+ free_endpoint(endpoint, &port->endpoints);
|
||||
kmod_module_unref(port->module);
|
||||
free(port->dev_buf);
|
||||
free(port->dev_path);
|
||||
@@ -87,6 +91,12 @@ static void free_port(struct cxl_port *port, struct list_head *head)
|
||||
free(port);
|
||||
}
|
||||
|
||||
+static void free_endpoint(struct cxl_endpoint *endpoint, struct list_head *head)
|
||||
+{
|
||||
+ __free_port(&endpoint->port, head);
|
||||
+ free(endpoint);
|
||||
+}
|
||||
+
|
||||
static void free_bus(struct cxl_bus *bus, struct list_head *head)
|
||||
{
|
||||
__free_port(&bus->port, head);
|
||||
@@ -500,6 +510,7 @@ static int cxl_port_init(struct cxl_port *port, struct cxl_port *parent_port,
|
||||
port->parent = parent_port;
|
||||
|
||||
list_head_init(&port->child_ports);
|
||||
+ list_head_init(&port->endpoints);
|
||||
|
||||
port->dev_path = strdup(cxlport_base);
|
||||
if (!port->dev_path)
|
||||
@@ -529,6 +540,97 @@ err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+static void *add_cxl_endpoint(void *parent, int id, const char *cxlep_base)
|
||||
+{
|
||||
+ const char *devname = devpath_to_devname(cxlep_base);
|
||||
+ struct cxl_endpoint *endpoint, *endpoint_dup;
|
||||
+ struct cxl_port *port = parent;
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
+ int rc;
|
||||
+
|
||||
+ dbg(ctx, "%s: base: \'%s\'\n", devname, cxlep_base);
|
||||
+
|
||||
+ endpoint = calloc(1, sizeof(*endpoint));
|
||||
+ if (!endpoint)
|
||||
+ return NULL;
|
||||
+
|
||||
+ rc = cxl_port_init(&endpoint->port, port, CXL_PORT_ENDPOINT, ctx, id,
|
||||
+ cxlep_base);
|
||||
+ if (rc)
|
||||
+ goto err;
|
||||
+
|
||||
+ cxl_endpoint_foreach(port, endpoint_dup)
|
||||
+ if (endpoint_dup->port.id == endpoint->port.id) {
|
||||
+ free_endpoint(endpoint, NULL);
|
||||
+ return endpoint_dup;
|
||||
+ }
|
||||
+
|
||||
+ list_add(&port->endpoints, &endpoint->port.list);
|
||||
+ return endpoint;
|
||||
+
|
||||
+err:
|
||||
+ free(endpoint);
|
||||
+ return NULL;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static void cxl_endpoints_init(struct cxl_port *port)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
+
|
||||
+ if (port->endpoints_init)
|
||||
+ return;
|
||||
+
|
||||
+ port->endpoints_init = 1;
|
||||
+
|
||||
+ sysfs_device_parse(ctx, port->dev_path, "endpoint", port,
|
||||
+ add_cxl_endpoint);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return endpoint->port.ctx;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *port)
|
||||
+{
|
||||
+ cxl_endpoints_init(port);
|
||||
+
|
||||
+ return list_top(&port->endpoints, struct cxl_endpoint, port.list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ struct cxl_port *port = endpoint->port.parent;
|
||||
+
|
||||
+ return list_next(&port->endpoints, endpoint, port.list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT const char *cxl_endpoint_get_devname(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return devpath_to_devname(endpoint->port.dev_path);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_endpoint_get_id(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return endpoint->port.id;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return endpoint->port.parent;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return &endpoint->port;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return cxl_port_is_enabled(&endpoint->port);
|
||||
+}
|
||||
+
|
||||
static void *add_cxl_port(void *parent, int id, const char *cxlport_base)
|
||||
{
|
||||
const char *devname = devpath_to_devname(cxlport_base);
|
||||
@@ -619,6 +721,11 @@ CXL_EXPORT bool cxl_port_is_switch(struct cxl_port *port)
|
||||
return port->type == CXL_PORT_SWITCH;
|
||||
}
|
||||
|
||||
+CXL_EXPORT bool cxl_port_is_endpoint(struct cxl_port *port)
|
||||
+{
|
||||
+ return port->type == CXL_PORT_ENDPOINT;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_bus *bus;
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index a7e923f..7a51a0c 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -93,5 +93,14 @@ global:
|
||||
cxl_port_is_root;
|
||||
cxl_port_is_switch;
|
||||
cxl_port_to_bus;
|
||||
+ cxl_port_is_endpoint;
|
||||
cxl_port_get_bus;
|
||||
+ cxl_endpoint_get_first;
|
||||
+ cxl_endpoint_get_next;
|
||||
+ cxl_endpoint_get_devname;
|
||||
+ cxl_endpoint_get_id;
|
||||
+ cxl_endpoint_get_ctx;
|
||||
+ cxl_endpoint_is_enabled;
|
||||
+ cxl_endpoint_get_parent;
|
||||
+ cxl_endpoint_get_port;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index 637f90d..cedd2f2 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -17,6 +17,7 @@ struct cxl_pmem {
|
||||
char *dev_path;
|
||||
};
|
||||
|
||||
+struct cxl_endpoint;
|
||||
struct cxl_memdev {
|
||||
int id, major, minor;
|
||||
void *dev_buf;
|
||||
@@ -32,11 +33,13 @@ struct cxl_memdev {
|
||||
struct kmod_module *module;
|
||||
struct cxl_pmem *pmem;
|
||||
unsigned long long serial;
|
||||
+ struct cxl_endpoint *endpoint;
|
||||
};
|
||||
|
||||
enum cxl_port_type {
|
||||
CXL_PORT_ROOT,
|
||||
CXL_PORT_SWITCH,
|
||||
+ CXL_PORT_ENDPOINT,
|
||||
};
|
||||
|
||||
struct cxl_port {
|
||||
@@ -46,6 +49,7 @@ struct cxl_port {
|
||||
char *dev_path;
|
||||
char *uport;
|
||||
int ports_init;
|
||||
+ int endpoints_init;
|
||||
struct cxl_ctx *ctx;
|
||||
struct cxl_bus *bus;
|
||||
enum cxl_port_type type;
|
||||
@@ -53,12 +57,18 @@ struct cxl_port {
|
||||
struct kmod_module *module;
|
||||
struct list_node list;
|
||||
struct list_head child_ports;
|
||||
+ struct list_head endpoints;
|
||||
};
|
||||
|
||||
struct cxl_bus {
|
||||
struct cxl_port port;
|
||||
};
|
||||
|
||||
+struct cxl_endpoint {
|
||||
+ struct cxl_port port;
|
||||
+ struct cxl_memdev *memdev;
|
||||
+};
|
||||
+
|
||||
enum cxl_cmd_query_status {
|
||||
CXL_CMD_QUERY_NOT_RUN = 0,
|
||||
CXL_CMD_QUERY_OK,
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index efbb397..f6ba9a1 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -81,12 +81,27 @@ struct cxl_port *cxl_port_get_parent(struct cxl_port *port);
|
||||
bool cxl_port_is_root(struct cxl_port *port);
|
||||
bool cxl_port_is_switch(struct cxl_port *port);
|
||||
struct cxl_bus *cxl_port_to_bus(struct cxl_port *port);
|
||||
+bool cxl_port_is_endpoint(struct cxl_port *port);
|
||||
struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
|
||||
|
||||
#define cxl_port_foreach(parent, port) \
|
||||
for (port = cxl_port_get_first(parent); port != NULL; \
|
||||
port = cxl_port_get_next(port))
|
||||
|
||||
+struct cxl_endpoint;
|
||||
+struct cxl_endpoint *cxl_endpoint_get_first(struct cxl_port *parent);
|
||||
+struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint);
|
||||
+const char *cxl_endpoint_get_devname(struct cxl_endpoint *endpoint);
|
||||
+int cxl_endpoint_get_id(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint);
|
||||
+int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
+
|
||||
+#define cxl_endpoint_foreach(port, endpoint) \
|
||||
+ for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \
|
||||
+ endpoint = cxl_endpoint_get_next(endpoint))
|
||||
+
|
||||
struct cxl_cmd;
|
||||
const char *cxl_cmd_get_devname(struct cxl_cmd *cmd);
|
||||
struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index 01ab19b..b15e01c 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -31,6 +31,11 @@ static const struct option options[] = {
|
||||
OPT_BOOLEAN('P', "ports", ¶m.ports, "include CXL port info"),
|
||||
OPT_BOOLEAN('S', "single", ¶m.single,
|
||||
"skip listing descendant objects"),
|
||||
+ OPT_STRING('e', "endpoint", ¶m.endpoint_filter,
|
||||
+ "endpoint device name",
|
||||
+ "filter by CXL endpoint device name(s)"),
|
||||
+ OPT_BOOLEAN('E', "endpoints", ¶m.endpoints,
|
||||
+ "include CXL endpoint info"),
|
||||
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
"use human friendly number formats "),
|
||||
@@ -44,7 +49,8 @@ static const struct option options[] = {
|
||||
|
||||
static int num_list_flags(void)
|
||||
{
|
||||
- return !!param.memdevs + !!param.buses + !!param.ports;
|
||||
+ return !!param.memdevs + !!param.buses + !!param.ports +
|
||||
+ !!param.endpoints;
|
||||
}
|
||||
|
||||
int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
@@ -74,6 +80,8 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
param.buses = true;
|
||||
if (param.port_filter)
|
||||
param.ports = true;
|
||||
+ if (param.endpoint_filter)
|
||||
+ param.endpoints = true;
|
||||
if (num_list_flags() == 0) {
|
||||
/*
|
||||
* TODO: We likely want to list regions by default if
|
||||
@@ -96,6 +104,9 @@ int cmd_list(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
if (cxl_filter_has(param.port_filter, "root") && param.ports)
|
||||
param.buses = true;
|
||||
|
||||
+ if (cxl_filter_has(param.port_filter, "endpoint") && param.ports)
|
||||
+ param.endpoints = true;
|
||||
+
|
||||
dbg(¶m, "walk topology\n");
|
||||
return cxl_filter_walk(ctx, ¶m);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,154 @@
|
||||
From f39735be3c1157fdfa7dd5c781048a411ebe4dc5 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:34 -0800
|
||||
Subject: [PATCH 106/217] cxl/list: Add 'host' entries for port-like objects
|
||||
|
||||
Add the device name of the "host" device for a given CXL port object. The
|
||||
kernel calls this the 'uport' attribute.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298561473.3021641.16508989603599026269.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 9 +++++++++
|
||||
Documentation/cxl/lib/libcxl.txt | 5 +++++
|
||||
cxl/json.c | 4 ++++
|
||||
cxl/lib/libcxl.c | 10 ++++++++++
|
||||
cxl/lib/libcxl.sym | 2 ++
|
||||
cxl/libcxl.h | 2 ++
|
||||
6 files changed, 32 insertions(+)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index d342da2..30b6161 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -210,6 +210,15 @@ OPTIONS
|
||||
--endpoints::
|
||||
Include endpoint objects (CXL Memory Device decoders) in the
|
||||
listing.
|
||||
+----
|
||||
+# cxl list -E
|
||||
+[
|
||||
+ {
|
||||
+ "endpoint":"endpoint2",
|
||||
+ "host":"mem0"
|
||||
+ }
|
||||
+]
|
||||
+----
|
||||
|
||||
-e::
|
||||
--endpoint::
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index eebab37..e4b372d 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -178,6 +178,7 @@ struct cxl_port *cxl_port_get_next(struct cxl_port *port);
|
||||
struct cxl_port *cxl_port_get_parent(struct cxl_port *port);
|
||||
struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
|
||||
struct cxl_ctx *cxl_port_get_ctx(struct cxl_port *port);
|
||||
+const char *cxl_port_get_host(struct cxl_port *port);
|
||||
|
||||
#define cxl_port_foreach(parent, port) \
|
||||
for (port = cxl_port_get_first(parent); port != NULL; \
|
||||
@@ -192,6 +193,9 @@ as a parent object retrievable via cxl_port_get_parent().
|
||||
The root port of a hiearchy can be retrieved via any port instance in
|
||||
that hierarchy via cxl_port_get_bus().
|
||||
|
||||
+The host of a port is the corresponding device name of the PCIe Root
|
||||
+Port, or Switch Upstream Port with CXL capabilities.
|
||||
+
|
||||
=== PORT: Attributes
|
||||
----
|
||||
const char *cxl_port_get_devname(struct cxl_port *port);
|
||||
@@ -222,6 +226,7 @@ struct cxl_endpoint *cxl_endpoint_get_next(struct cxl_endpoint *endpoint);
|
||||
struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
+const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
|
||||
|
||||
#define cxl_endpoint_foreach(port, endpoint) \
|
||||
for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index 08f6192..af3b4fe 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -258,6 +258,10 @@ static struct json_object *__util_cxl_port_to_json(struct cxl_port *port,
|
||||
if (jobj)
|
||||
json_object_object_add(jport, name_key, jobj);
|
||||
|
||||
+ jobj = json_object_new_string(cxl_port_get_host(port));
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jport, "host", jobj);
|
||||
+
|
||||
if (!cxl_port_is_enabled(port)) {
|
||||
jobj = json_object_new_string("disabled");
|
||||
if (jobj)
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index a25e715..5f48202 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -626,6 +626,11 @@ CXL_EXPORT struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint)
|
||||
return &endpoint->port;
|
||||
}
|
||||
|
||||
+CXL_EXPORT const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ return cxl_port_get_host(&endpoint->port);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint)
|
||||
{
|
||||
return cxl_port_is_enabled(&endpoint->port);
|
||||
@@ -744,6 +749,11 @@ CXL_EXPORT struct cxl_bus *cxl_port_get_bus(struct cxl_port *port)
|
||||
return bus;
|
||||
}
|
||||
|
||||
+CXL_EXPORT const char *cxl_port_get_host(struct cxl_port *port)
|
||||
+{
|
||||
+ return devpath_to_devname(port->uport);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 7a51a0c..dc2863e 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -95,6 +95,7 @@ global:
|
||||
cxl_port_to_bus;
|
||||
cxl_port_is_endpoint;
|
||||
cxl_port_get_bus;
|
||||
+ cxl_port_get_host;
|
||||
cxl_endpoint_get_first;
|
||||
cxl_endpoint_get_next;
|
||||
cxl_endpoint_get_devname;
|
||||
@@ -103,4 +104,5 @@ global:
|
||||
cxl_endpoint_is_enabled;
|
||||
cxl_endpoint_get_parent;
|
||||
cxl_endpoint_get_port;
|
||||
+ cxl_endpoint_get_host;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index f6ba9a1..a60777e 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -83,6 +83,7 @@ bool cxl_port_is_switch(struct cxl_port *port);
|
||||
struct cxl_bus *cxl_port_to_bus(struct cxl_port *port);
|
||||
bool cxl_port_is_endpoint(struct cxl_port *port);
|
||||
struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
|
||||
+const char *cxl_port_get_host(struct cxl_port *port);
|
||||
|
||||
#define cxl_port_foreach(parent, port) \
|
||||
for (port = cxl_port_get_first(parent); port != NULL; \
|
||||
@@ -97,6 +98,7 @@ struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint);
|
||||
int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
+const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
|
||||
|
||||
#define cxl_endpoint_foreach(port, endpoint) \
|
||||
for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \
|
||||
--
|
||||
2.27.0
|
||||
|
175
SOURCES/0107-cxl-list-Add-host-entries-for-memdevs.patch
Normal file
175
SOURCES/0107-cxl-list-Add-host-entries-for-memdevs.patch
Normal file
@ -0,0 +1,175 @@
|
||||
From eec8c953a840a1cbdca63352c64cec3e48e86afe Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:39 -0800
|
||||
Subject: [PATCH 107/217] cxl/list: Add 'host' entries for memdevs
|
||||
|
||||
For debugging CXL port connectivity issues it will be useful to have the
|
||||
PCI device name for the memory expander in the 'memdev' listing.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298561980.3021641.9636572507721689266.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@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(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 30b6161..9c21ab7 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -43,7 +43,8 @@ EXAMPLE
|
||||
"memdev":"mem0",
|
||||
"pmem_size":268435456,
|
||||
"ram_size":0,
|
||||
- "serial":0
|
||||
+ "serial":0,
|
||||
+ "host":"0000:35:00.0"
|
||||
}
|
||||
]
|
||||
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index e4b372d..91fd33e 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -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);
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index af3b4fe..1868686 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 5f48202..c4ddc7d 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -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;
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index dc2863e..8f0688a 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -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;
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index cedd2f2..b097bdf 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -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;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index a60777e..5487b55 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -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);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,499 @@
|
||||
From 41d6769393f449008abf934e815f137360889633 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:45 -0800
|
||||
Subject: [PATCH 108/217] cxl/list: Move enabled memdevs underneath their
|
||||
endpoint
|
||||
|
||||
When a memdev is enabled it means that the kernel was able to validate a
|
||||
CXL connection from the CXL root, through intervening switches, and to the
|
||||
endpoint. Reflect that state by listing memdevs as child objects of
|
||||
endpoints, or aggregated into an array if individual endpoints are not
|
||||
listed.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298562531.3021641.10620937879296964476.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 11 ++-
|
||||
Documentation/cxl/lib/libcxl.txt | 2 +
|
||||
cxl/filter.c | 130 ++++++++++++++++++++++++-------
|
||||
cxl/json.c | 6 ++
|
||||
cxl/lib/libcxl.c | 97 +++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 3 +
|
||||
cxl/libcxl.h | 4 +
|
||||
7 files changed, 223 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 9c21ab7..1751868 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -19,7 +19,16 @@ Options can be specified to limit the output to specific objects. When a
|
||||
single object type is specified the return json object is an array of
|
||||
just those objects, when multiple objects types are specified the
|
||||
returned the returned object may be an array of arrays with the inner
|
||||
-array named for the given object type.
|
||||
+array named for the given object type. The top-level arrays are ellided
|
||||
+when the objects can nest under a higher object-type in the hierararchy.
|
||||
+The potential top-level array names and their nesting properties are:
|
||||
+
|
||||
+"anon memdevs":: (disabled memory devices) do not nest
|
||||
+"buses":: do not nest
|
||||
+"ports":: nest under buses
|
||||
+"endpoints":: nest under ports or buses (if ports are not emitted)
|
||||
+"memdevs":: nest under endpoints or ports (if endpoints are not
|
||||
+ emitted) or buses (if endpoints and ports are not emitted)
|
||||
|
||||
Filters can by specifed as either a single identidier, a space separated
|
||||
quoted string, or a comma separated list. When multiple filter
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index 91fd33e..73b0fb9 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -41,6 +41,7 @@ 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)
|
||||
+struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint);
|
||||
|
||||
#define cxl_memdev_foreach(ctx, memdev) \
|
||||
for (memdev = cxl_memdev_get_first(ctx); \
|
||||
@@ -231,6 +232,7 @@ struct cxl_ctx *cxl_endpoint_get_ctx(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev);
|
||||
|
||||
#define cxl_endpoint_foreach(port, endpoint) \
|
||||
for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 5d80d1b..2130816 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -381,13 +381,16 @@ static struct json_object *pick_array(struct json_object *child,
|
||||
}
|
||||
|
||||
static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
|
||||
- struct json_object *jeps, unsigned long flags)
|
||||
+ struct json_object *jeps, struct json_object *jdevs,
|
||||
+ unsigned long flags)
|
||||
{
|
||||
struct cxl_endpoint *endpoint;
|
||||
|
||||
cxl_endpoint_foreach(port, endpoint) {
|
||||
struct cxl_port *ep_port = cxl_endpoint_get_port(endpoint);
|
||||
- struct json_object *jendpoint;
|
||||
+ const char *devname = cxl_endpoint_get_devname(endpoint);
|
||||
+ struct json_object *jendpoint = NULL;
|
||||
+ struct cxl_memdev *memdev;
|
||||
|
||||
if (!util_cxl_endpoint_filter(endpoint, p->endpoint_filter))
|
||||
continue;
|
||||
@@ -398,24 +401,54 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
|
||||
continue;
|
||||
if (!p->idle && !cxl_endpoint_is_enabled(endpoint))
|
||||
continue;
|
||||
- jendpoint = util_cxl_endpoint_to_json(endpoint, flags);
|
||||
- if (jendpoint)
|
||||
+ if (p->endpoints) {
|
||||
+ jendpoint = util_cxl_endpoint_to_json(endpoint, flags);
|
||||
+ if (!jendpoint) {
|
||||
+ err(p, "%s: failed to list\n", devname);
|
||||
+ continue;
|
||||
+ }
|
||||
json_object_array_add(jeps, jendpoint);
|
||||
+ }
|
||||
+ if (p->memdevs) {
|
||||
+ struct json_object *jobj;
|
||||
+
|
||||
+ memdev = cxl_endpoint_get_memdev(endpoint);
|
||||
+ if (!memdev)
|
||||
+ continue;
|
||||
+ if (!util_cxl_memdev_filter(memdev, p->memdev_filter,
|
||||
+ p->serial_filter))
|
||||
+ continue;
|
||||
+ if (!p->idle && !cxl_memdev_is_enabled(memdev))
|
||||
+ continue;
|
||||
+ jobj = util_cxl_memdev_to_json(memdev, flags);
|
||||
+ if (!jobj) {
|
||||
+ err(p, "failed to json serialize %s\n",
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (p->endpoints)
|
||||
+ json_object_object_add(jendpoint, "memdev",
|
||||
+ jobj);
|
||||
+ else
|
||||
+ json_object_array_add(jdevs, jobj);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
static void walk_child_ports(struct cxl_port *parent_port,
|
||||
struct cxl_filter_params *p,
|
||||
struct json_object *jports,
|
||||
- struct json_object *jeps, unsigned long flags)
|
||||
+ struct json_object *jeps,
|
||||
+ struct json_object *jdevs, unsigned long flags)
|
||||
{
|
||||
struct cxl_port *port;
|
||||
|
||||
cxl_port_foreach(parent_port, port) {
|
||||
const char *devname = cxl_port_get_devname(port);
|
||||
struct json_object *jport = NULL;
|
||||
+ struct json_object *jchilddevs = NULL;
|
||||
struct json_object *jchildports = NULL;
|
||||
- struct json_object *jchildendpoints = NULL;
|
||||
+ struct json_object *jchildeps = NULL;
|
||||
|
||||
if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
|
||||
goto walk_children;
|
||||
@@ -436,28 +469,41 @@ static void walk_child_ports(struct cxl_port *parent_port,
|
||||
devname);
|
||||
continue;
|
||||
}
|
||||
- }
|
||||
|
||||
- if (p->ports && p->endpoints) {
|
||||
- jchildendpoints = json_object_new_array();
|
||||
- if (!jchildendpoints) {
|
||||
- err(p,
|
||||
- "%s: failed to enumerate child endpoints\n",
|
||||
- devname);
|
||||
- continue;
|
||||
+ if (p->memdevs && !p->endpoints) {
|
||||
+ jchilddevs = json_object_new_array();
|
||||
+ if (!jchilddevs) {
|
||||
+ err(p,
|
||||
+ "%s: failed to enumerate child memdevs\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (p->endpoints) {
|
||||
+ jchildeps = json_object_new_array();
|
||||
+ if (!jchildeps) {
|
||||
+ err(p,
|
||||
+ "%s: failed to enumerate child endpoints\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
walk_children:
|
||||
- if (p->endpoints)
|
||||
- walk_endpoints(port, p, pick_array(jchildendpoints, jeps),
|
||||
- flags);
|
||||
+ if (p->endpoints || p->memdevs)
|
||||
+ walk_endpoints(port, p, pick_array(jchildeps, jeps),
|
||||
+ pick_array(jchilddevs, jdevs), flags);
|
||||
|
||||
walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
- pick_array(jchildendpoints, jeps), flags);
|
||||
+ pick_array(jchildeps, jeps),
|
||||
+ pick_array(jchilddevs, jdevs), flags);
|
||||
cond_add_put_array_suffix(jport, "ports", devname, jchildports);
|
||||
cond_add_put_array_suffix(jport, "endpoints", devname,
|
||||
- jchildendpoints);
|
||||
+ jchildeps);
|
||||
+ cond_add_put_array_suffix(jport, "memdevs", devname,
|
||||
+ jchilddevs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,6 +512,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
struct json_object *jdevs = NULL, *jbuses = NULL, *jports = NULL;
|
||||
struct json_object *jplatform = json_object_new_array();
|
||||
unsigned long flags = params_to_flags(p);
|
||||
+ struct json_object *janondevs = NULL;
|
||||
struct json_object *jeps = NULL;
|
||||
struct cxl_memdev *memdev;
|
||||
int top_level_objs = 0;
|
||||
@@ -476,8 +523,8 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
- jdevs = json_object_new_array();
|
||||
- if (!jdevs)
|
||||
+ janondevs = json_object_new_array();
|
||||
+ if (!janondevs)
|
||||
goto err;
|
||||
|
||||
jbuses = json_object_new_array();
|
||||
@@ -492,20 +539,28 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
if (!jeps)
|
||||
goto err;
|
||||
|
||||
+ jdevs = json_object_new_array();
|
||||
+ if (!jdevs)
|
||||
+ goto err;
|
||||
+
|
||||
dbg(p, "walk memdevs\n");
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
- struct json_object *jdev;
|
||||
+ struct json_object *janondev;
|
||||
|
||||
if (!util_cxl_memdev_filter(memdev, p->memdev_filter,
|
||||
p->serial_filter))
|
||||
continue;
|
||||
+ if (cxl_memdev_is_enabled(memdev))
|
||||
+ continue;
|
||||
+ if (!p->idle)
|
||||
+ continue;
|
||||
if (p->memdevs) {
|
||||
- jdev = util_cxl_memdev_to_json(memdev, flags);
|
||||
- if (!jdev) {
|
||||
+ janondev = util_cxl_memdev_to_json(memdev, flags);
|
||||
+ if (!janondev) {
|
||||
dbg(p, "memdev object allocation failure\n");
|
||||
continue;
|
||||
}
|
||||
- json_object_array_add(jdevs, jdev);
|
||||
+ json_object_array_add(janondevs, janondev);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -513,6 +568,7 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
cxl_bus_foreach(ctx, bus) {
|
||||
struct json_object *jbus = NULL;
|
||||
struct json_object *jchildports = NULL;
|
||||
+ struct json_object *jchilddevs = NULL;
|
||||
struct json_object *jchildeps = NULL;
|
||||
struct cxl_port *port = cxl_bus_get_port(bus);
|
||||
const char *devname = cxl_bus_get_devname(bus);
|
||||
@@ -546,17 +602,29 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (p->memdevs && !p->ports && !p->endpoints) {
|
||||
+ jchilddevs = json_object_new_array();
|
||||
+ if (!jchilddevs) {
|
||||
+ err(p,
|
||||
+ "%s: failed to enumerate child memdevs\n",
|
||||
+ devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
walk_children:
|
||||
dbg(p, "walk ports\n");
|
||||
walk_child_ports(port, p, pick_array(jchildports, jports),
|
||||
- pick_array(jchildeps, jeps), flags);
|
||||
+ pick_array(jchildeps, jeps),
|
||||
+ pick_array(jchilddevs, jdevs), flags);
|
||||
cond_add_put_array_suffix(jbus, "ports", devname, jchildports);
|
||||
cond_add_put_array_suffix(jbus, "endpoints", devname,
|
||||
jchildeps);
|
||||
+ cond_add_put_array_suffix(jbus, "memdevs", devname, jchilddevs);
|
||||
}
|
||||
|
||||
- if (json_object_array_length(jdevs))
|
||||
+ if (json_object_array_length(janondevs))
|
||||
top_level_objs++;
|
||||
if (json_object_array_length(jbuses))
|
||||
top_level_objs++;
|
||||
@@ -564,20 +632,24 @@ walk_children:
|
||||
top_level_objs++;
|
||||
if (json_object_array_length(jeps))
|
||||
top_level_objs++;
|
||||
+ if (json_object_array_length(jdevs))
|
||||
+ top_level_objs++;
|
||||
|
||||
- splice_array(p, jdevs, jplatform, "anon memdevs", top_level_objs > 1);
|
||||
+ splice_array(p, janondevs, jplatform, "anon memdevs", top_level_objs > 1);
|
||||
splice_array(p, jbuses, jplatform, "buses", top_level_objs > 1);
|
||||
splice_array(p, jports, jplatform, "ports", top_level_objs > 1);
|
||||
splice_array(p, jeps, jplatform, "endpoints", top_level_objs > 1);
|
||||
+ splice_array(p, jdevs, jplatform, "memdevs", top_level_objs > 1);
|
||||
|
||||
util_display_json_array(stdout, jplatform, flags);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
- json_object_put(jdevs);
|
||||
+ json_object_put(janondevs);
|
||||
json_object_put(jbuses);
|
||||
json_object_put(jports);
|
||||
json_object_put(jeps);
|
||||
+ json_object_put(jdevs);
|
||||
json_object_put(jplatform);
|
||||
return -ENOMEM;
|
||||
}
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index 1868686..b809332 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -224,6 +224,12 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
if (jobj)
|
||||
json_object_object_add(jdev, "host", jobj);
|
||||
|
||||
+ if (!cxl_memdev_is_enabled(memdev)) {
|
||||
+ jobj = json_object_new_string("disabled");
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdev, "state", jobj);
|
||||
+ }
|
||||
+
|
||||
return jdev;
|
||||
}
|
||||
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index c4ddc7d..4523ca6 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -480,6 +480,60 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev
|
||||
return memdev->firmware_version;
|
||||
}
|
||||
|
||||
+static struct cxl_endpoint *cxl_port_find_endpoint(struct cxl_port *parent_port,
|
||||
+ struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_endpoint *endpoint;
|
||||
+ struct cxl_port *port;
|
||||
+
|
||||
+ cxl_port_foreach(parent_port, port) {
|
||||
+ cxl_endpoint_foreach(port, endpoint)
|
||||
+ if (strcmp(cxl_endpoint_get_host(endpoint),
|
||||
+ cxl_memdev_get_devname(memdev)) == 0)
|
||||
+ return endpoint;
|
||||
+ endpoint = cxl_port_find_endpoint(port, memdev);
|
||||
+ if (endpoint)
|
||||
+ return endpoint;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_endpoint *
|
||||
+cxl_memdev_get_endpoint(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ struct cxl_endpoint *endpoint = NULL;
|
||||
+ struct cxl_bus *bus;
|
||||
+
|
||||
+ if (memdev->endpoint)
|
||||
+ return memdev->endpoint;
|
||||
+
|
||||
+ if (!cxl_memdev_is_enabled(memdev))
|
||||
+ return NULL;
|
||||
+
|
||||
+ cxl_bus_foreach (ctx, bus) {
|
||||
+ struct cxl_port *port = cxl_bus_get_port(bus);
|
||||
+
|
||||
+ endpoint = cxl_port_find_endpoint(port, memdev);
|
||||
+ if (endpoint)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!endpoint)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (endpoint->memdev && endpoint->memdev != memdev)
|
||||
+ err(ctx, "%s assigned to %s not %s\n",
|
||||
+ cxl_endpoint_get_devname(endpoint),
|
||||
+ cxl_memdev_get_devname(endpoint->memdev),
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ memdev->endpoint = endpoint;
|
||||
+ endpoint->memdev = memdev;
|
||||
+
|
||||
+ return endpoint;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev)
|
||||
{
|
||||
return memdev->lsa_size;
|
||||
@@ -495,6 +549,21 @@ static int is_enabled(const char *drvpath)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+CXL_EXPORT int cxl_memdev_is_enabled(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ char *path = memdev->dev_buf;
|
||||
+ int len = memdev->buf_len;
|
||||
+
|
||||
+ if (snprintf(path, len, "%s/driver", memdev->dev_path) >= len) {
|
||||
+ err(ctx, "%s: buffer too small!\n",
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return is_enabled(path);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev)
|
||||
{
|
||||
struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
@@ -660,6 +729,34 @@ CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint)
|
||||
return cxl_port_is_enabled(&endpoint->port);
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_memdev *
|
||||
+cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_endpoint_get_ctx(endpoint);
|
||||
+ struct cxl_memdev *memdev;
|
||||
+
|
||||
+ if (endpoint->memdev)
|
||||
+ return endpoint->memdev;
|
||||
+
|
||||
+ if (!cxl_endpoint_is_enabled(endpoint))
|
||||
+ return NULL;
|
||||
+
|
||||
+ cxl_memdev_foreach(ctx, memdev)
|
||||
+ if (strcmp(cxl_memdev_get_devname(memdev),
|
||||
+ cxl_endpoint_get_host(endpoint)) == 0) {
|
||||
+ if (memdev->endpoint && memdev->endpoint != endpoint)
|
||||
+ err(ctx, "%s assigned to %s not %s\n",
|
||||
+ cxl_memdev_get_devname(memdev),
|
||||
+ cxl_endpoint_get_devname(memdev->endpoint),
|
||||
+ cxl_endpoint_get_devname(endpoint));
|
||||
+ endpoint->memdev = memdev;
|
||||
+ memdev->endpoint = endpoint;
|
||||
+ return memdev;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static void *add_cxl_port(void *parent, int id, const char *cxlport_base)
|
||||
{
|
||||
const char *devname = devpath_to_devname(cxlport_base);
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 8f0688a..321acac 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -106,4 +106,7 @@ global:
|
||||
cxl_endpoint_get_parent;
|
||||
cxl_endpoint_get_port;
|
||||
cxl_endpoint_get_host;
|
||||
+ cxl_endpoint_get_memdev;
|
||||
+ cxl_memdev_get_endpoint;
|
||||
+ cxl_memdev_is_enabled;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 5487b55..790ece8 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -46,6 +46,8 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev);
|
||||
unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
+struct cxl_endpoint;
|
||||
+struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev);
|
||||
int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
||||
int cxl_memdev_zero_label(struct cxl_memdev *memdev, size_t length,
|
||||
size_t offset);
|
||||
@@ -100,6 +102,8 @@ int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint);
|
||||
+int cxl_memdev_is_enabled(struct cxl_memdev *memdev);
|
||||
|
||||
#define cxl_endpoint_foreach(port, endpoint) \
|
||||
for (endpoint = cxl_endpoint_get_first(port); endpoint != NULL; \
|
||||
--
|
||||
2.27.0
|
||||
|
329
SOURCES/0109-cxl-list-Filter-memdev-by-ancestry.patch
Normal file
329
SOURCES/0109-cxl-list-Filter-memdev-by-ancestry.patch
Normal file
@ -0,0 +1,329 @@
|
||||
From b90fc91e1034668cfde06f0fd8a7293df8b7690d Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:50 -0800
|
||||
Subject: [PATCH 109/217] cxl/list: Filter memdev by ancestry
|
||||
|
||||
Whenever a memdev filter is specified limit output of buses, ports and
|
||||
endpoints to those that are in the memdev's ancestry.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298563039.3021641.5253222797042241091.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-list.txt | 19 +++++++++
|
||||
Documentation/cxl/lib/libcxl.txt | 11 +++++
|
||||
cxl/filter.c | 69 ++++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.c | 36 +++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 5 +++
|
||||
cxl/libcxl.h | 4 ++
|
||||
6 files changed, 144 insertions(+)
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 1751868..bac27c7 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -39,6 +39,25 @@ they are combined as an 'AND' filter. So, "-m mem0,mem1,mem2 -p port10"
|
||||
would only list objects that are beneath port10 AND map mem0, mem1, OR
|
||||
mem2.
|
||||
|
||||
+Given that many topology queries seek to answer questions relative to a
|
||||
+given memdev, buses, ports, and endpoints can be filtered by one or more
|
||||
+memdevs. For example:
|
||||
+----
|
||||
+# cxl list -P -p switch,endpoint -m mem0
|
||||
+[
|
||||
+ {
|
||||
+ "port":"port1",
|
||||
+ "host":"ACPI0016:00",
|
||||
+ "endpoints:port1":[
|
||||
+ {
|
||||
+ "endpoint":"endpoint2",
|
||||
+ "host":"mem0"
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+]
|
||||
+----
|
||||
+
|
||||
The --human option in addition to reformatting some fields to more human
|
||||
friendly strings also unwraps the array to reduce the number of lines of
|
||||
output.
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index 73b0fb9..b0253d7 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -150,11 +150,18 @@ cxl_bus'.
|
||||
----
|
||||
struct cxl_bus *cxl_bus_get_first(struct cxl_ctx *ctx);
|
||||
struct cxl_bus *cxl_bus_get_next(struct cxl_bus *bus);
|
||||
+struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus);
|
||||
+struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev);
|
||||
+struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint);
|
||||
|
||||
#define cxl_bus_foreach(ctx, bus) \
|
||||
for (bus = cxl_bus_get_first(ctx); bus != NULL; \
|
||||
bus = cxl_bus_get_next(bus))
|
||||
----
|
||||
+When a memdev is active it has established a CXL port hierarchy between
|
||||
+itself and the root of its associated CXL topology. The
|
||||
+cxl_{memdev,endpoint}_get_bus() helpers walk that topology to retrieve
|
||||
+the associated bus object.
|
||||
|
||||
=== BUS: Attributes
|
||||
----
|
||||
@@ -209,6 +216,7 @@ int cxl_port_is_enabled(struct cxl_port *port);
|
||||
bool cxl_port_is_root(struct cxl_port *port);
|
||||
bool cxl_port_is_switch(struct cxl_port *port);
|
||||
bool cxl_port_is_endpoint(struct cxl_port *port);
|
||||
+bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev);
|
||||
----
|
||||
The port type is communicated via cxl_port_is_<type>(). An 'enabled' port
|
||||
is one that has succeeded in discovering the CXL component registers in
|
||||
@@ -217,6 +225,9 @@ memdev to be enabled for CXL memory operation all CXL ports in its
|
||||
ancestry must also be enabled including a root port, an arbitrary number
|
||||
of intervening switch ports, and a terminal endpoint port.
|
||||
|
||||
+cxl_port_hosts_memdev() returns true if the port's host appears in the
|
||||
+memdev host's device topology ancestry.
|
||||
+
|
||||
ENDPOINTS
|
||||
---------
|
||||
CXL endpoint objects encapsulate the set of host-managed device-memory
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index 2130816..6dc61a1 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -297,6 +297,66 @@ struct cxl_memdev *util_cxl_memdev_filter(struct cxl_memdev *memdev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct cxl_bus *util_cxl_bus_filter_by_memdev(struct cxl_bus *bus,
|
||||
+ const char *ident,
|
||||
+ const char *serial)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_bus_get_ctx(bus);
|
||||
+ struct cxl_memdev *memdev;
|
||||
+
|
||||
+ if (!ident && !serial)
|
||||
+ return bus;
|
||||
+
|
||||
+ cxl_memdev_foreach(ctx, memdev) {
|
||||
+ if (!util_cxl_memdev_filter(memdev, ident, serial))
|
||||
+ continue;
|
||||
+ if (cxl_memdev_get_bus(memdev) == bus)
|
||||
+ return bus;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static struct cxl_endpoint *
|
||||
+util_cxl_endpoint_filter_by_memdev(struct cxl_endpoint *endpoint,
|
||||
+ const char *ident, const char *serial)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_endpoint_get_ctx(endpoint);
|
||||
+ struct cxl_memdev *memdev;
|
||||
+
|
||||
+ if (!ident && !serial)
|
||||
+ return endpoint;
|
||||
+
|
||||
+ cxl_memdev_foreach(ctx, memdev) {
|
||||
+ if (!util_cxl_memdev_filter(memdev, ident, serial))
|
||||
+ continue;
|
||||
+ if (cxl_memdev_get_endpoint(memdev) == endpoint)
|
||||
+ return endpoint;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static struct cxl_port *util_cxl_port_filter_by_memdev(struct cxl_port *port,
|
||||
+ const char *ident,
|
||||
+ const char *serial)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
+ struct cxl_memdev *memdev;
|
||||
+
|
||||
+ if (!ident && !serial)
|
||||
+ return port;
|
||||
+
|
||||
+ cxl_memdev_foreach(ctx, memdev) {
|
||||
+ if (!util_cxl_memdev_filter(memdev, ident, serial))
|
||||
+ continue;
|
||||
+ if (cxl_port_hosts_memdev(port, memdev))
|
||||
+ return port;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static unsigned long params_to_flags(struct cxl_filter_params *param)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
@@ -399,6 +459,9 @@ static void walk_endpoints(struct cxl_port *port, struct cxl_filter_params *p,
|
||||
if (!util_cxl_endpoint_filter_by_port(endpoint, p->port_filter,
|
||||
pf_mode(p)))
|
||||
continue;
|
||||
+ if (!util_cxl_endpoint_filter_by_memdev(
|
||||
+ endpoint, p->memdev_filter, p->serial_filter))
|
||||
+ continue;
|
||||
if (!p->idle && !cxl_endpoint_is_enabled(endpoint))
|
||||
continue;
|
||||
if (p->endpoints) {
|
||||
@@ -450,6 +513,9 @@ static void walk_child_ports(struct cxl_port *parent_port,
|
||||
struct json_object *jchildports = NULL;
|
||||
struct json_object *jchildeps = NULL;
|
||||
|
||||
+ if (!util_cxl_port_filter_by_memdev(port, p->memdev_filter,
|
||||
+ p->serial_filter))
|
||||
+ continue;
|
||||
if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
|
||||
goto walk_children;
|
||||
if (!util_cxl_port_filter_by_bus(port, p->bus_filter))
|
||||
@@ -573,6 +639,9 @@ int cxl_filter_walk(struct cxl_ctx *ctx, struct cxl_filter_params *p)
|
||||
struct cxl_port *port = cxl_bus_get_port(bus);
|
||||
const char *devname = cxl_bus_get_devname(bus);
|
||||
|
||||
+ if (!util_cxl_bus_filter_by_memdev(bus, p->memdev_filter,
|
||||
+ p->serial_filter))
|
||||
+ continue;
|
||||
if (!util_cxl_bus_filter(bus, p->bus_filter))
|
||||
goto walk_children;
|
||||
if (!util_cxl_port_filter(port, p->port_filter, pf_mode(p)))
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 4523ca6..0065f6b 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -455,6 +455,15 @@ CXL_EXPORT const char *cxl_memdev_get_host(struct cxl_memdev *memdev)
|
||||
return memdev->host;
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_endpoint *endpoint = cxl_memdev_get_endpoint(memdev);
|
||||
+
|
||||
+ if (!endpoint)
|
||||
+ return NULL;
|
||||
+ return cxl_endpoint_get_bus(endpoint);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_memdev_get_major(struct cxl_memdev *memdev)
|
||||
{
|
||||
return memdev->major;
|
||||
@@ -724,6 +733,13 @@ CXL_EXPORT const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint)
|
||||
return cxl_port_get_host(&endpoint->port);
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint)
|
||||
+{
|
||||
+ struct cxl_port *port = &endpoint->port;
|
||||
+
|
||||
+ return cxl_port_get_bus(port);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint)
|
||||
{
|
||||
return cxl_port_is_enabled(&endpoint->port);
|
||||
@@ -875,6 +891,21 @@ CXL_EXPORT const char *cxl_port_get_host(struct cxl_port *port)
|
||||
return devpath_to_devname(port->uport);
|
||||
}
|
||||
|
||||
+CXL_EXPORT bool cxl_port_hosts_memdev(struct cxl_port *port,
|
||||
+ struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_endpoint *endpoint = cxl_memdev_get_endpoint(memdev);
|
||||
+ struct cxl_port *iter;
|
||||
+
|
||||
+ if (!endpoint)
|
||||
+ return false;
|
||||
+
|
||||
+ iter = cxl_endpoint_get_port(endpoint);
|
||||
+ while (iter && iter != port)
|
||||
+ iter = iter->parent;
|
||||
+ return iter != NULL;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT int cxl_port_is_enabled(struct cxl_port *port)
|
||||
{
|
||||
struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
@@ -985,6 +1016,11 @@ CXL_EXPORT const char *cxl_bus_get_provider(struct cxl_bus *bus)
|
||||
return devname;
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus)
|
||||
+{
|
||||
+ return cxl_port_get_ctx(&bus->port);
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT void cxl_cmd_unref(struct cxl_cmd *cmd)
|
||||
{
|
||||
if (!cmd)
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 321acac..29f3498 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -84,6 +84,7 @@ global:
|
||||
cxl_bus_get_devname;
|
||||
cxl_bus_get_id;
|
||||
cxl_bus_get_port;
|
||||
+ cxl_bus_get_ctx;
|
||||
cxl_port_get_first;
|
||||
cxl_port_get_next;
|
||||
cxl_port_get_devname;
|
||||
@@ -97,6 +98,8 @@ global:
|
||||
cxl_port_is_endpoint;
|
||||
cxl_port_get_bus;
|
||||
cxl_port_get_host;
|
||||
+ cxl_port_get_bus;
|
||||
+ cxl_port_hosts_memdev;
|
||||
cxl_endpoint_get_first;
|
||||
cxl_endpoint_get_next;
|
||||
cxl_endpoint_get_devname;
|
||||
@@ -107,6 +110,8 @@ global:
|
||||
cxl_endpoint_get_port;
|
||||
cxl_endpoint_get_host;
|
||||
cxl_endpoint_get_memdev;
|
||||
+ cxl_endpoint_get_bus;
|
||||
cxl_memdev_get_endpoint;
|
||||
cxl_memdev_is_enabled;
|
||||
+ cxl_memdev_get_bus;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 790ece8..e7b675e 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -39,6 +39,7 @@ 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);
|
||||
+struct cxl_bus *cxl_memdev_get_bus(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);
|
||||
@@ -68,6 +69,7 @@ const char *cxl_bus_get_provider(struct cxl_bus *bus);
|
||||
const char *cxl_bus_get_devname(struct cxl_bus *bus);
|
||||
int cxl_bus_get_id(struct cxl_bus *bus);
|
||||
struct cxl_port *cxl_bus_get_port(struct cxl_bus *bus);
|
||||
+struct cxl_ctx *cxl_bus_get_ctx(struct cxl_bus *bus);
|
||||
|
||||
#define cxl_bus_foreach(ctx, bus) \
|
||||
for (bus = cxl_bus_get_first(ctx); bus != NULL; \
|
||||
@@ -87,6 +89,7 @@ struct cxl_bus *cxl_port_to_bus(struct cxl_port *port);
|
||||
bool cxl_port_is_endpoint(struct cxl_port *port);
|
||||
struct cxl_bus *cxl_port_get_bus(struct cxl_port *port);
|
||||
const char *cxl_port_get_host(struct cxl_port *port);
|
||||
+bool cxl_port_hosts_memdev(struct cxl_port *port, struct cxl_memdev *memdev);
|
||||
|
||||
#define cxl_port_foreach(parent, port) \
|
||||
for (port = cxl_port_get_first(parent); port != NULL; \
|
||||
@@ -102,6 +105,7 @@ int cxl_endpoint_is_enabled(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_parent(struct cxl_endpoint *endpoint);
|
||||
struct cxl_port *cxl_endpoint_get_port(struct cxl_endpoint *endpoint);
|
||||
const char *cxl_endpoint_get_host(struct cxl_endpoint *endpoint);
|
||||
+struct cxl_bus *cxl_endpoint_get_bus(struct cxl_endpoint *endpoint);
|
||||
struct cxl_memdev *cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint);
|
||||
int cxl_memdev_is_enabled(struct cxl_memdev *memdev);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
173
SOURCES/0110-cxl-memdev-Use-a-local-logger-for-debug.patch
Normal file
173
SOURCES/0110-cxl-memdev-Use-a-local-logger-for-debug.patch
Normal file
@ -0,0 +1,173 @@
|
||||
From 5e1c1ab5bf6b6257552ad9fa242483ec1c1de006 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:53:55 -0800
|
||||
Subject: [PATCH 110/217] cxl/memdev: Use a local logger for debug
|
||||
|
||||
The "fail()" macro skips some of the nicer features of the centralized
|
||||
logger. Add one to supplement the library logger.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298563547.3021641.16504008034705274247.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/memdev.c | 48 ++++++++++++++++++++++++------------------------
|
||||
1 file changed, 24 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/cxl/memdev.c b/cxl/memdev.c
|
||||
index b9141be..327c260 100644
|
||||
--- a/cxl/memdev.c
|
||||
+++ b/cxl/memdev.c
|
||||
@@ -26,11 +26,7 @@ static struct parameters {
|
||||
bool verbose;
|
||||
} param;
|
||||
|
||||
-#define fail(fmt, ...) \
|
||||
-do { \
|
||||
- fprintf(stderr, "cxl-%s:%s:%d: " fmt, \
|
||||
- VERSION, __func__, __LINE__, ##__VA_ARGS__); \
|
||||
-} while (0)
|
||||
+static struct log_ctx ml;
|
||||
|
||||
#define BASE_OPTIONS() \
|
||||
OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug")
|
||||
@@ -79,7 +75,7 @@ static int action_zero(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
size = cxl_memdev_get_label_size(memdev);
|
||||
|
||||
if (cxl_memdev_nvdimm_bridge_active(memdev)) {
|
||||
- fprintf(stderr,
|
||||
+ log_err(&ml,
|
||||
"%s: has active nvdimm bridge, abort label write\n",
|
||||
cxl_memdev_get_devname(memdev));
|
||||
return -EBUSY;
|
||||
@@ -87,7 +83,7 @@ static int action_zero(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
|
||||
rc = cxl_memdev_zero_label(memdev, size, param.offset);
|
||||
if (rc < 0)
|
||||
- fprintf(stderr, "%s: label zeroing failed: %s\n",
|
||||
+ log_err(&ml, "%s: label zeroing failed: %s\n",
|
||||
cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
|
||||
return rc;
|
||||
@@ -100,7 +96,7 @@ static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
int rc;
|
||||
|
||||
if (cxl_memdev_nvdimm_bridge_active(memdev)) {
|
||||
- fprintf(stderr,
|
||||
+ log_err(&ml,
|
||||
"%s: has active nvdimm bridge, abort label write\n",
|
||||
cxl_memdev_get_devname(memdev));
|
||||
return -EBUSY;
|
||||
@@ -114,7 +110,7 @@ static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
fseek(actx->f_in, 0L, SEEK_SET);
|
||||
|
||||
if (size > label_size) {
|
||||
- fprintf(stderr,
|
||||
+ log_err(&ml,
|
||||
"File size (%zu) greater than label area size (%zu), aborting\n",
|
||||
size, label_size);
|
||||
return -EINVAL;
|
||||
@@ -133,7 +129,7 @@ static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
|
||||
rc = cxl_memdev_write_label(memdev, buf, size, param.offset);
|
||||
if (rc < 0)
|
||||
- fprintf(stderr, "%s: label write failed: %s\n",
|
||||
+ log_err(&ml, "%s: label write failed: %s\n",
|
||||
cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
|
||||
out:
|
||||
@@ -158,7 +154,7 @@ static int action_read(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
|
||||
rc = cxl_memdev_read_label(memdev, buf, size, param.offset);
|
||||
if (rc < 0) {
|
||||
- fprintf(stderr, "%s: label read failed: %s\n",
|
||||
+ log_err(&ml, "%s: label read failed: %s\n",
|
||||
cxl_memdev_get_devname(memdev), strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
@@ -188,6 +184,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
};
|
||||
unsigned long id;
|
||||
|
||||
+ log_init(&ml, "cxl memdev", "CXL_MEMDEV_LOG");
|
||||
argc = parse_options(argc, argv, options, u, 0);
|
||||
|
||||
if (argc == 0)
|
||||
@@ -200,8 +197,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
}
|
||||
|
||||
if (sscanf(argv[i], "mem%lu", &id) != 1) {
|
||||
- fprintf(stderr, "'%s' is not a valid memdev name\n",
|
||||
- argv[i]);
|
||||
+ log_err(&ml, "'%s' is not a valid memdev name\n",
|
||||
+ argv[i]);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
@@ -216,8 +213,8 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
else {
|
||||
actx.f_out = fopen(param.outfile, "w+");
|
||||
if (!actx.f_out) {
|
||||
- fprintf(stderr, "failed to open: %s: (%s)\n",
|
||||
- param.outfile, strerror(errno));
|
||||
+ log_err(&ml, "failed to open: %s: (%s)\n",
|
||||
+ param.outfile, strerror(errno));
|
||||
rc = -errno;
|
||||
goto out;
|
||||
}
|
||||
@@ -228,15 +225,18 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
} else {
|
||||
actx.f_in = fopen(param.infile, "r");
|
||||
if (!actx.f_in) {
|
||||
- fprintf(stderr, "failed to open: %s: (%s)\n",
|
||||
- param.infile, strerror(errno));
|
||||
+ log_err(&ml, "failed to open: %s: (%s)\n", param.infile,
|
||||
+ strerror(errno));
|
||||
rc = -errno;
|
||||
goto out_close_fout;
|
||||
}
|
||||
}
|
||||
|
||||
- if (param.verbose)
|
||||
+ if (param.verbose) {
|
||||
cxl_set_log_priority(ctx, LOG_DEBUG);
|
||||
+ ml.log_priority = LOG_DEBUG;
|
||||
+ } else
|
||||
+ ml.log_priority = LOG_INFO;
|
||||
|
||||
rc = 0;
|
||||
err = 0;
|
||||
@@ -299,8 +299,8 @@ int cmd_write_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
int count = memdev_action(argc, argv, ctx, action_write, write_options,
|
||||
"cxl write-labels <memdev> [-i <filename>]");
|
||||
|
||||
- fprintf(stderr, "wrote %d mem%s\n", count >= 0 ? count : 0,
|
||||
- count > 1 ? "s" : "");
|
||||
+ log_info(&ml, "wrote %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -309,8 +309,8 @@ int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
int count = memdev_action(argc, argv, ctx, action_read, read_options,
|
||||
"cxl read-labels <mem0> [<mem1>..<memN>] [-o <filename>]");
|
||||
|
||||
- fprintf(stderr, "read %d mem%s\n", count >= 0 ? count : 0,
|
||||
- count > 1 ? "s" : "");
|
||||
+ log_info(&ml, "read %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
int count = memdev_action(argc, argv, ctx, action_zero, zero_options,
|
||||
"cxl zero-labels <mem0> [<mem1>..<memN>] [<options>]");
|
||||
|
||||
- fprintf(stderr, "zeroed %d mem%s\n", count >= 0 ? count : 0,
|
||||
- count > 1 ? "s" : "");
|
||||
+ log_info(&ml, "zeroed %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
64
SOURCES/0111-cxl-memdev-Cleanup-memdev-filter.patch
Normal file
64
SOURCES/0111-cxl-memdev-Cleanup-memdev-filter.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From 6cab8e0186e73af75f0a15ce87c4db20ef0089df Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:54:01 -0800
|
||||
Subject: [PATCH 111/217] cxl/memdev: Cleanup memdev filter
|
||||
|
||||
util_cxl_memdev_filter() already handles the difference between 'mem%d',
|
||||
'%d', and 'all' for the identifier format. Drop the duplicate / incomplete
|
||||
format checking.
|
||||
|
||||
If the checking for bad formats was dropped too then this command could
|
||||
support "0,1,2" syntax in addition to "0 1 2" like 'cxl list'. However, it is
|
||||
not clear that's worthwhile since 'list' is ok to be imprecise, but memdev
|
||||
commands need to be stricter.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298564100.3021641.9410483964085163708.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
cxl/memdev.c | 18 +++++++-----------
|
||||
1 file changed, 7 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/cxl/memdev.c b/cxl/memdev.c
|
||||
index 327c260..4cca8b8 100644
|
||||
--- a/cxl/memdev.c
|
||||
+++ b/cxl/memdev.c
|
||||
@@ -191,16 +191,16 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
usage_with_options(u, options);
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "all") == 0) {
|
||||
- argv[0] = "all";
|
||||
argc = 1;
|
||||
break;
|
||||
}
|
||||
+ if (sscanf(argv[i], "mem%lu", &id) == 1)
|
||||
+ continue;
|
||||
+ if (sscanf(argv[i], "%lu", &id) == 1)
|
||||
+ continue;
|
||||
|
||||
- if (sscanf(argv[i], "mem%lu", &id) != 1) {
|
||||
- log_err(&ml, "'%s' is not a valid memdev name\n",
|
||||
- argv[i]);
|
||||
- err++;
|
||||
- }
|
||||
+ log_err(&ml, "'%s' is not a valid memdev name\n", argv[i]);
|
||||
+ err++;
|
||||
}
|
||||
|
||||
if (err == argc) {
|
||||
@@ -243,11 +243,7 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
count = 0;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
- if (sscanf(argv[i], "mem%lu", &id) != 1
|
||||
- && strcmp(argv[i], "all") != 0)
|
||||
- continue;
|
||||
-
|
||||
- cxl_memdev_foreach (ctx, memdev) {
|
||||
+ cxl_memdev_foreach(ctx, memdev) {
|
||||
if (!util_cxl_memdev_filter(memdev, argv[i], NULL))
|
||||
continue;
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,133 @@
|
||||
From c09c507e5a608718ac96af088fdc8cb441b09d0b Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:54:06 -0800
|
||||
Subject: [PATCH 112/217] cxl/memdev: Add serial support for memdev-related
|
||||
commands
|
||||
|
||||
Allow for a "-s, --serial" option to turn the argument list into serial
|
||||
identifiers.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298564631.3021641.5552442288217413180.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/memdev-option.txt | 5 ++++
|
||||
Documentation/cxl/meson.build | 4 ++-
|
||||
cxl/memdev.c | 45 +++++++++++++++++++++--------
|
||||
3 files changed, 41 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/Documentation/cxl/memdev-option.txt b/Documentation/cxl/memdev-option.txt
|
||||
index e778582..64348be 100644
|
||||
--- a/Documentation/cxl/memdev-option.txt
|
||||
+++ b/Documentation/cxl/memdev-option.txt
|
||||
@@ -2,3 +2,8 @@
|
||||
A 'memX' device name, or a memdev id number. Restrict the operation to
|
||||
the specified memdev(s). The keyword 'all' can be specified to indicate
|
||||
the lack of any restriction.
|
||||
+
|
||||
+-S::
|
||||
+--serial::
|
||||
+ Rather an a memdev id number, interpret the <memdev> argument(s)
|
||||
+ as a list of serial numbers.
|
||||
diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build
|
||||
index 64ce13f..0a6346b 100644
|
||||
--- a/Documentation/cxl/meson.build
|
||||
+++ b/Documentation/cxl/meson.build
|
||||
@@ -19,7 +19,9 @@ else
|
||||
endif
|
||||
|
||||
filedeps = [
|
||||
- '../copyright.txt',
|
||||
+ '../copyright.txt',
|
||||
+ 'memdev-option.txt',
|
||||
+ 'labels-options.txt',
|
||||
]
|
||||
|
||||
cxl_manpages = [
|
||||
diff --git a/cxl/memdev.c b/cxl/memdev.c
|
||||
index 4cca8b8..ef5343a 100644
|
||||
--- a/cxl/memdev.c
|
||||
+++ b/cxl/memdev.c
|
||||
@@ -24,12 +24,14 @@ static struct parameters {
|
||||
unsigned len;
|
||||
unsigned offset;
|
||||
bool verbose;
|
||||
+ bool serial;
|
||||
} param;
|
||||
|
||||
static struct log_ctx ml;
|
||||
|
||||
#define BASE_OPTIONS() \
|
||||
-OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug")
|
||||
+OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug"), \
|
||||
+OPT_BOOLEAN('S', "serial", ¶m.serial, "user serials numbers to id memdevs")
|
||||
|
||||
#define READ_OPTIONS() \
|
||||
OPT_STRING('o', "output", ¶m.outfile, "output-file", \
|
||||
@@ -172,8 +174,9 @@ out:
|
||||
}
|
||||
|
||||
static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
- int (*action)(struct cxl_memdev *memdev, struct action_context *actx),
|
||||
- const struct option *options, const char *usage)
|
||||
+ int (*action)(struct cxl_memdev *memdev,
|
||||
+ struct action_context *actx),
|
||||
+ const struct option *options, const char *usage)
|
||||
{
|
||||
struct cxl_memdev *memdev, *single = NULL;
|
||||
struct action_context actx = { 0 };
|
||||
@@ -190,16 +193,25 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
if (argc == 0)
|
||||
usage_with_options(u, options);
|
||||
for (i = 0; i < argc; i++) {
|
||||
- if (strcmp(argv[i], "all") == 0) {
|
||||
- argc = 1;
|
||||
- break;
|
||||
+ if (param.serial) {
|
||||
+ char *end;
|
||||
+
|
||||
+ strtoull(argv[i], &end, 0);
|
||||
+ if (end[0] == 0)
|
||||
+ continue;
|
||||
+ } else {
|
||||
+ if (strcmp(argv[i], "all") == 0) {
|
||||
+ argc = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (sscanf(argv[i], "mem%lu", &id) == 1)
|
||||
+ continue;
|
||||
+ if (sscanf(argv[i], "%lu", &id) == 1)
|
||||
+ continue;
|
||||
}
|
||||
- if (sscanf(argv[i], "mem%lu", &id) == 1)
|
||||
- continue;
|
||||
- if (sscanf(argv[i], "%lu", &id) == 1)
|
||||
- continue;
|
||||
|
||||
- log_err(&ml, "'%s' is not a valid memdev name\n", argv[i]);
|
||||
+ log_err(&ml, "'%s' is not a valid memdev %s\n", argv[i],
|
||||
+ param.serial ? "serial number" : "name");
|
||||
err++;
|
||||
}
|
||||
|
||||
@@ -244,7 +256,16 @@ static int memdev_action(int argc, const char **argv, struct cxl_ctx *ctx,
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
cxl_memdev_foreach(ctx, memdev) {
|
||||
- if (!util_cxl_memdev_filter(memdev, argv[i], NULL))
|
||||
+ const char *memdev_filter = NULL;
|
||||
+ const char *serial_filter = NULL;
|
||||
+
|
||||
+ if (param.serial)
|
||||
+ serial_filter = argv[i];
|
||||
+ else
|
||||
+ memdev_filter = argv[i];
|
||||
+
|
||||
+ if (!util_cxl_memdev_filter(memdev, memdev_filter,
|
||||
+ serial_filter))
|
||||
continue;
|
||||
|
||||
if (action == action_write) {
|
||||
--
|
||||
2.27.0
|
||||
|
136
SOURCES/0113-cxl-list-Add-numa_node-to-memdev-listings.patch
Normal file
136
SOURCES/0113-cxl-list-Add-numa_node-to-memdev-listings.patch
Normal file
@ -0,0 +1,136 @@
|
||||
From ca582b2003a2335eafac382e71afdf0a6caaef18 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:54:11 -0800
|
||||
Subject: [PATCH 113/217] cxl/list: Add 'numa_node' to memdev listings
|
||||
|
||||
If the kernel exports a valid numa_node, >= 0, include it in memdev objects
|
||||
listings.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298565156.3021641.14097226245654611710.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/lib/libcxl.txt | 4 ++++
|
||||
cxl/json.c | 8 ++++++++
|
||||
cxl/lib/libcxl.c | 11 +++++++++++
|
||||
cxl/lib/libcxl.sym | 1 +
|
||||
cxl/lib/private.h | 1 +
|
||||
cxl/libcxl.h | 1 +
|
||||
6 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index b0253d7..de88d19 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -71,6 +71,7 @@ unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_get_numa_node(struct cxl_memdev *memdev);
|
||||
----
|
||||
|
||||
A memdev is given a kernel device name of the form "mem%d" where an id
|
||||
@@ -89,6 +90,9 @@ The 'pmem_size' and 'ram_size' attributes return the current
|
||||
provisioning of DPA (Device Physical Address / local capacity) in the
|
||||
device.
|
||||
|
||||
+cxl_memdev_get_numa_node() returns the affinitized CPU node number if
|
||||
+available or -1 otherwise.
|
||||
+
|
||||
=== MEMDEV: Commands
|
||||
----
|
||||
struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index b809332..51918d6 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -190,6 +190,7 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
const char *devname = cxl_memdev_get_devname(memdev);
|
||||
struct json_object *jdev, *jobj;
|
||||
unsigned long long serial;
|
||||
+ int numa_node;
|
||||
|
||||
jdev = json_object_new_object();
|
||||
if (!jdev)
|
||||
@@ -220,6 +221,13 @@ struct json_object *util_cxl_memdev_to_json(struct cxl_memdev *memdev,
|
||||
json_object_object_add(jdev, "serial", jobj);
|
||||
}
|
||||
|
||||
+ numa_node = cxl_memdev_get_numa_node(memdev);
|
||||
+ if (numa_node >= 0) {
|
||||
+ jobj = json_object_new_int(numa_node);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdev, "numa_node", jobj);
|
||||
+ }
|
||||
+
|
||||
jobj = json_object_new_string(cxl_memdev_get_host(memdev));
|
||||
if (jobj)
|
||||
json_object_object_add(jdev, "host", jobj);
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 0065f6b..14c7db8 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -348,6 +348,12 @@ static void *add_cxl_memdev(void *parent, int id, const char *cxlmem_base)
|
||||
else
|
||||
memdev->serial = strtoull(buf, NULL, 0);
|
||||
|
||||
+ sprintf(path, "%s/numa_node", cxlmem_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
+ memdev->numa_node = -1;
|
||||
+ else
|
||||
+ memdev->numa_node = strtol(buf, NULL, 0);
|
||||
+
|
||||
memdev->dev_path = strdup(cxlmem_base);
|
||||
if (!memdev->dev_path)
|
||||
goto err_read;
|
||||
@@ -445,6 +451,11 @@ CXL_EXPORT unsigned long long cxl_memdev_get_serial(struct cxl_memdev *memdev)
|
||||
return memdev->serial;
|
||||
}
|
||||
|
||||
+CXL_EXPORT int cxl_memdev_get_numa_node(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ return memdev->numa_node;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT const char *cxl_memdev_get_devname(struct cxl_memdev *memdev)
|
||||
{
|
||||
return devpath_to_devname(memdev->dev_path);
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index 29f3498..b13a2d6 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -77,6 +77,7 @@ local:
|
||||
LIBCXL_2 {
|
||||
global:
|
||||
cxl_memdev_get_serial;
|
||||
+ cxl_memdev_get_numa_node;
|
||||
cxl_memdev_get_host;
|
||||
cxl_bus_get_first;
|
||||
cxl_bus_get_next;
|
||||
diff --git a/cxl/lib/private.h b/cxl/lib/private.h
|
||||
index b097bdf..c00bb36 100644
|
||||
--- a/cxl/lib/private.h
|
||||
+++ b/cxl/lib/private.h
|
||||
@@ -20,6 +20,7 @@ struct cxl_pmem {
|
||||
struct cxl_endpoint;
|
||||
struct cxl_memdev {
|
||||
int id, major, minor;
|
||||
+ int numa_node;
|
||||
void *dev_buf;
|
||||
size_t buf_len;
|
||||
char *host;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index e7b675e..be656ed 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -37,6 +37,7 @@ struct cxl_memdev *cxl_memdev_get_first(struct cxl_ctx *ctx);
|
||||
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);
|
||||
+int cxl_memdev_get_numa_node(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_devname(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_host(struct cxl_memdev *memdev);
|
||||
struct cxl_bus *cxl_memdev_get_bus(struct cxl_memdev *memdev);
|
||||
--
|
||||
2.27.0
|
||||
|
329
SOURCES/0114-util-Implement-common-bind-unbind-helpers.patch
Normal file
329
SOURCES/0114-util-Implement-common-bind-unbind-helpers.patch
Normal file
@ -0,0 +1,329 @@
|
||||
From e31fc778998b4d02ffec68e61869aaeccfd99be8 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:54:17 -0800
|
||||
Subject: [PATCH 114/217] util: Implement common bind/unbind helpers
|
||||
|
||||
Refactor ndctl_{bind,unbind}() into util_{bind,unbind}() for libcxl to
|
||||
reuse.
|
||||
|
||||
daxctl can not join the party for now as it needs to play games with
|
||||
'new_id'.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298565707.3021641.7763459936156744907.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
ndctl/lib/libndctl.c | 103 +++++--------------------------------------
|
||||
util/sysfs.c | 76 +++++++++++++++++++++++++++++++
|
||||
util/sysfs.h | 8 ++++
|
||||
3 files changed, 96 insertions(+), 91 deletions(-)
|
||||
|
||||
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
|
||||
index 1374ad9..98d184b 100644
|
||||
--- a/ndctl/lib/libndctl.c
|
||||
+++ b/ndctl/lib/libndctl.c
|
||||
@@ -1665,10 +1665,6 @@ static enum ndctl_fwa_result fwa_result_to_result(const char *result)
|
||||
return NDCTL_FWA_RESULT_INVALID;
|
||||
}
|
||||
|
||||
-static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module,
|
||||
- const char *devname);
|
||||
-static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath);
|
||||
-
|
||||
static int populate_dimm_attributes(struct ndctl_dimm *dimm,
|
||||
const char *dimm_base,
|
||||
const char *bus_prefix)
|
||||
@@ -2305,7 +2301,7 @@ NDCTL_EXPORT int ndctl_dimm_disable(struct ndctl_dimm *dimm)
|
||||
if (!ndctl_dimm_is_enabled(dimm))
|
||||
return 0;
|
||||
|
||||
- ndctl_unbind(ctx, dimm->dimm_path);
|
||||
+ util_unbind(dimm->dimm_path, ctx);
|
||||
|
||||
if (ndctl_dimm_is_enabled(dimm)) {
|
||||
err(ctx, "%s: failed to disable\n", devname);
|
||||
@@ -2324,7 +2320,7 @@ NDCTL_EXPORT int ndctl_dimm_enable(struct ndctl_dimm *dimm)
|
||||
if (ndctl_dimm_is_enabled(dimm))
|
||||
return 0;
|
||||
|
||||
- ndctl_bind(ctx, dimm->module, devname);
|
||||
+ util_bind(devname, dimm->module, "nd", ctx);
|
||||
|
||||
if (!ndctl_dimm_is_enabled(dimm)) {
|
||||
err(ctx, "%s: failed to enable\n", devname);
|
||||
@@ -3573,7 +3569,7 @@ NDCTL_EXPORT int ndctl_region_enable(struct ndctl_region *region)
|
||||
if (ndctl_region_is_enabled(region))
|
||||
return 0;
|
||||
|
||||
- ndctl_bind(ctx, region->module, devname);
|
||||
+ util_bind(devname, region->module, "nd", ctx);
|
||||
|
||||
if (!ndctl_region_is_enabled(region)) {
|
||||
err(ctx, "%s: failed to enable\n", devname);
|
||||
@@ -3610,7 +3606,7 @@ static int ndctl_region_disable(struct ndctl_region *region, int cleanup)
|
||||
if (!ndctl_region_is_enabled(region))
|
||||
return 0;
|
||||
|
||||
- ndctl_unbind(ctx, region->region_path);
|
||||
+ util_unbind(region->region_path, ctx);
|
||||
|
||||
if (ndctl_region_is_enabled(region)) {
|
||||
err(ctx, "%s: failed to disable\n", devname);
|
||||
@@ -4373,81 +4369,6 @@ NDCTL_EXPORT struct badblock *ndctl_namespace_get_first_badblock(
|
||||
return badblocks_iter_first(&ndns->bb_iter, ctx, path);
|
||||
}
|
||||
|
||||
-static int ndctl_bind(struct ndctl_ctx *ctx, struct kmod_module *module,
|
||||
- const char *devname)
|
||||
-{
|
||||
- DIR *dir;
|
||||
- int rc = 0;
|
||||
- char path[200];
|
||||
- struct dirent *de;
|
||||
- const int len = sizeof(path);
|
||||
-
|
||||
- if (!devname) {
|
||||
- err(ctx, "missing devname\n");
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
- if (module) {
|
||||
- rc = kmod_module_probe_insert_module(module,
|
||||
- KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL,
|
||||
- NULL);
|
||||
- if (rc < 0) {
|
||||
- err(ctx, "%s: insert failure: %d\n", __func__, rc);
|
||||
- return rc;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (snprintf(path, len, "/sys/bus/nd/drivers") >= len) {
|
||||
- err(ctx, "%s: buffer too small!\n", devname);
|
||||
- return -ENXIO;
|
||||
- }
|
||||
-
|
||||
- dir = opendir(path);
|
||||
- if (!dir) {
|
||||
- err(ctx, "%s: opendir(\"%s\") failed\n", devname, path);
|
||||
- return -ENXIO;
|
||||
- }
|
||||
-
|
||||
- while ((de = readdir(dir)) != NULL) {
|
||||
- char *drv_path;
|
||||
-
|
||||
- if (de->d_ino == 0)
|
||||
- continue;
|
||||
- if (de->d_name[0] == '.')
|
||||
- continue;
|
||||
- if (asprintf(&drv_path, "%s/%s/bind", path, de->d_name) < 0) {
|
||||
- err(ctx, "%s: path allocation failure\n", devname);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- rc = sysfs_write_attr_quiet(ctx, drv_path, devname);
|
||||
- free(drv_path);
|
||||
- if (rc == 0)
|
||||
- break;
|
||||
- }
|
||||
- closedir(dir);
|
||||
-
|
||||
- if (rc) {
|
||||
- dbg(ctx, "%s: bind failed\n", devname);
|
||||
- return -ENXIO;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath)
|
||||
-{
|
||||
- const char *devname = devpath_to_devname(devpath);
|
||||
- char path[200];
|
||||
- const int len = sizeof(path);
|
||||
-
|
||||
- if (snprintf(path, len, "%s/driver/unbind", devpath) >= len) {
|
||||
- err(ctx, "%s: buffer too small!\n", devname);
|
||||
- return -ENXIO;
|
||||
- }
|
||||
-
|
||||
- return sysfs_write_attr(ctx, path, devname);
|
||||
-}
|
||||
-
|
||||
static void *add_btt(void *parent, int id, const char *btt_base);
|
||||
static void *add_pfn(void *parent, int id, const char *pfn_base);
|
||||
static void *add_dax(void *parent, int id, const char *dax_base);
|
||||
@@ -4533,7 +4454,7 @@ NDCTL_EXPORT int ndctl_namespace_enable(struct ndctl_namespace *ndns)
|
||||
if (ndctl_namespace_is_enabled(ndns))
|
||||
return 0;
|
||||
|
||||
- rc = ndctl_bind(ctx, ndns->module, devname);
|
||||
+ rc = util_bind(devname, ndns->module, "nd", ctx);
|
||||
|
||||
/*
|
||||
* Rescan now as successfully enabling a namespace device leads
|
||||
@@ -4581,7 +4502,7 @@ NDCTL_EXPORT int ndctl_namespace_disable(struct ndctl_namespace *ndns)
|
||||
if (!ndctl_namespace_is_enabled(ndns))
|
||||
return 0;
|
||||
|
||||
- ndctl_unbind(ctx, ndns->ndns_path);
|
||||
+ util_unbind(ndns->ndns_path, ctx);
|
||||
|
||||
if (ndctl_namespace_is_enabled(ndns)) {
|
||||
err(ctx, "%s: failed to disable\n", devname);
|
||||
@@ -5420,7 +5341,7 @@ NDCTL_EXPORT int ndctl_btt_enable(struct ndctl_btt *btt)
|
||||
if (ndctl_btt_is_enabled(btt))
|
||||
return 0;
|
||||
|
||||
- ndctl_bind(ctx, btt->module, devname);
|
||||
+ util_bind(devname, btt->module, "nd", ctx);
|
||||
|
||||
if (!ndctl_btt_is_enabled(btt)) {
|
||||
err(ctx, "%s: failed to enable\n", devname);
|
||||
@@ -5457,7 +5378,7 @@ NDCTL_EXPORT int ndctl_btt_delete(struct ndctl_btt *btt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- ndctl_unbind(ctx, btt->btt_path);
|
||||
+ util_unbind(btt->btt_path, ctx);
|
||||
|
||||
rc = ndctl_btt_set_namespace(btt, NULL);
|
||||
if (rc) {
|
||||
@@ -5908,7 +5829,7 @@ NDCTL_EXPORT int ndctl_pfn_enable(struct ndctl_pfn *pfn)
|
||||
if (ndctl_pfn_is_enabled(pfn))
|
||||
return 0;
|
||||
|
||||
- ndctl_bind(ctx, pfn->module, devname);
|
||||
+ util_bind(devname, pfn->module, "nd", ctx);
|
||||
|
||||
if (!ndctl_pfn_is_enabled(pfn)) {
|
||||
err(ctx, "%s: failed to enable\n", devname);
|
||||
@@ -5945,7 +5866,7 @@ NDCTL_EXPORT int ndctl_pfn_delete(struct ndctl_pfn *pfn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- ndctl_unbind(ctx, pfn->pfn_path);
|
||||
+ util_unbind(pfn->pfn_path, ctx);
|
||||
|
||||
rc = ndctl_pfn_set_namespace(pfn, NULL);
|
||||
if (rc) {
|
||||
@@ -6101,7 +6022,7 @@ NDCTL_EXPORT int ndctl_dax_enable(struct ndctl_dax *dax)
|
||||
if (ndctl_dax_is_enabled(dax))
|
||||
return 0;
|
||||
|
||||
- ndctl_bind(ctx, pfn->module, devname);
|
||||
+ util_bind(devname, pfn->module, "nd", ctx);
|
||||
|
||||
if (!ndctl_dax_is_enabled(dax)) {
|
||||
err(ctx, "%s: failed to enable\n", devname);
|
||||
@@ -6132,7 +6053,7 @@ NDCTL_EXPORT int ndctl_dax_delete(struct ndctl_dax *dax)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- ndctl_unbind(ctx, pfn->pfn_path);
|
||||
+ util_unbind(pfn->pfn_path, ctx);
|
||||
|
||||
rc = ndctl_dax_set_namespace(dax, NULL);
|
||||
if (rc) {
|
||||
diff --git a/util/sysfs.c b/util/sysfs.c
|
||||
index 23330cb..968683b 100644
|
||||
--- a/util/sysfs.c
|
||||
+++ b/util/sysfs.c
|
||||
@@ -145,3 +145,79 @@ struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx,
|
||||
|
||||
return mod;
|
||||
}
|
||||
+
|
||||
+int __util_bind(const char *devname, struct kmod_module *module,
|
||||
+ const char *bus, struct log_ctx *ctx)
|
||||
+{
|
||||
+ DIR *dir;
|
||||
+ int rc = 0;
|
||||
+ char path[200];
|
||||
+ struct dirent *de;
|
||||
+ const int len = sizeof(path);
|
||||
+
|
||||
+ if (!devname) {
|
||||
+ log_err(ctx, "missing devname\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (module) {
|
||||
+ rc = kmod_module_probe_insert_module(module,
|
||||
+ KMOD_PROBE_APPLY_BLACKLIST,
|
||||
+ NULL, NULL, NULL, NULL);
|
||||
+ if (rc < 0) {
|
||||
+ log_err(ctx, "%s: insert failure: %d\n", __func__, rc);
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (snprintf(path, len, "/sys/bus/%s/drivers", bus) >= len) {
|
||||
+ log_err(ctx, "%s: buffer too small!\n", devname);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ dir = opendir(path);
|
||||
+ if (!dir) {
|
||||
+ log_err(ctx, "%s: opendir(\"%s\") failed\n", devname, path);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ while ((de = readdir(dir)) != NULL) {
|
||||
+ char *drv_path;
|
||||
+
|
||||
+ if (de->d_ino == 0)
|
||||
+ continue;
|
||||
+ if (de->d_name[0] == '.')
|
||||
+ continue;
|
||||
+
|
||||
+ if (asprintf(&drv_path, "%s/%s/bind", path, de->d_name) < 0) {
|
||||
+ log_err(ctx, "%s: path allocation failure\n", devname);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ rc = __sysfs_write_attr_quiet(ctx, drv_path, devname);
|
||||
+ free(drv_path);
|
||||
+ if (rc == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+ closedir(dir);
|
||||
+
|
||||
+ if (rc) {
|
||||
+ log_dbg(ctx, "%s: bind failed\n", devname);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int __util_unbind(const char *devpath, struct log_ctx *ctx)
|
||||
+{
|
||||
+ const char *devname = devpath_to_devname(devpath);
|
||||
+ char path[200];
|
||||
+ const int len = sizeof(path);
|
||||
+
|
||||
+ if (snprintf(path, len, "%s/driver/unbind", devpath) >= len) {
|
||||
+ log_err(ctx, "%s: buffer too small!\n", devname);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ return __sysfs_write_attr(ctx, path, devname);
|
||||
+}
|
||||
diff --git a/util/sysfs.h b/util/sysfs.h
|
||||
index bdee4f5..4c95c70 100644
|
||||
--- a/util/sysfs.h
|
||||
+++ b/util/sysfs.h
|
||||
@@ -35,4 +35,12 @@ struct kmod_module *__util_modalias_to_module(struct kmod_ctx *kmod_ctx,
|
||||
struct log_ctx *log);
|
||||
#define util_modalias_to_module(ctx, buf) \
|
||||
__util_modalias_to_module((ctx)->kmod_ctx, buf, &(ctx)->ctx)
|
||||
+
|
||||
+int __util_bind(const char *devname, struct kmod_module *module, const char *bus,
|
||||
+ struct log_ctx *ctx);
|
||||
+#define util_bind(n, m, b, c) __util_bind(n, m, b, &(c)->ctx)
|
||||
+
|
||||
+int __util_unbind(const char *devpath, struct log_ctx *ctx);
|
||||
+#define util_unbind(p, c) __util_unbind(p, &(c)->ctx)
|
||||
+
|
||||
#endif /* __UTIL_SYSFS_H__ */
|
||||
--
|
||||
2.27.0
|
||||
|
379
SOURCES/0115-cxl-memdev-Enable-disable-support.patch
Normal file
379
SOURCES/0115-cxl-memdev-Enable-disable-support.patch
Normal file
@ -0,0 +1,379 @@
|
||||
From 782694f9aeff6e146cfd00b31822995790546175 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:54:22 -0800
|
||||
Subject: [PATCH 115/217] cxl/memdev: Enable / disable support
|
||||
|
||||
Introduce the 'cxl {enable,disable}-memdev' commands. When a memdev is
|
||||
disabled the ports in the topology may be unregistered. CXL memory regions
|
||||
require each endpoint in the interleave to attach to the cxl_mem driver
|
||||
before regions are activated.
|
||||
|
||||
Note that this starts out with the deliberate bug that it has false
|
||||
positive detection of active memdevs. The fix for that bug requires kernel
|
||||
support to detect the device's active participation in a region, until then
|
||||
require all disable attempts to specify the --force override. This way
|
||||
there are never any releases of cxl-cli that lack disable-memdev safety.
|
||||
|
||||
Link: https://lore.kernel.org/r/164298566245.3021641.12696907310209056878.stgit@dwillia2-desk3.amr.corp.intel.com
|
||||
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
|
||||
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
|
||||
---
|
||||
Documentation/cxl/cxl-disable-memdev.txt | 37 +++++++++++++++
|
||||
Documentation/cxl/cxl-enable-memdev.txt | 34 ++++++++++++++
|
||||
Documentation/cxl/lib/libcxl.txt | 23 +++++++++
|
||||
Documentation/cxl/meson.build | 2 +
|
||||
cxl/builtin.h | 2 +
|
||||
cxl/cxl.c | 2 +
|
||||
cxl/lib/libcxl.c | 58 +++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 2 +
|
||||
cxl/libcxl.h | 2 +
|
||||
cxl/memdev.c | 60 +++++++++++++++++++++++-
|
||||
10 files changed, 221 insertions(+), 1 deletion(-)
|
||||
create mode 100644 Documentation/cxl/cxl-disable-memdev.txt
|
||||
create mode 100644 Documentation/cxl/cxl-enable-memdev.txt
|
||||
|
||||
diff --git a/Documentation/cxl/cxl-disable-memdev.txt b/Documentation/cxl/cxl-disable-memdev.txt
|
||||
new file mode 100644
|
||||
index 0000000..edd5385
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/cxl-disable-memdev.txt
|
||||
@@ -0,0 +1,37 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+cxl-disable-memdev(1)
|
||||
+=====================
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+cxl-disable-memdev - deactivate / hot-remove a given CXL memdev
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+'cxl disable-memdev' <mem0> [<mem1>..<memN>] [<options>]
|
||||
+
|
||||
+
|
||||
+OPTIONS
|
||||
+-------
|
||||
+<memory device(s)>::
|
||||
+include::memdev-option.txt[]
|
||||
+
|
||||
+-f::
|
||||
+--force::
|
||||
+ DANGEROUS: Override the safety measure that blocks attempts to disable
|
||||
+ a device if the tool determines the memdev is in active usage. Recall
|
||||
+ that CXL memory ranges might have been established by platform
|
||||
+ firmware and disabling an active device is akin to force removing
|
||||
+ memory from a running system.
|
||||
+
|
||||
+-v::
|
||||
+ Turn on verbose debug messages in the library (if libcxl was built with
|
||||
+ logging and debug enabled).
|
||||
+
|
||||
+include::../copyright.txt[]
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linkcxl:cxl-enable-memdev[1]
|
||||
diff --git a/Documentation/cxl/cxl-enable-memdev.txt b/Documentation/cxl/cxl-enable-memdev.txt
|
||||
new file mode 100644
|
||||
index 0000000..088d5e0
|
||||
--- /dev/null
|
||||
+++ b/Documentation/cxl/cxl-enable-memdev.txt
|
||||
@@ -0,0 +1,34 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+cxl-enable-memdev(1)
|
||||
+====================
|
||||
+
|
||||
+NAME
|
||||
+----
|
||||
+cxl-enable-memdev - activate / hot-add a given CXL memdev
|
||||
+
|
||||
+SYNOPSIS
|
||||
+--------
|
||||
+[verse]
|
||||
+'cxl enable-memdev' <mem0> [<mem1>..<memN>] [<options>]
|
||||
+
|
||||
+A memdev typically autoenables at initial device discovery. However, if
|
||||
+it was manually disabled this command can trigger the kernel to activate
|
||||
+it again. This involves detecting the state of the HDM (Host Managed
|
||||
+Device Memory) Decoders and validating that CXL.mem is enabled for each
|
||||
+port in the device's hierarchy.
|
||||
+
|
||||
+OPTIONS
|
||||
+-------
|
||||
+<memory device(s)>::
|
||||
+include::memdev-option.txt[]
|
||||
+
|
||||
+-v::
|
||||
+ Turn on verbose debug messages in the library (if libcxl was built with
|
||||
+ logging and debug enabled).
|
||||
+
|
||||
+include::../copyright.txt[]
|
||||
+
|
||||
+SEE ALSO
|
||||
+--------
|
||||
+linkcxl:cxl-disable-memdev[1]
|
||||
diff --git a/Documentation/cxl/lib/libcxl.txt b/Documentation/cxl/lib/libcxl.txt
|
||||
index de88d19..49edb71 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -93,6 +93,29 @@ device.
|
||||
cxl_memdev_get_numa_node() returns the affinitized CPU node number if
|
||||
available or -1 otherwise.
|
||||
|
||||
+=== MEMDEV: Control
|
||||
+----
|
||||
+int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_enable(struct cxl_memdev *memdev);
|
||||
+----
|
||||
+When a memory device is disabled it unregisters its associated endpoints
|
||||
+and potentially intervening switch ports if there are no other memdevs
|
||||
+pinning that port active. That means that any existing port objects that
|
||||
+the library has previously returned are in valid and need to be re-read.
|
||||
+Callers must be careful to re-retrieve port objects after
|
||||
+cxl_memdev_disable_invalidate(). Any usage of a previously obtained port
|
||||
+object after a cxl_memdev_disable_invalidate() call is a use-after-free
|
||||
+programming error. It follows that after cxl_memdev_enable() new ports
|
||||
+may appear in the topology that were not previously enumerable.
|
||||
+
|
||||
+NOTE: cxl_memdev_disable_invalidate() will force disable the memdev
|
||||
+regardless of whether the memory provided by the device is in active use
|
||||
+by the operating system. Callers take responisbility for assuring that
|
||||
+it is safe to disable the memory device. Otherwise, this call can be as
|
||||
+destructive as ripping a DIMM out of a running system. Like all other
|
||||
+libcxl calls that mutate the system state or divulge security sensitive
|
||||
+information this call requires root / CAP_SYS_ADMIN.
|
||||
+
|
||||
=== MEMDEV: Commands
|
||||
----
|
||||
struct cxl_cmd *cxl_cmd_new_raw(struct cxl_memdev *memdev, int opcode);
|
||||
diff --git a/Documentation/cxl/meson.build b/Documentation/cxl/meson.build
|
||||
index 0a6346b..7618c97 100644
|
||||
--- a/Documentation/cxl/meson.build
|
||||
+++ b/Documentation/cxl/meson.build
|
||||
@@ -30,6 +30,8 @@ cxl_manpages = [
|
||||
'cxl-read-labels.txt',
|
||||
'cxl-write-labels.txt',
|
||||
'cxl-zero-labels.txt',
|
||||
+ 'cxl-enable-memdev.txt',
|
||||
+ 'cxl-disable-memdev.txt',
|
||||
]
|
||||
|
||||
foreach man : cxl_manpages
|
||||
diff --git a/cxl/builtin.h b/cxl/builtin.h
|
||||
index 78eca6e..621c85c 100644
|
||||
--- a/cxl/builtin.h
|
||||
+++ b/cxl/builtin.h
|
||||
@@ -10,4 +10,6 @@ int cmd_read_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
+int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx);
|
||||
#endif /* _CXL_BUILTIN_H_ */
|
||||
diff --git a/cxl/cxl.c b/cxl/cxl.c
|
||||
index 4b1661d..78d2e9a 100644
|
||||
--- a/cxl/cxl.c
|
||||
+++ b/cxl/cxl.c
|
||||
@@ -64,6 +64,8 @@ static struct cmd_struct commands[] = {
|
||||
{ "zero-labels", .c_fn = cmd_zero_labels },
|
||||
{ "read-labels", .c_fn = cmd_read_labels },
|
||||
{ "write-labels", .c_fn = cmd_write_labels },
|
||||
+ { "disable-memdev", .c_fn = cmd_disable_memdev },
|
||||
+ { "enable-memdev", .c_fn = cmd_enable_memdev },
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv)
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 14c7db8..2fdaf71 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -500,6 +500,64 @@ CXL_EXPORT const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev
|
||||
return memdev->firmware_version;
|
||||
}
|
||||
|
||||
+CXL_EXPORT int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+ struct cxl_port *port, *_p, *bus_port;
|
||||
+ struct cxl_bus *bus;
|
||||
+
|
||||
+ if (!cxl_memdev_is_enabled(memdev))
|
||||
+ return 0;
|
||||
+
|
||||
+ bus = cxl_memdev_get_bus(memdev);
|
||||
+ if (!bus) {
|
||||
+ err(ctx, "%s: failed to invalidate\n", devname);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ util_unbind(memdev->dev_path, ctx);
|
||||
+
|
||||
+ if (cxl_memdev_is_enabled(memdev)) {
|
||||
+ err(ctx, "%s: failed to disable\n", devname);
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * The state of all ports is now indeterminate, delete them all
|
||||
+ * and start over.
|
||||
+ */
|
||||
+ bus_port = cxl_bus_get_port(bus);
|
||||
+ list_for_each_safe(&bus_port->child_ports, port, _p, list)
|
||||
+ free_port(port, &bus_port->child_ports);
|
||||
+ bus_port->ports_init = 0;
|
||||
+ memdev->endpoint = NULL;
|
||||
+
|
||||
+ dbg(ctx, "%s: disabled\n", devname);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_memdev_enable(struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+ const char *devname = cxl_memdev_get_devname(memdev);
|
||||
+
|
||||
+ if (cxl_memdev_is_enabled(memdev))
|
||||
+ return 0;
|
||||
+
|
||||
+ util_bind(devname, memdev->module, "cxl", ctx);
|
||||
+
|
||||
+ if (!cxl_memdev_is_enabled(memdev)) {
|
||||
+ err(ctx, "%s: failed to enable\n", devname);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ dbg(ctx, "%s: enabled\n", devname);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static struct cxl_endpoint *cxl_port_find_endpoint(struct cxl_port *parent_port,
|
||||
struct cxl_memdev *memdev)
|
||||
{
|
||||
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
|
||||
index b13a2d6..f235e99 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -115,4 +115,6 @@ global:
|
||||
cxl_memdev_get_endpoint;
|
||||
cxl_memdev_is_enabled;
|
||||
cxl_memdev_get_bus;
|
||||
+ cxl_memdev_disable_invalidate;
|
||||
+ cxl_memdev_enable;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index be656ed..53f68dd 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -48,6 +48,8 @@ unsigned long long cxl_memdev_get_pmem_size(struct cxl_memdev *memdev);
|
||||
unsigned long long cxl_memdev_get_ram_size(struct cxl_memdev *memdev);
|
||||
const char *cxl_memdev_get_firmware_verison(struct cxl_memdev *memdev);
|
||||
size_t cxl_memdev_get_label_size(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_disable_invalidate(struct cxl_memdev *memdev);
|
||||
+int cxl_memdev_enable(struct cxl_memdev *memdev);
|
||||
struct cxl_endpoint;
|
||||
struct cxl_endpoint *cxl_memdev_get_endpoint(struct cxl_memdev *memdev);
|
||||
int cxl_memdev_nvdimm_bridge_active(struct cxl_memdev *memdev);
|
||||
diff --git a/cxl/memdev.c b/cxl/memdev.c
|
||||
index ef5343a..90b33e1 100644
|
||||
--- a/cxl/memdev.c
|
||||
+++ b/cxl/memdev.c
|
||||
@@ -25,13 +25,14 @@ static struct parameters {
|
||||
unsigned offset;
|
||||
bool verbose;
|
||||
bool serial;
|
||||
+ bool force;
|
||||
} param;
|
||||
|
||||
static struct log_ctx ml;
|
||||
|
||||
#define BASE_OPTIONS() \
|
||||
OPT_BOOLEAN('v',"verbose", ¶m.verbose, "turn on debug"), \
|
||||
-OPT_BOOLEAN('S', "serial", ¶m.serial, "user serials numbers to id memdevs")
|
||||
+OPT_BOOLEAN('S', "serial", ¶m.serial, "use serial numbers to id memdevs")
|
||||
|
||||
#define READ_OPTIONS() \
|
||||
OPT_STRING('o', "output", ¶m.outfile, "output-file", \
|
||||
@@ -46,6 +47,10 @@ OPT_UINTEGER('s', "size", ¶m.len, "number of label bytes to operate"), \
|
||||
OPT_UINTEGER('O', "offset", ¶m.offset, \
|
||||
"offset into the label area to start operation")
|
||||
|
||||
+#define DISABLE_OPTIONS() \
|
||||
+OPT_BOOLEAN('f', "force", ¶m.force, \
|
||||
+ "DANGEROUS: override active memdev safety checks")
|
||||
+
|
||||
static const struct option read_options[] = {
|
||||
BASE_OPTIONS(),
|
||||
LABEL_OPTIONS(),
|
||||
@@ -66,6 +71,37 @@ static const struct option zero_options[] = {
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
+static const struct option disable_options[] = {
|
||||
+ BASE_OPTIONS(),
|
||||
+ DISABLE_OPTIONS(),
|
||||
+ OPT_END(),
|
||||
+};
|
||||
+
|
||||
+static const struct option enable_options[] = {
|
||||
+ BASE_OPTIONS(),
|
||||
+ OPT_END(),
|
||||
+};
|
||||
+
|
||||
+static int action_disable(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
+{
|
||||
+ if (!cxl_memdev_is_enabled(memdev))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!param.force) {
|
||||
+ /* TODO: actually detect rather than assume active */
|
||||
+ log_err(&ml, "%s is part of an active region\n",
|
||||
+ cxl_memdev_get_devname(memdev));
|
||||
+ return -EBUSY;
|
||||
+ }
|
||||
+
|
||||
+ return cxl_memdev_disable_invalidate(memdev);
|
||||
+}
|
||||
+
|
||||
+static int action_enable(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
+{
|
||||
+ return cxl_memdev_enable(memdev);
|
||||
+}
|
||||
+
|
||||
static int action_zero(struct cxl_memdev *memdev, struct action_context *actx)
|
||||
{
|
||||
size_t size;
|
||||
@@ -340,3 +376,25 @@ int cmd_zero_labels(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
count > 1 ? "s" : "");
|
||||
return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
}
|
||||
+
|
||||
+int cmd_disable_memdev(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ int count = memdev_action(
|
||||
+ argc, argv, ctx, action_disable, disable_options,
|
||||
+ "cxl disable-memdev <mem0> [<mem1>..<memN>] [<options>]");
|
||||
+
|
||||
+ log_info(&ml, "disabled %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
+ return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
+}
|
||||
+
|
||||
+int cmd_enable_memdev(int argc, const char **argv, struct cxl_ctx *ctx)
|
||||
+{
|
||||
+ int count = memdev_action(
|
||||
+ argc, argv, ctx, action_enable, enable_options,
|
||||
+ "cxl enable-memdev <mem0> [<mem1>..<memN>] [<options>]");
|
||||
+
|
||||
+ log_info(&ml, "enabled %d mem%s\n", count >= 0 ? count : 0,
|
||||
+ count > 1 ? "s" : "");
|
||||
+ return count >= 0 ? 0 : EXIT_FAILURE;
|
||||
+}
|
||||
--
|
||||
2.27.0
|
||||
|
1108
SOURCES/0116-cxl-list-Add-decoder-support.patch
Normal file
1108
SOURCES/0116-cxl-list-Add-decoder-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user