Backport changes up to v74, excluding the config file changes
This includes support for the CXL commands, and adds the following packages: cxl-cli, cxl-devel, cxl-libs. Resolves: rhbz#2132167
This commit is contained in:
parent
bc084de093
commit
2c91dc1bcd
51
0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch
Normal file
51
0003-ndctl-test-Fix-btt-expect-table-compile-warning.patch
Normal file
@ -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
0004-ndctl-test-Cleanup-unnecessary-out-label.patch
Normal file
57
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
0005-ndctl-test-Fix-device-dax-mremap-test.patch
Normal file
40
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
|
||||
|
134
0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch
Normal file
134
0006-ndctl-test-Exercise-soft_offline_page-corner-cases.patch
Normal file
@ -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
|
||||
|
140
0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch
Normal file
140
0008-ndctl-namespace-Fix-disable-namespace-accounting-rel.patch
Normal file
@ -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
0009-zero_info_block-skip-seed-devices.patch
Normal file
50
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
0010-ndctl-update-.gitignore.patch
Normal file
51
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
|
||||
|
127
0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch
Normal file
127
0011-ndctl-test-add-checking-the-presence-of-jq-command-a.patch
Normal file
@ -0,0 +1,127 @@
|
||||
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
|
||||
|
||||
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
|
||||
---
|
||||
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
|
||||
--- a/test/daxdev-errors.sh
|
||||
+++ b/test/daxdev-errors.sh
|
||||
@@ -9,6 +9,7 @@ rc=77
|
||||
. $(dirname $0)/common
|
||||
|
||||
check_min_kver "4.12" || do_skip "lacks dax dev error handling"
|
||||
+check_prereq "jq"
|
||||
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
diff --git a/test/inject-error.sh b/test/inject-error.sh
|
||||
index c636033..7d0b826 100755
|
||||
--- a/test/inject-error.sh
|
||||
+++ b/test/inject-error.sh
|
||||
@@ -11,6 +11,8 @@ err_count=8
|
||||
|
||||
. $(dirname $0)/common
|
||||
|
||||
+check_prereq "jq"
|
||||
+
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
# sample json:
|
||||
diff --git a/test/inject-smart.sh b/test/inject-smart.sh
|
||||
index 94705df..4ca83b8 100755
|
||||
--- a/test/inject-smart.sh
|
||||
+++ b/test/inject-smart.sh
|
||||
@@ -166,6 +166,7 @@ do_tests()
|
||||
}
|
||||
|
||||
check_min_kver "4.19" || do_skip "kernel $KVER may not support smart (un)injection"
|
||||
+check_prereq "jq"
|
||||
modprobe nfit_test
|
||||
rc=1
|
||||
|
||||
diff --git a/test/label-compat.sh b/test/label-compat.sh
|
||||
index 340b93d..8ab2858 100755
|
||||
--- a/test/label-compat.sh
|
||||
+++ b/test/label-compat.sh
|
||||
@@ -10,6 +10,7 @@ BASE=$(dirname $0)
|
||||
. $BASE/common
|
||||
|
||||
check_min_kver "4.11" || do_skip "may not provide reliable isetcookie values"
|
||||
+check_prereq "jq"
|
||||
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
diff --git a/test/max_available_extent_ns.sh b/test/max_available_extent_ns.sh
|
||||
index 14d741d..343f3c9 100755
|
||||
--- a/test/max_available_extent_ns.sh
|
||||
+++ b/test/max_available_extent_ns.sh
|
||||
@@ -9,6 +9,7 @@ rc=77
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
check_min_kver "4.19" || do_skip "kernel $KVER may not support max_available_size"
|
||||
+check_prereq "jq"
|
||||
|
||||
init()
|
||||
{
|
||||
diff --git a/test/monitor.sh b/test/monitor.sh
|
||||
index cdab5e1..28c5541 100755
|
||||
--- a/test/monitor.sh
|
||||
+++ b/test/monitor.sh
|
||||
@@ -13,6 +13,8 @@ smart_supported_bus=""
|
||||
|
||||
. $(dirname $0)/common
|
||||
|
||||
+check_prereq "jq"
|
||||
+
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
check_min_kver "4.15" || do_skip "kernel $KVER may not support monitor service"
|
||||
diff --git a/test/multi-dax.sh b/test/multi-dax.sh
|
||||
index e932569..8496619 100755
|
||||
--- a/test/multi-dax.sh
|
||||
+++ b/test/multi-dax.sh
|
||||
@@ -9,6 +9,7 @@ rc=77
|
||||
. $(dirname $0)/common
|
||||
|
||||
check_min_kver "4.13" || do_skip "may lack multi-dax support"
|
||||
+check_prereq "jq"
|
||||
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
diff --git a/test/sector-mode.sh b/test/sector-mode.sh
|
||||
index dd7013e..54fa806 100755
|
||||
--- a/test/sector-mode.sh
|
||||
+++ b/test/sector-mode.sh
|
||||
@@ -6,6 +6,8 @@ rc=77
|
||||
|
||||
. $(dirname $0)/common
|
||||
|
||||
+check_prereq "jq"
|
||||
+
|
||||
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
|
||||
|
221
0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch
Normal file
221
0014-daxctl-fail-reconfigure-device-based-on-kernel-onlin.patch
Normal file
@ -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
|
||||
|
113
0016-libndctl-check-for-active-system-ram-before-disablin.patch
Normal file
113
0016-libndctl-check-for-active-system-ram-before-disablin.patch
Normal file
@ -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
|
||||
|
49
0017-daxctl-emit-counts-of-total-and-online-memblocks.patch
Normal file
49
0017-daxctl-emit-counts-of-total-and-online-memblocks.patch
Normal file
@ -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
|
||||
|
211
0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch
Normal file
211
0019-test-Don-t-skip-tests-if-nfit-modules-are-missing.patch
Normal file
@ -0,0 +1,211 @@
|
||||
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
|
||||
|
||||
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>
|
||||
---
|
||||
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
|
||||
--- a/test.h
|
||||
+++ b/test.h
|
||||
@@ -20,7 +20,7 @@ void builtin_xaction_namespace_reset(void);
|
||||
|
||||
struct kmod_ctx;
|
||||
struct kmod_module;
|
||||
-int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
+int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
struct ndctl_ctx *nd_ctx, int log_level,
|
||||
struct ndctl_test *test);
|
||||
|
||||
diff --git a/test/ack-shutdown-count-set.c b/test/ack-shutdown-count-set.c
|
||||
index fb1d82b..c561ff3 100644
|
||||
--- a/test/ack-shutdown-count-set.c
|
||||
+++ b/test/ack-shutdown-count-set.c
|
||||
@@ -99,7 +99,7 @@ static int test_ack_shutdown_count_set(int loglevel, struct ndctl_test *test,
|
||||
int result = EXIT_FAILURE, err;
|
||||
|
||||
ndctl_set_log_priority(ctx, loglevel);
|
||||
- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
if (err < 0) {
|
||||
result = 77;
|
||||
ndctl_test_skip(test);
|
||||
diff --git a/test/blk_namespaces.c b/test/blk_namespaces.c
|
||||
index d7f00cb..f076e85 100644
|
||||
--- a/test/blk_namespaces.c
|
||||
+++ b/test/blk_namespaces.c
|
||||
@@ -228,7 +228,7 @@ int test_blk_namespaces(int log_level, struct ndctl_test *test,
|
||||
|
||||
if (!bus) {
|
||||
fprintf(stderr, "ACPI.NFIT unavailable falling back to nfit_test\n");
|
||||
- rc = nfit_test_init(&kmod_ctx, &mod, NULL, log_level, test);
|
||||
+ rc = ndctl_test_init(&kmod_ctx, &mod, NULL, log_level, test);
|
||||
ndctl_invalidate(ctx);
|
||||
bus = ndctl_bus_get_by_provider(ctx, "nfit_test.0");
|
||||
if (rc < 0 || !bus) {
|
||||
diff --git a/test/core.c b/test/core.c
|
||||
index cc7d8d9..2b03aa9 100644
|
||||
--- a/test/core.c
|
||||
+++ b/test/core.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <util/log.h>
|
||||
#include <util/sysfs.h>
|
||||
#include <ndctl/libndctl.h>
|
||||
+#include <ndctl/ndctl.h>
|
||||
#include <ccan/array_size/array_size.h>
|
||||
|
||||
#define KVER_STRLEN 20
|
||||
@@ -106,11 +107,11 @@ int ndctl_test_get_skipped(struct ndctl_test *test)
|
||||
return test->skip;
|
||||
}
|
||||
|
||||
-int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
+int ndctl_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
struct ndctl_ctx *nd_ctx, int log_level,
|
||||
struct ndctl_test *test)
|
||||
{
|
||||
- int rc;
|
||||
+ int rc, family = -1;
|
||||
unsigned int i;
|
||||
const char *name;
|
||||
struct ndctl_bus *bus;
|
||||
@@ -127,10 +128,28 @@ int nfit_test_init(struct kmod_ctx **ctx, struct kmod_module **mod,
|
||||
"nd_e820",
|
||||
"nd_pmem",
|
||||
};
|
||||
+ char *test_env;
|
||||
|
||||
log_init(&log_ctx, "test/init", "NDCTL_TEST");
|
||||
log_ctx.log_priority = log_level;
|
||||
|
||||
+ /*
|
||||
+ * The following two checks determine the platform family. For
|
||||
+ * Intel/platforms which support ACPI, check sysfs; for other platforms
|
||||
+ * determine from the environment variable NVDIMM_TEST_FAMILY
|
||||
+ */
|
||||
+ if (access("/sys/bus/acpi", F_OK) == 0)
|
||||
+ family = NVDIMM_FAMILY_INTEL;
|
||||
+
|
||||
+ test_env = getenv("NDCTL_TEST_FAMILY");
|
||||
+ if (test_env && strcmp(test_env, "PAPR") == 0)
|
||||
+ family = NVDIMM_FAMILY_PAPR;
|
||||
+
|
||||
+ if (family == -1) {
|
||||
+ log_err(&log_ctx, "Cannot determine NVDIMM family\n");
|
||||
+ return -ENOTSUP;
|
||||
+ }
|
||||
+
|
||||
*ctx = kmod_new(NULL, NULL);
|
||||
if (!*ctx)
|
||||
return -ENXIO;
|
||||
@@ -185,6 +204,11 @@ retry:
|
||||
|
||||
path = kmod_module_get_path(*mod);
|
||||
if (!path) {
|
||||
+ if (family != NVDIMM_FAMILY_INTEL &&
|
||||
+ (strcmp(name, "nfit") == 0 ||
|
||||
+ strcmp(name, "nd_e820") == 0))
|
||||
+ continue;
|
||||
+
|
||||
log_err(&log_ctx, "%s.ko: failed to get path\n", name);
|
||||
break;
|
||||
}
|
||||
diff --git a/test/dpa-alloc.c b/test/dpa-alloc.c
|
||||
index e922009..0b3bb7a 100644
|
||||
--- a/test/dpa-alloc.c
|
||||
+++ b/test/dpa-alloc.c
|
||||
@@ -289,7 +289,7 @@ int test_dpa_alloc(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx)
|
||||
return 77;
|
||||
|
||||
ndctl_set_log_priority(ctx, loglevel);
|
||||
- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
if (err < 0) {
|
||||
ndctl_test_skip(test);
|
||||
fprintf(stderr, "nfit_test unavailable skipping tests\n");
|
||||
diff --git a/test/dsm-fail.c b/test/dsm-fail.c
|
||||
index 9dfd8b0..0a6383d 100644
|
||||
--- a/test/dsm-fail.c
|
||||
+++ b/test/dsm-fail.c
|
||||
@@ -346,7 +346,7 @@ int test_dsm_fail(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx)
|
||||
int result = EXIT_FAILURE, err;
|
||||
|
||||
ndctl_set_log_priority(ctx, loglevel);
|
||||
- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
if (err < 0) {
|
||||
result = 77;
|
||||
ndctl_test_skip(test);
|
||||
diff --git a/test/libndctl.c b/test/libndctl.c
|
||||
index c42f785..d9b50f4 100644
|
||||
--- a/test/libndctl.c
|
||||
+++ b/test/libndctl.c
|
||||
@@ -2708,7 +2708,7 @@ int test_libndctl(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx)
|
||||
daxctl_set_log_priority(daxctl_ctx, loglevel);
|
||||
ndctl_set_private_data(ctx, test);
|
||||
|
||||
- err = nfit_test_init(&kmod_ctx, &mod, ctx, loglevel, test);
|
||||
+ err = ndctl_test_init(&kmod_ctx, &mod, ctx, loglevel, test);
|
||||
if (err < 0) {
|
||||
ndctl_test_skip(test);
|
||||
fprintf(stderr, "nfit_test unavailable skipping tests\n");
|
||||
diff --git a/test/multi-pmem.c b/test/multi-pmem.c
|
||||
index 3d10952..3ea08cc 100644
|
||||
--- a/test/multi-pmem.c
|
||||
+++ b/test/multi-pmem.c
|
||||
@@ -249,7 +249,7 @@ int test_multi_pmem(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ctx
|
||||
|
||||
ndctl_set_log_priority(ctx, loglevel);
|
||||
|
||||
- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
if (err < 0) {
|
||||
result = 77;
|
||||
ndctl_test_skip(test);
|
||||
diff --git a/test/parent-uuid.c b/test/parent-uuid.c
|
||||
index 6424e9f..bded33a 100644
|
||||
--- a/test/parent-uuid.c
|
||||
+++ b/test/parent-uuid.c
|
||||
@@ -218,7 +218,7 @@ int test_parent_uuid(int loglevel, struct ndctl_test *test, struct ndctl_ctx *ct
|
||||
return 77;
|
||||
|
||||
ndctl_set_log_priority(ctx, loglevel);
|
||||
- err = nfit_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
+ err = ndctl_test_init(&kmod_ctx, &mod, NULL, loglevel, test);
|
||||
if (err < 0) {
|
||||
ndctl_test_skip(test);
|
||||
fprintf(stderr, "nfit_test unavailable skipping tests\n");
|
||||
diff --git a/test/pmem_namespaces.c b/test/pmem_namespaces.c
|
||||
index f0f2edd..a4db1ae 100644
|
||||
--- a/test/pmem_namespaces.c
|
||||
+++ b/test/pmem_namespaces.c
|
||||
@@ -191,7 +191,7 @@ int test_pmem_namespaces(int log_level, struct ndctl_test *test,
|
||||
|
||||
if (!bus) {
|
||||
fprintf(stderr, "ACPI.NFIT unavailable falling back to nfit_test\n");
|
||||
- rc = nfit_test_init(&kmod_ctx, &mod, NULL, log_level, test);
|
||||
+ rc = ndctl_test_init(&kmod_ctx, &mod, NULL, log_level, test);
|
||||
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
|
||||
|
38
0022-libndctl-Remove-redundant-checks-and-assignments.patch
Normal file
38
0022-libndctl-Remove-redundant-checks-and-assignments.patch
Normal file
@ -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
0023-ndctl-Update-nvdimm-mailing-list-address.patch
Normal file
56
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
|
||||
|
122
0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch
Normal file
122
0024-libndctl-papr-Fix-probe-for-papr-scm-compatible-nvdi.patch
Normal file
@ -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
|
||||
|
38
0025-ndctl-scrub-Stop-translating-return-values.patch
Normal file
38
0025-ndctl-scrub-Stop-translating-return-values.patch
Normal file
@ -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
|
||||
|
48
0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch
Normal file
48
0026-ndctl-scrub-Reread-scrub-engine-status-at-start.patch
Normal file
@ -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
0027-ndctl-dimm-Fix-label-index-block-calculations.patch
Normal file
167
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.
|
||||
Reverts commit e01045e58ad5 ("ndctl/namespace: Fix destroy-namespace
|
||||
accounting relative to seed devices")
|
||||
|
||||
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>
|
||||
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
0031-ndctl-add-.clang-format.patch
Normal file
187
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
0032-cxl-add-a-cxl-utility-and-libcxl-library.patch
Normal file
1277
0032-cxl-add-a-cxl-utility-and-libcxl-library.patch
Normal file
File diff suppressed because it is too large
Load Diff
256
0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch
Normal file
256
0033-cxl-add-a-local-copy-of-the-cxl_mem-UAPI-header.patch
Normal file
@ -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
|
||||
|
114
0034-util-add-the-struct_size-helper-from-the-kernel.patch
Normal file
114
0034-util-add-the-struct_size-helper-from-the-kernel.patch
Normal file
@ -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
|
||||
|
535
0035-libcxl-add-support-for-command-query-and-submission.patch
Normal file
535
0035-libcxl-add-support-for-command-query-and-submission.patch
Normal file
@ -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
|
||||
|
157
0036-libcxl-add-support-for-the-Identify-Device-command.patch
Normal file
157
0036-libcxl-add-support-for-the-Identify-Device-command.patch
Normal file
@ -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
|
||||
|
575
0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch
Normal file
575
0037-libcxl-add-GET_HEALTH_INFO-mailbox-command-and-acces.patch
Normal file
@ -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
0038-libcxl-add-support-for-the-GET_LSA-command.patch
Normal file
113
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
|
||||
|
184
0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch
Normal file
184
0040-libcxl-add-representation-for-an-nvdimm-bridge-objec.patch
Normal file
@ -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
0041-libcxl-add-interfaces-for-label-operations.patch
Normal file
247
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
|
||||
|
583
0042-cxl-add-commands-to-read-write-and-zero-labels.patch
Normal file
583
0042-cxl-add-commands-to-read-write-and-zero-labels.patch
Normal file
@ -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
|
||||
|
248
0043-Documentation-cxl-add-library-API-documentation.patch
Normal file
248
0043-Documentation-cxl-add-library-API-documentation.patch
Normal file
@ -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
0044-ndctl-Add-CXL-packages-to-the-RPM-spec.patch
Normal file
147
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
0045-cxl-cli-add-bash-completion.patch
Normal file
139
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
0046-cxl-add-health-information-to-cxl-list.patch
Normal file
308
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
0047-ndctl-install-bash-completion-symlinks.patch
Normal file
75
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
0048-scripts-Add-a-man-page-template-generator.patch
Normal file
400
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
|
||||
|
167
0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch
Normal file
167
0049-daxctl-Add-Soft-Reservation-theory-of-operation.patch
Normal file
@ -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
0064-ndctl-release-v72.patch
Normal file
142
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
0067-ndctl-add-repology-graphic-to-README.md.patch
Normal file
32
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
|
||||
|
171
0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch
Normal file
171
0070-ndctl-test-Prepare-for-BLK-aperture-support-removal.patch
Normal file
@ -0,0 +1,171 @@
|
||||
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
|
||||
|
||||
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>
|
||||
---
|
||||
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
|
||||
--- a/test/core.c
|
||||
+++ b/test/core.c
|
||||
@@ -261,8 +261,8 @@ retry:
|
||||
ndctl_bus_foreach(nd_ctx, bus) {
|
||||
struct ndctl_region *region;
|
||||
|
||||
- if (strncmp(ndctl_bus_get_provider(bus),
|
||||
- "nfit_test", 9) != 0)
|
||||
+ if (strcmp(ndctl_bus_get_provider(bus),
|
||||
+ "nfit_test.0") != 0)
|
||||
continue;
|
||||
ndctl_region_foreach(bus, region)
|
||||
ndctl_region_disable_invalidate(region);
|
||||
@@ -280,5 +280,30 @@ retry:
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (rc)
|
||||
kmod_unref(*ctx);
|
||||
- return rc;
|
||||
+
|
||||
+ if (!nd_ctx)
|
||||
+ return rc;
|
||||
+
|
||||
+ ndctl_bus_foreach (nd_ctx, bus) {
|
||||
+ struct ndctl_region *region;
|
||||
+ struct ndctl_dimm *dimm;
|
||||
+
|
||||
+ if (strcmp(ndctl_bus_get_provider(bus), "nfit_test.0") != 0)
|
||||
+ continue;
|
||||
+
|
||||
+ ndctl_region_foreach (bus, region)
|
||||
+ ndctl_region_disable_invalidate(region);
|
||||
+
|
||||
+ ndctl_dimm_foreach (bus, dimm) {
|
||||
+ ndctl_dimm_read_label_index(dimm);
|
||||
+ ndctl_dimm_init_labels(dimm, NDCTL_NS_VERSION_1_2);
|
||||
+ ndctl_dimm_disable(dimm);
|
||||
+ ndctl_dimm_enable(dimm);
|
||||
+ }
|
||||
+
|
||||
+ ndctl_region_foreach (bus, region)
|
||||
+ ndctl_region_enable(region);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
diff --git a/test/libndctl.c b/test/libndctl.c
|
||||
index d9b50f4..c0e4b4c 100644
|
||||
--- a/test/libndctl.c
|
||||
+++ b/test/libndctl.c
|
||||
@@ -2587,17 +2587,41 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void reset_bus(struct ndctl_bus *bus)
|
||||
+enum dimm_reset {
|
||||
+ DIMM_INIT,
|
||||
+ DIMM_ZERO,
|
||||
+};
|
||||
+
|
||||
+static int reset_dimms(struct ndctl_bus *bus, enum dimm_reset reset)
|
||||
{
|
||||
- struct ndctl_region *region;
|
||||
struct ndctl_dimm *dimm;
|
||||
+ int rc = 0;
|
||||
+
|
||||
+ ndctl_dimm_foreach(bus, dimm) {
|
||||
+ if (reset == DIMM_ZERO)
|
||||
+ ndctl_dimm_zero_labels(dimm);
|
||||
+ else {
|
||||
+ ndctl_dimm_read_label_index(dimm);
|
||||
+ ndctl_dimm_init_labels(dimm, NDCTL_NS_VERSION_1_2);
|
||||
+ }
|
||||
+ ndctl_dimm_disable(dimm);
|
||||
+ rc = ndctl_dimm_enable(dimm);
|
||||
+ if (rc)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return rc;
|
||||
+}
|
||||
+
|
||||
+static void reset_bus(struct ndctl_bus *bus, enum dimm_reset reset)
|
||||
+{
|
||||
+ struct ndctl_region *region;
|
||||
|
||||
/* disable all regions so that set_config_data commands are permitted */
|
||||
ndctl_region_foreach(bus, region)
|
||||
ndctl_region_disable_invalidate(region);
|
||||
|
||||
- ndctl_dimm_foreach(bus, dimm)
|
||||
- ndctl_dimm_zero_labels(dimm);
|
||||
+ reset_dimms(bus, reset);
|
||||
|
||||
/* set regions back to their default state */
|
||||
ndctl_region_foreach(bus, region)
|
||||
@@ -2608,7 +2632,6 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
{
|
||||
struct ndctl_bus *bus = ndctl_bus_get_by_provider(ctx, NFIT_PROVIDER0);
|
||||
struct ndctl_region *region;
|
||||
- struct ndctl_dimm *dimm;
|
||||
int rc;
|
||||
|
||||
if (!bus)
|
||||
@@ -2625,13 +2648,10 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
- ndctl_dimm_foreach(bus, dimm) {
|
||||
- rc = ndctl_dimm_zero_labels(dimm);
|
||||
- if (rc < 0) {
|
||||
- fprintf(stderr, "failed to zero %s\n",
|
||||
- ndctl_dimm_get_devname(dimm));
|
||||
- return rc;
|
||||
- }
|
||||
+ rc = reset_dimms(bus, DIMM_INIT);
|
||||
+ if (rc < 0) {
|
||||
+ fprintf(stderr, "failed to reset dimms\n");
|
||||
+ return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2649,14 +2669,14 @@ static int do_test0(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
rc = check_regions(bus, regions0, ARRAY_SIZE(regions0), DAX);
|
||||
if (rc)
|
||||
return rc;
|
||||
- reset_bus(bus);
|
||||
+ reset_bus(bus, DIMM_INIT);
|
||||
}
|
||||
|
||||
if (ndctl_test_attempt(test, KERNEL_VERSION(4, 8, 0))) {
|
||||
rc = check_regions(bus, regions0, ARRAY_SIZE(regions0), PFN);
|
||||
if (rc)
|
||||
return rc;
|
||||
- reset_bus(bus);
|
||||
+ reset_bus(bus, DIMM_INIT);
|
||||
}
|
||||
|
||||
return check_regions(bus, regions0, ARRAY_SIZE(regions0), BTT);
|
||||
@@ -2671,6 +2691,7 @@ static int do_test1(struct ndctl_ctx *ctx, struct ndctl_test *test)
|
||||
return -ENXIO;
|
||||
|
||||
ndctl_bus_wait_probe(bus);
|
||||
+ reset_bus(bus, DIMM_ZERO);
|
||||
|
||||
/*
|
||||
* Starting with v4.10 the dimm on nfit_test.1 gets a unique
|
||||
--
|
||||
2.27.0
|
||||
|
428
0071-ndctl-test-Move-reset-to-function-in-common.patch
Normal file
428
0071-ndctl-test-Move-reset-to-function-in-common.patch
Normal file
@ -0,0 +1,428 @@
|
||||
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'
|
||||
|
||||
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>
|
||||
---
|
||||
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
|
||||
--- a/test/blk-exhaust.sh
|
||||
+++ b/test/blk-exhaust.sh
|
||||
@@ -14,9 +14,7 @@ trap 'err $LINENO' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
# if the kernel accounting is correct we should be able to create two
|
||||
# pmem and two blk namespaces on nfit_test.0
|
||||
diff --git a/test/btt-check.sh b/test/btt-check.sh
|
||||
index 8e0b489..65b5c58 100755
|
||||
--- a/test/btt-check.sh
|
||||
+++ b/test/btt-check.sh
|
||||
@@ -39,13 +39,6 @@ create()
|
||||
[ $size -gt 0 ] || err "$LINENO"
|
||||
}
|
||||
|
||||
-reset()
|
||||
-{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-}
|
||||
-
|
||||
# re-enable the BTT namespace, and do IO to it in an attempt to
|
||||
# verify it still comes up ok, and functions as expected
|
||||
post_repair_test()
|
||||
diff --git a/test/btt-errors.sh b/test/btt-errors.sh
|
||||
index 4e59f57..5a20d26 100755
|
||||
--- a/test/btt-errors.sh
|
||||
+++ b/test/btt-errors.sh
|
||||
@@ -45,9 +45,7 @@ trap 'err $LINENO cleanup' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
@@ -126,9 +124,7 @@ dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1
|
||||
|
||||
# reset everything to get a clean log
|
||||
if grep -q "$MNT" /proc/mounts; then umount $MNT; fi
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
dev="x"
|
||||
json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector)
|
||||
eval "$(echo "$json" | json2var)"
|
||||
@@ -148,9 +144,7 @@ force_raw 0
|
||||
dd if=/dev/$blockdev of=/dev/null iflag=direct bs=4096 count=1 && err $LINENO || true
|
||||
|
||||
# done, exit
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
cleanup
|
||||
_cleanup
|
||||
exit 0
|
||||
diff --git a/test/btt-pad-compat.sh b/test/btt-pad-compat.sh
|
||||
index bf1ea54..be538b7 100755
|
||||
--- a/test/btt-pad-compat.sh
|
||||
+++ b/test/btt-pad-compat.sh
|
||||
@@ -37,13 +37,6 @@ create()
|
||||
fi
|
||||
}
|
||||
|
||||
-reset()
|
||||
-{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-}
|
||||
-
|
||||
verify_idx()
|
||||
{
|
||||
idx0="$1"
|
||||
diff --git a/test/clear.sh b/test/clear.sh
|
||||
index fb9d52c..c4d02d5 100755
|
||||
--- a/test/clear.sh
|
||||
+++ b/test/clear.sh
|
||||
@@ -14,9 +14,7 @@ trap 'err $LINENO' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
diff --git a/test/common b/test/common
|
||||
index 6bcefca..3c54d63 100644
|
||||
--- a/test/common
|
||||
+++ b/test/common
|
||||
@@ -46,6 +46,21 @@ err()
|
||||
exit $rc
|
||||
}
|
||||
|
||||
+reset()
|
||||
+{
|
||||
+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
+ $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+}
|
||||
+
|
||||
+reset1()
|
||||
+{
|
||||
+ $NDCTL disable-region -b $NFIT_TEST_BUS1 all
|
||||
+ $NDCTL zero-labels -b $NFIT_TEST_BUS1 all
|
||||
+ $NDCTL enable-region -b $NFIT_TEST_BUS1 all
|
||||
+}
|
||||
+
|
||||
+
|
||||
# check_min_kver
|
||||
# $1: Supported kernel version. format: X.Y
|
||||
#
|
||||
diff --git a/test/create.sh b/test/create.sh
|
||||
index b0fd99f..e9baaa0 100755
|
||||
--- a/test/create.sh
|
||||
+++ b/test/create.sh
|
||||
@@ -15,9 +15,7 @@ trap 'err $LINENO' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
diff --git a/test/daxctl-create.sh b/test/daxctl-create.sh
|
||||
index 198779a..d319a39 100755
|
||||
--- a/test/daxctl-create.sh
|
||||
+++ b/test/daxctl-create.sh
|
||||
@@ -10,7 +10,7 @@ trap 'cleanup $LINENO' ERR
|
||||
cleanup()
|
||||
{
|
||||
printf "Error at line %d\n" "$1"
|
||||
- [[ $testdev ]] && reset
|
||||
+ [[ $testdev ]] && reset_dax
|
||||
exit $rc
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ reset_dev()
|
||||
"$DAXCTL" enable-device "$testdev"
|
||||
}
|
||||
|
||||
-reset()
|
||||
+reset_dax()
|
||||
{
|
||||
test -n "$testdev"
|
||||
|
||||
diff --git a/test/daxdev-errors.sh b/test/daxdev-errors.sh
|
||||
index 9547d78..e13453d 100755
|
||||
--- a/test/daxdev-errors.sh
|
||||
+++ b/test/daxdev-errors.sh
|
||||
@@ -15,9 +15,7 @@ trap 'err $LINENO' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
diff --git a/test/firmware-update.sh b/test/firmware-update.sh
|
||||
index 8cc9c41..93ce166 100755
|
||||
--- a/test/firmware-update.sh
|
||||
+++ b/test/firmware-update.sh
|
||||
@@ -10,11 +10,9 @@ image="update-fw.img"
|
||||
|
||||
trap 'err $LINENO' ERR
|
||||
|
||||
-reset()
|
||||
+fwupd_reset()
|
||||
{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+ reset
|
||||
if [ -f $image ]; then
|
||||
rm -f $image
|
||||
fi
|
||||
@@ -73,7 +71,7 @@ do_tests()
|
||||
check_min_kver "4.16" || do_skip "may lack firmware update test handling"
|
||||
|
||||
modprobe nfit_test
|
||||
-reset
|
||||
+fwupd_reset
|
||||
detect
|
||||
rc=1
|
||||
do_tests
|
||||
diff --git a/test/inject-error.sh b/test/inject-error.sh
|
||||
index 7d0b826..fd823b6 100755
|
||||
--- a/test/inject-error.sh
|
||||
+++ b/test/inject-error.sh
|
||||
@@ -37,13 +37,6 @@ create()
|
||||
[ $size -gt 0 ] || err "$LINENO"
|
||||
}
|
||||
|
||||
-reset()
|
||||
-{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-}
|
||||
-
|
||||
check_status()
|
||||
{
|
||||
local sector="$1"
|
||||
diff --git a/test/max_available_extent_ns.sh b/test/max_available_extent_ns.sh
|
||||
index 343f3c9..47a921f 100755
|
||||
--- a/test/max_available_extent_ns.sh
|
||||
+++ b/test/max_available_extent_ns.sh
|
||||
@@ -11,13 +11,6 @@ trap 'err $LINENO' ERR
|
||||
check_min_kver "4.19" || do_skip "kernel $KVER may not support max_available_size"
|
||||
check_prereq "jq"
|
||||
|
||||
-init()
|
||||
-{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-}
|
||||
-
|
||||
do_test()
|
||||
{
|
||||
region=$($NDCTL list -b $NFIT_TEST_BUS0 -R -t pmem | jq -r 'sort_by(-.size) | .[].dev' | head -1)
|
||||
@@ -40,7 +33,7 @@ do_test()
|
||||
|
||||
modprobe nfit_test
|
||||
rc=1
|
||||
-init
|
||||
+reset
|
||||
do_test
|
||||
_cleanup
|
||||
exit 0
|
||||
diff --git a/test/monitor.sh b/test/monitor.sh
|
||||
index c015c11..6aa4196 100755
|
||||
--- a/test/monitor.sh
|
||||
+++ b/test/monitor.sh
|
||||
@@ -19,13 +19,6 @@ trap 'err $LINENO' ERR
|
||||
|
||||
check_min_kver "4.15" || do_skip "kernel $KVER may not support monitor service"
|
||||
|
||||
-init()
|
||||
-{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-}
|
||||
-
|
||||
start_monitor()
|
||||
{
|
||||
logfile=$(mktemp)
|
||||
@@ -112,7 +105,7 @@ test_filter_region()
|
||||
|
||||
test_filter_namespace()
|
||||
{
|
||||
- init
|
||||
+ reset
|
||||
monitor_namespace=$($NDCTL create-namespace -b $smart_supported_bus | jq -r .dev)
|
||||
monitor_dimms=$(get_monitor_dimm "-n $monitor_namespace")
|
||||
start_monitor "-n $monitor_namespace"
|
||||
@@ -170,7 +163,7 @@ do_tests()
|
||||
|
||||
modprobe nfit_test
|
||||
rc=1
|
||||
-init
|
||||
+reset
|
||||
set_smart_supported_bus
|
||||
do_tests
|
||||
_cleanup
|
||||
diff --git a/test/multi-dax.sh b/test/multi-dax.sh
|
||||
index b343a38..04070ad 100755
|
||||
--- a/test/multi-dax.sh
|
||||
+++ b/test/multi-dax.sh
|
||||
@@ -17,9 +17,7 @@ ALIGN_SIZE=`getconf PAGESIZE`
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
rc=1
|
||||
|
||||
query=". | sort_by(.available_size) | reverse | .[0].dev"
|
||||
diff --git a/test/pfn-meta-errors.sh b/test/pfn-meta-errors.sh
|
||||
index 0ade2e5..6314897 100755
|
||||
--- a/test/pfn-meta-errors.sh
|
||||
+++ b/test/pfn-meta-errors.sh
|
||||
@@ -29,9 +29,7 @@ trap 'err $LINENO' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh
|
||||
index 4225c3b..2065780 100755
|
||||
--- a/test/pmem-errors.sh
|
||||
+++ b/test/pmem-errors.sh
|
||||
@@ -28,9 +28,7 @@ trap 'err $LINENO cleanup' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
diff --git a/test/rescan-partitions.sh b/test/rescan-partitions.sh
|
||||
index 1686de3..51bbd73 100755
|
||||
--- a/test/rescan-partitions.sh
|
||||
+++ b/test/rescan-partitions.sh
|
||||
@@ -25,13 +25,6 @@ check_min_kver "4.16" || do_skip "may not contain fixes for partition rescanning
|
||||
check_prereq "parted"
|
||||
check_prereq "blockdev"
|
||||
|
||||
-reset()
|
||||
-{
|
||||
- $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-}
|
||||
-
|
||||
test_mode()
|
||||
{
|
||||
local mode="$1"
|
||||
diff --git a/test/sector-mode.sh b/test/sector-mode.sh
|
||||
index 7a2faea..439ef33 100755
|
||||
--- a/test/sector-mode.sh
|
||||
+++ b/test/sector-mode.sh
|
||||
@@ -15,13 +15,8 @@ ALIGN_SIZE=`getconf PAGESIZE`
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
-
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS1 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS1 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS1 all
|
||||
+reset
|
||||
+reset1
|
||||
|
||||
rc=1
|
||||
query=". | sort_by(.size) | reverse | .[0].dev"
|
||||
diff --git a/test/track-uuid.sh b/test/track-uuid.sh
|
||||
index be3cf9c..3bacd2c 100755
|
||||
--- a/test/track-uuid.sh
|
||||
+++ b/test/track-uuid.sh
|
||||
@@ -12,9 +12,7 @@ trap 'err $LINENO' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+reset
|
||||
|
||||
rc=1
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
104
0072-ndctl-test-Initialize-the-label-area-by-default.patch
Normal file
104
0072-ndctl-test-Initialize-the-label-area-by-default.patch
Normal file
@ -0,0 +1,104 @@
|
||||
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
|
||||
|
||||
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>
|
||||
---
|
||||
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
|
||||
--- a/test/btt-errors.sh
|
||||
+++ b/test/btt-errors.sh
|
||||
@@ -45,7 +45,7 @@ trap 'err $LINENO cleanup' ERR
|
||||
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
-reset
|
||||
+resetV
|
||||
|
||||
rc=1
|
||||
|
||||
@@ -124,7 +124,7 @@ dd if=$MNT/$FILE of=/dev/null iflag=direct bs=4096 count=1
|
||||
|
||||
# reset everything to get a clean log
|
||||
if grep -q "$MNT" /proc/mounts; then umount $MNT; fi
|
||||
-reset
|
||||
+resetV
|
||||
dev="x"
|
||||
json=$($NDCTL create-namespace -b $NFIT_TEST_BUS0 -t pmem -m sector)
|
||||
eval "$(echo "$json" | json2var)"
|
||||
diff --git a/test/btt-pad-compat.sh b/test/btt-pad-compat.sh
|
||||
index be538b7..005316a 100755
|
||||
--- a/test/btt-pad-compat.sh
|
||||
+++ b/test/btt-pad-compat.sh
|
||||
@@ -148,7 +148,7 @@ do_tests()
|
||||
verify_idx 0 1
|
||||
|
||||
# do the same with an old format namespace
|
||||
- reset
|
||||
+ resetV
|
||||
create_oldfmt_ns
|
||||
verify_idx 0 2
|
||||
|
||||
diff --git a/test/common b/test/common
|
||||
index 3c54d63..b6d4712 100644
|
||||
--- a/test/common
|
||||
+++ b/test/common
|
||||
@@ -49,14 +49,21 @@ err()
|
||||
reset()
|
||||
{
|
||||
$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
+ $NDCTL init-labels -f -b $NFIT_TEST_BUS0 all
|
||||
+ $NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
+}
|
||||
+
|
||||
+resetV()
|
||||
+{
|
||||
+ $NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
+ $NDCTL init-labels -f -V 1.2 -b $NFIT_TEST_BUS0 all
|
||||
$NDCTL enable-region -b $NFIT_TEST_BUS0 all
|
||||
}
|
||||
|
||||
reset1()
|
||||
{
|
||||
$NDCTL disable-region -b $NFIT_TEST_BUS1 all
|
||||
- $NDCTL zero-labels -b $NFIT_TEST_BUS1 all
|
||||
+ $NDCTL init-labels -f -b $NFIT_TEST_BUS1 all
|
||||
$NDCTL enable-region -b $NFIT_TEST_BUS1 all
|
||||
}
|
||||
|
||||
diff --git a/test/label-compat.sh b/test/label-compat.sh
|
||||
index 8ab2858..7ae4d5e 100755
|
||||
--- a/test/label-compat.sh
|
||||
+++ b/test/label-compat.sh
|
||||
@@ -17,7 +17,7 @@ trap 'err $LINENO' ERR
|
||||
# setup (reset nfit_test dimms)
|
||||
modprobe nfit_test
|
||||
$NDCTL disable-region -b $NFIT_TEST_BUS0 all
|
||||
-$NDCTL zero-labels -b $NFIT_TEST_BUS0 all
|
||||
+$NDCTL init-labels -f -b $NFIT_TEST_BUS0 all
|
||||
|
||||
# grab the largest pmem region on -b $NFIT_TEST_BUS0
|
||||
query=". | sort_by(.available_size) | reverse | .[0].dev"
|
||||
--
|
||||
2.27.0
|
||||
|
43
0073-ndctl-test-Skip-BLK-flags-checks.patch
Normal file
43
0073-ndctl-test-Skip-BLK-flags-checks.patch
Normal file
@ -0,0 +1,43 @@
|
||||
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
|
||||
|
||||
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>
|
||||
---
|
||||
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
|
||||
--- a/test/libndctl.c
|
||||
+++ b/test/libndctl.c
|
||||
@@ -2535,7 +2535,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
|
||||
fprintf(stderr, "dimm%d expected formats: %d got: %d\n",
|
||||
i, dimms[i].formats,
|
||||
ndctl_dimm_get_formats(dimm));
|
||||
- return -ENXIO;
|
||||
+ fprintf(stderr, "continuing...\n");
|
||||
}
|
||||
for (j = 0; j < dimms[i].formats; j++) {
|
||||
if (ndctl_dimm_get_formatN(dimm, j) != dimms[i].format[j]) {
|
||||
@@ -2543,7 +2543,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
|
||||
"dimm%d expected format[%d]: %d got: %d\n",
|
||||
i, j, dimms[i].format[j],
|
||||
ndctl_dimm_get_formatN(dimm, j));
|
||||
- return -ENXIO;
|
||||
+ fprintf(stderr, "continuing...\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
41
0074-ndctl-test-Move-sector-mode-to-a-different-region.patch
Normal file
41
0074-ndctl-test-Move-sector-mode-to-a-different-region.patch
Normal file
@ -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
|
||||
|
1966
0075-ndctl-Deprecate-BLK-aperture-support.patch
Normal file
1966
0075-ndctl-Deprecate-BLK-aperture-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
5595
0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch
Normal file
5595
0077-util-Distribute-filter-and-json-helpers-to-per-tool-.patch
Normal file
File diff suppressed because it is too large
Load Diff
104
0078-Documentation-Drop-attrs.adoc-include.patch
Normal file
104
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)
|
||||
==========================
|
||||
|
53
0079-build-Drop-unnecessary-tool-config.h-includes.patch
Normal file
53
0079-build-Drop-unnecessary-tool-config.h-includes.patch
Normal file
@ -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
0080-test-Prepare-out-of-line-builds.patch
Normal file
355
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
0082-build-Add-meson-build-infrastructure.patch
Normal file
1577
0082-build-Add-meson-build-infrastructure.patch
Normal file
File diff suppressed because it is too large
Load Diff
223
0083-build-Add-meson-rpmbuild-support.patch
Normal file
223
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
0084-ndctl-Jettison-autotools.patch
Normal file
1423
0084-ndctl-Jettison-autotools.patch
Normal file
File diff suppressed because it is too large
Load Diff
32
0085-ndctl-build-Default-asciidoctor-to-enabled.patch
Normal file
32
0085-ndctl-build-Default-asciidoctor-to-enabled.patch
Normal file
@ -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
0086-ndctl-update-README.md-for-meson-build.patch
Normal file
88
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
0087-test-Add-suite-identifiers-to-tests.patch
Normal file
122
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
0088-ndctl-Rename-util_filter-to-ndctl_filter.patch
Normal file
287
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
0089-build-Add-tags.patch
Normal file
54
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
0090-json-Add-support-for-json_object_new_uint64.patch
Normal file
194
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__ */
|
32
0091-cxl-json-Cleanup-object-leak-false-positive.patch
Normal file
32
0091-cxl-json-Cleanup-object-leak-false-positive.patch
Normal file
@ -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
|
||||
|
118
0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch
Normal file
118
0092-cxl-list-Support-multiple-memdev-device-name-filter-.patch
Normal file
@ -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
0093-cxl-list-Support-comma-separated-lists.patch
Normal file
55
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
0094-cxl-list-Introduce-cxl_filter_walk.patch
Normal file
292
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
0095-cxl-list-Emit-device-serial-numbers.patch
Normal file
159
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
0096-cxl-list-Add-filter-by-serial-support.patch
Normal file
163
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
0097-cxl-lib-Rename-nvdimm-bridge-to-pmem.patch
Normal file
164
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
0098-cxl-list-Cleanup-options-definitions.patch
Normal file
61
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
|
||||
|
170
0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch
Normal file
170
0099-Documentation-Enhance-libcxl-memdev-API-documentatio.patch
Normal file
@ -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
0100-cxl-list-Add-bus-objects.patch
Normal file
739
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
|
||||
|
44
0101-util-json-Warn-on-stderr-about-empty-list-results.patch
Normal file
44
0101-util-json-Warn-on-stderr-about-empty-list-results.patch
Normal file
@ -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
|
||||
|
165
0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch
Normal file
165
0102-util-sysfs-Uplevel-modalias-lookup-helper-to-util.patch
Normal file
@ -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
0103-cxl-list-Add-port-enumeration.patch
Normal file
862
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
0104-cxl-list-Add-debug-option.patch
Normal file
103
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
0105-cxl-list-Add-endpoints.patch
Normal file
746
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
|
||||
|
154
0106-cxl-list-Add-host-entries-for-port-like-objects.patch
Normal file
154
0106-cxl-list-Add-host-entries-for-port-like-objects.patch
Normal file
@ -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
0107-cxl-list-Add-host-entries-for-memdevs.patch
Normal file
175
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
|
||||
|
499
0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch
Normal file
499
0108-cxl-list-Move-enabled-memdevs-underneath-their-endpo.patch
Normal file
@ -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
0109-cxl-list-Filter-memdev-by-ancestry.patch
Normal file
329
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
0110-cxl-memdev-Use-a-local-logger-for-debug.patch
Normal file
173
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
0111-cxl-memdev-Cleanup-memdev-filter.patch
Normal file
64
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
|
||||
|
133
0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch
Normal file
133
0112-cxl-memdev-Add-serial-support-for-memdev-related-com.patch
Normal file
@ -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
0113-cxl-list-Add-numa_node-to-memdev-listings.patch
Normal file
136
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
0114-util-Implement-common-bind-unbind-helpers.patch
Normal file
329
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
0115-cxl-memdev-Enable-disable-support.patch
Normal file
379
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
0116-cxl-list-Add-decoder-support.patch
Normal file
1108
0116-cxl-list-Add-decoder-support.patch
Normal file
File diff suppressed because it is too large
Load Diff
537
0117-cxl-list-Extend-decoder-objects-with-target-informat.patch
Normal file
537
0117-cxl-list-Extend-decoder-objects-with-target-informat.patch
Normal file
@ -0,0 +1,537 @@
|
||||
From 1279d1989ef77085d214a193c1458b624039c612 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Williams <dan.j.williams@intel.com>
|
||||
Date: Sun, 23 Jan 2022 16:54:34 -0800
|
||||
Subject: [PATCH 117/217] cxl/list: Extend decoder objects with target
|
||||
information
|
||||
|
||||
A target combines information about a dport along with its position in the
|
||||
intereleave order. With targets enumerated decoders can also be filtered be
|
||||
memory devices by seeing which decoders have a dport in the memory-device's
|
||||
ancestry.
|
||||
|
||||
$ cxl list -D -d 3.1 -T -u
|
||||
{
|
||||
"decoder":"decoder3.1",
|
||||
"resource":"0x8030000000",
|
||||
"size":"512.00 MiB (536.87 MB)",
|
||||
"volatile_capable":true,
|
||||
"nr_targets":2,
|
||||
"targets":[
|
||||
{
|
||||
"target":"cxl_host_bridge.1",
|
||||
"position":1,
|
||||
"id":"0x1"
|
||||
},
|
||||
{
|
||||
"target":"cxl_host_bridge.0",
|
||||
"position":0,
|
||||
"id":"0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Link: https://lore.kernel.org/r/164298567435.3021641.3771899644901785666.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 | 8 ++-
|
||||
Documentation/cxl/lib/libcxl.txt | 58 ++++++++++++++++
|
||||
cxl/filter.c | 25 +++++++
|
||||
cxl/filter.h | 1 +
|
||||
cxl/json.c | 46 +++++++++++++
|
||||
cxl/lib/libcxl.c | 115 +++++++++++++++++++++++++++++++
|
||||
cxl/lib/libcxl.sym | 10 +++
|
||||
cxl/libcxl.h | 19 +++++
|
||||
cxl/list.c | 2 +
|
||||
10 files changed, 283 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/.clang-format b/.clang-format
|
||||
index 16e28ac..47fb657 100644
|
||||
--- a/.clang-format
|
||||
+++ b/.clang-format
|
||||
@@ -81,6 +81,7 @@ ForEachMacros:
|
||||
- 'cxl_bus_foreach'
|
||||
- 'cxl_port_foreach'
|
||||
- 'cxl_decoder_foreach'
|
||||
+ - 'cxl_target_foreach'
|
||||
- 'cxl_endpoint_foreach'
|
||||
- 'daxctl_dev_foreach'
|
||||
- 'daxctl_mapping_foreach'
|
||||
diff --git a/Documentation/cxl/cxl-list.txt b/Documentation/cxl/cxl-list.txt
|
||||
index 84872b9..20ff2cb 100644
|
||||
--- a/Documentation/cxl/cxl-list.txt
|
||||
+++ b/Documentation/cxl/cxl-list.txt
|
||||
@@ -44,8 +44,8 @@ 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:
|
||||
+given memdev, buses, ports, endpoints, and decoders can be filtered by
|
||||
+one or more memdevs. For example:
|
||||
----
|
||||
# cxl list -P -p switch,endpoint -m mem0
|
||||
[
|
||||
@@ -270,6 +270,10 @@ OPTIONS
|
||||
"decoder<port_id>.<instance_id>". The possible decoder type names are
|
||||
"root", "switch", or "endpoint", similar to the port filter syntax.
|
||||
|
||||
+-T::
|
||||
+--targets::
|
||||
+ Extend decoder listings with downstream port target information.
|
||||
+
|
||||
--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 73af3d0..bd92fef 100644
|
||||
--- a/Documentation/cxl/lib/libcxl.txt
|
||||
+++ b/Documentation/cxl/lib/libcxl.txt
|
||||
@@ -300,6 +300,7 @@ device-local-physical-address).
|
||||
struct cxl_decoder *cxl_decoder_get_first(struct cxl_port *port);
|
||||
struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder);
|
||||
struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder);
|
||||
+struct cxl_decoder *cxl_target_get_decoder(struct cxl_target *target);
|
||||
|
||||
#define cxl_decoder_foreach(port, decoder) \
|
||||
for (decoder = cxl_decoder_get_first(port); decoder != NULL; \
|
||||
@@ -314,6 +315,7 @@ unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder);
|
||||
unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder);
|
||||
const char *cxl_decoder_get_devname(struct cxl_decoder *decoder);
|
||||
int cxl_decoder_get_id(struct cxl_decoder *decoder);
|
||||
+int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder);
|
||||
|
||||
enum cxl_decoder_target_type {
|
||||
CXL_DECODER_TTYPE_UNKNOWN,
|
||||
@@ -352,6 +354,62 @@ Platform firmware may setup the CXL decode hierarchy before the OS
|
||||
boots, and may additionally require that the OS not change the decode
|
||||
settings. This property is indicated by the cxl_decoder_is_locked() API.
|
||||
|
||||
+==== TARGETS
|
||||
+A root or switch level decoder takes an SPA (system-physical-address) as
|
||||
+input and routes it to a downstream port. Which downstream port depends
|
||||
+on the downstream port's position in the interleave. A 'struct
|
||||
+cxl_target' object represents the properties of a given downstream port
|
||||
+relative to its interleave configuration.
|
||||
+
|
||||
+===== TARGET: Enumeration
|
||||
+----
|
||||
+struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder,
|
||||
+ struct cxl_memdev *memdev);
|
||||
+struct cxl_target *
|
||||
+cxl_decoder_get_target_by_position(struct cxl_decoder *decoder, int position);
|
||||
+struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder);
|
||||
+struct cxl_target *cxl_target_get_next(struct cxl_target *target);
|
||||
+
|
||||
+#define cxl_target_foreach(decoder, target) \
|
||||
+ for (target = cxl_target_get_first(decoder); target != NULL; \
|
||||
+ target = cxl_target_get_next(target))
|
||||
+----
|
||||
+Target objects can only be enumerated if the decoder has been
|
||||
+configured, for switch decoders. For root decoders they are always
|
||||
+available since the root decoder target mapping is static. The
|
||||
+cxl_decoder_get_target_by_memdev() helper walks the topology to validate
|
||||
+if the given memory device is capable of receiving cycles from this
|
||||
+upstream decoder. It does not validate if the memory device is currently
|
||||
+configured to participate in that decode.
|
||||
+
|
||||
+===== TARGET: Attributes
|
||||
+----
|
||||
+int cxl_target_get_position(struct cxl_target *target);
|
||||
+unsigned long cxl_target_get_id(struct cxl_target *target);
|
||||
+const char *cxl_target_get_devname(struct cxl_target *target);
|
||||
+bool cxl_target_maps_memdev(struct cxl_target *target,
|
||||
+ struct cxl_memdev *memdev);
|
||||
+----
|
||||
+The position of a decoder along with the interleave granularity dictate
|
||||
+which address in the decoder's resource range map to which port.
|
||||
+
|
||||
+The target id is an identifier that the CXL port uses to reference this
|
||||
+downstream port. For CXL / PCIe downstream switch ports the id is
|
||||
+defined by the PCIe Link Capability Port Number field. For root decoders
|
||||
+the id is specified by platform firmware specific mechanism. For
|
||||
+ACPI.CXL defined root ports the id comes from the CEDT.CHBS / ACPI0016
|
||||
+_UID.
|
||||
+
|
||||
+The device name of a target is the name of the host device for the
|
||||
+downstream port. For CXL / PCIe downstream ports the devname is
|
||||
+downstream switch port PCI device. For CXL root ports the devname is a
|
||||
+platform firmware object for the host bridge like a ACPI0016 device
|
||||
+instance.
|
||||
+
|
||||
+The cxl_target_maps_memdev() helper is the companion of
|
||||
+cxl_decoder_get_target_by_memdev() to determine which downstream ports /
|
||||
+targets are capable of mapping which memdevs.
|
||||
+
|
||||
include::../../copyright.txt[]
|
||||
|
||||
SEE ALSO
|
||||
diff --git a/cxl/filter.c b/cxl/filter.c
|
||||
index dc052f6..05ede91 100644
|
||||
--- a/cxl/filter.c
|
||||
+++ b/cxl/filter.c
|
||||
@@ -421,6 +421,26 @@ static struct cxl_decoder *util_cxl_decoder_filter(struct cxl_decoder *decoder,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static struct cxl_decoder *
|
||||
+util_cxl_decoder_filter_by_memdev(struct cxl_decoder *decoder,
|
||||
+ const char *ident, const char *serial)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_decoder_get_ctx(decoder);
|
||||
+ struct cxl_memdev *memdev;
|
||||
+
|
||||
+ if (!ident && !serial)
|
||||
+ return decoder;
|
||||
+
|
||||
+ cxl_memdev_foreach(ctx, memdev) {
|
||||
+ if (!util_cxl_memdev_filter(memdev, ident, serial))
|
||||
+ continue;
|
||||
+ if (cxl_decoder_get_target_by_memdev(decoder, memdev))
|
||||
+ return decoder;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
static unsigned long params_to_flags(struct cxl_filter_params *param)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
@@ -431,6 +451,8 @@ static unsigned long params_to_flags(struct cxl_filter_params *param)
|
||||
flags |= UTIL_JSON_HUMAN;
|
||||
if (param->health)
|
||||
flags |= UTIL_JSON_HEALTH;
|
||||
+ if (param->targets)
|
||||
+ flags |= UTIL_JSON_TARGETS;
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -521,6 +543,9 @@ static void walk_decoders(struct cxl_port *port, struct cxl_filter_params *p,
|
||||
if (!util_cxl_decoder_filter_by_port(decoder, p->port_filter,
|
||||
pf_mode(p)))
|
||||
continue;
|
||||
+ if (!util_cxl_decoder_filter_by_memdev(
|
||||
+ decoder, p->memdev_filter, p->serial_filter))
|
||||
+ continue;
|
||||
if (!p->idle && cxl_decoder_get_size(decoder) == 0)
|
||||
continue;
|
||||
jdecoder = util_cxl_decoder_to_json(decoder, flags);
|
||||
diff --git a/cxl/filter.h b/cxl/filter.h
|
||||
index 5d7bf45..6fd469f 100644
|
||||
--- a/cxl/filter.h
|
||||
+++ b/cxl/filter.h
|
||||
@@ -16,6 +16,7 @@ struct cxl_filter_params {
|
||||
bool single;
|
||||
bool endpoints;
|
||||
bool decoders;
|
||||
+ bool targets;
|
||||
bool memdevs;
|
||||
bool ports;
|
||||
bool buses;
|
||||
diff --git a/cxl/json.c b/cxl/json.c
|
||||
index 548bc52..3a37909 100644
|
||||
--- a/cxl/json.c
|
||||
+++ b/cxl/json.c
|
||||
@@ -268,6 +268,8 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder,
|
||||
const char *devname = cxl_decoder_get_devname(decoder);
|
||||
struct cxl_port *port = cxl_decoder_get_port(decoder);
|
||||
struct json_object *jdecoder, *jobj;
|
||||
+ struct json_object *jtargets;
|
||||
+ struct cxl_target *target;
|
||||
u64 val;
|
||||
|
||||
jdecoder = json_object_new_object();
|
||||
@@ -321,7 +323,51 @@ struct json_object *util_cxl_decoder_to_json(struct cxl_decoder *decoder,
|
||||
jobj);
|
||||
}
|
||||
|
||||
+ /* Endpoints don't have targets, they *are* targets */
|
||||
+ if (cxl_port_is_endpoint(port))
|
||||
+ return jdecoder;
|
||||
+
|
||||
+ val = cxl_decoder_get_nr_targets(decoder);
|
||||
+ jobj = json_object_new_int(val);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jdecoder, "nr_targets", jobj);
|
||||
+
|
||||
+ if (!(flags & UTIL_JSON_TARGETS) ||
|
||||
+ !cxl_decoder_get_nr_targets(decoder))
|
||||
+ return jdecoder;
|
||||
+
|
||||
+ jtargets = json_object_new_array();
|
||||
+ if (!jtargets)
|
||||
+ return jdecoder;
|
||||
+
|
||||
+ cxl_target_foreach(decoder, target) {
|
||||
+ struct json_object *jtarget = json_object_new_object();
|
||||
+
|
||||
+ if (!jtarget)
|
||||
+ continue;
|
||||
+
|
||||
+ devname = cxl_target_get_devname(target);
|
||||
+ jobj = json_object_new_string(devname);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jtarget, "target", jobj);
|
||||
+
|
||||
+ val = cxl_target_get_position(target);
|
||||
+ jobj = json_object_new_int(val);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jtarget, "position", jobj);
|
||||
+
|
||||
+ val = cxl_target_get_id(target);
|
||||
+ jobj = util_json_object_hex(val, flags);
|
||||
+ if (jobj)
|
||||
+ json_object_object_add(jtarget, "id", jobj);
|
||||
+
|
||||
+ json_object_array_add(jtargets, jtarget);
|
||||
+ }
|
||||
+
|
||||
+ json_object_object_add(jdecoder, "targets", jtargets);
|
||||
+
|
||||
return jdecoder;
|
||||
+
|
||||
}
|
||||
|
||||
static struct json_object *__util_cxl_port_to_json(struct cxl_port *port,
|
||||
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
|
||||
index 5e30923..877f42c 100644
|
||||
--- a/cxl/lib/libcxl.c
|
||||
+++ b/cxl/lib/libcxl.c
|
||||
@@ -67,10 +67,22 @@ static void free_memdev(struct cxl_memdev *memdev, struct list_head *head)
|
||||
free(memdev);
|
||||
}
|
||||
|
||||
+static void free_target(struct cxl_target *target, struct list_head *head)
|
||||
+{
|
||||
+ if (head)
|
||||
+ list_del_from(head, &target->list);
|
||||
+ free(target->dev_path);
|
||||
+ free(target);
|
||||
+}
|
||||
+
|
||||
static void free_decoder(struct cxl_decoder *decoder, struct list_head *head)
|
||||
{
|
||||
+ struct cxl_target *target, *_t;
|
||||
+
|
||||
if (head)
|
||||
list_del_from(head, &decoder->list);
|
||||
+ list_for_each_safe(&decoder->targets, target, _t, list)
|
||||
+ free_target(target, &decoder->targets);
|
||||
free(decoder->dev_buf);
|
||||
free(decoder->dev_path);
|
||||
free(decoder);
|
||||
@@ -856,6 +868,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base)
|
||||
struct cxl_port *port = parent;
|
||||
struct cxl_ctx *ctx = cxl_port_get_ctx(port);
|
||||
char buf[SYSFS_ATTR_SIZE];
|
||||
+ char *target_id, *save;
|
||||
size_t i;
|
||||
|
||||
dbg(ctx, "%s: base: \'%s\'\n", devname, cxldecoder_base);
|
||||
@@ -870,6 +883,7 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base)
|
||||
decoder->id = id;
|
||||
decoder->ctx = ctx;
|
||||
decoder->port = port;
|
||||
+ list_head_init(&decoder->targets);
|
||||
|
||||
decoder->dev_path = strdup(cxldecoder_base);
|
||||
if (!decoder->dev_path)
|
||||
@@ -935,6 +949,36 @@ static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base)
|
||||
}
|
||||
}
|
||||
|
||||
+ sprintf(path, "%s/target_list", cxldecoder_base);
|
||||
+ if (sysfs_read_attr(ctx, path, buf) < 0)
|
||||
+ buf[0] = '\0';
|
||||
+
|
||||
+ for (i = 0, target_id = strtok_r(buf, ",", &save); target_id;
|
||||
+ target_id = strtok_r(NULL, ",", &save), i++) {
|
||||
+ int did = strtoul(target_id, NULL, 0);
|
||||
+ struct cxl_target *target = calloc(1, sizeof(*target));
|
||||
+
|
||||
+ if (!target)
|
||||
+ break;
|
||||
+
|
||||
+ target->id = did;
|
||||
+ target->position = i;
|
||||
+ target->decoder = decoder;
|
||||
+ sprintf(port->dev_buf, "%s/dport%d", port->dev_path, did);
|
||||
+ target->dev_path = realpath(port->dev_buf, NULL);
|
||||
+ if (!target->dev_path) {
|
||||
+ free(target);
|
||||
+ break;
|
||||
+ }
|
||||
+ dbg(ctx, "%s: target%ld %s\n", devname, i, target->dev_path);
|
||||
+ list_add(&decoder->targets, &target->list);
|
||||
+ }
|
||||
+
|
||||
+ if (target_id)
|
||||
+ err(ctx, "%s: failed to parse target%ld\n",
|
||||
+ devpath_to_devname(cxldecoder_base), i);
|
||||
+ decoder->nr_targets = i;
|
||||
+
|
||||
cxl_decoder_foreach(port, decoder_dup)
|
||||
if (decoder_dup->id == decoder->id) {
|
||||
free_decoder(decoder, NULL);
|
||||
@@ -1044,11 +1088,82 @@ CXL_EXPORT bool cxl_decoder_is_locked(struct cxl_decoder *decoder)
|
||||
return decoder->locked;
|
||||
}
|
||||
|
||||
+CXL_EXPORT int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder)
|
||||
+{
|
||||
+ return decoder->nr_targets;
|
||||
+}
|
||||
+
|
||||
CXL_EXPORT const char *cxl_decoder_get_devname(struct cxl_decoder *decoder)
|
||||
{
|
||||
return devpath_to_devname(decoder->dev_path);
|
||||
}
|
||||
|
||||
+CXL_EXPORT struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder)
|
||||
+{
|
||||
+ return list_top(&decoder->targets, struct cxl_target, list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_decoder *cxl_target_get_decoder(struct cxl_target *target)
|
||||
+{
|
||||
+ return target->decoder;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_target *cxl_target_get_next(struct cxl_target *target)
|
||||
+{
|
||||
+ struct cxl_decoder *decoder = cxl_target_get_decoder(target);
|
||||
+
|
||||
+ return list_next(&decoder->targets, target, list);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT const char *cxl_target_get_devname(struct cxl_target *target)
|
||||
+{
|
||||
+ return devpath_to_devname(target->dev_path);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT unsigned long cxl_target_get_id(struct cxl_target *target)
|
||||
+{
|
||||
+ return target->id;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT int cxl_target_get_position(struct cxl_target *target)
|
||||
+{
|
||||
+ return target->position;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT bool cxl_target_maps_memdev(struct cxl_target *target,
|
||||
+ struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_ctx *ctx = cxl_memdev_get_ctx(memdev);
|
||||
+
|
||||
+ dbg(ctx, "memdev: %s target: %s\n", memdev->host_path,
|
||||
+ target->dev_path);
|
||||
+
|
||||
+ return !!strstr(memdev->host_path, target->dev_path);
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_target *
|
||||
+cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder,
|
||||
+ struct cxl_memdev *memdev)
|
||||
+{
|
||||
+ struct cxl_target *target;
|
||||
+
|
||||
+ cxl_target_foreach(decoder, target)
|
||||
+ if (cxl_target_maps_memdev(target, memdev))
|
||||
+ return target;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+CXL_EXPORT struct cxl_target *
|
||||
+cxl_decoder_get_target_by_position(struct cxl_decoder *decoder, int position)
|
||||
+{
|
||||
+ struct cxl_target *target;
|
||||
+
|
||||
+ cxl_target_foreach(decoder, target)
|
||||
+ if (target->position == position)
|
||||
+ return target;
|
||||
+ 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 22babb7..cb33180 100644
|
||||
--- a/cxl/lib/libcxl.sym
|
||||
+++ b/cxl/lib/libcxl.sym
|
||||
@@ -125,10 +125,20 @@ global:
|
||||
cxl_decoder_get_resource;
|
||||
cxl_decoder_get_size;
|
||||
cxl_decoder_get_devname;
|
||||
+ cxl_decoder_get_target_by_memdev;
|
||||
+ cxl_decoder_get_target_by_position;
|
||||
+ cxl_decoder_get_nr_targets;
|
||||
cxl_decoder_get_target_type;
|
||||
cxl_decoder_is_pmem_capable;
|
||||
cxl_decoder_is_volatile_capable;
|
||||
cxl_decoder_is_mem_capable;
|
||||
cxl_decoder_is_accelmem_capable;
|
||||
cxl_decoder_is_locked;
|
||||
+ cxl_target_get_first;
|
||||
+ cxl_target_get_next;
|
||||
+ cxl_target_get_decoder;
|
||||
+ cxl_target_get_position;
|
||||
+ cxl_target_get_id;
|
||||
+ cxl_target_get_devname;
|
||||
+ cxl_target_maps_memdev;
|
||||
} LIBCXL_1;
|
||||
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
|
||||
index 439ed93..abda0e5 100644
|
||||
--- a/cxl/libcxl.h
|
||||
+++ b/cxl/libcxl.h
|
||||
@@ -104,6 +104,11 @@ struct cxl_decoder *cxl_decoder_get_next(struct cxl_decoder *decoder);
|
||||
unsigned long long cxl_decoder_get_resource(struct cxl_decoder *decoder);
|
||||
unsigned long long cxl_decoder_get_size(struct cxl_decoder *decoder);
|
||||
const char *cxl_decoder_get_devname(struct cxl_decoder *decoder);
|
||||
+struct cxl_target *cxl_decoder_get_target_by_memdev(struct cxl_decoder *decoder,
|
||||
+ struct cxl_memdev *memdev);
|
||||
+struct cxl_target *
|
||||
+cxl_decoder_get_target_by_position(struct cxl_decoder *decoder, int position);
|
||||
+int cxl_decoder_get_nr_targets(struct cxl_decoder *decoder);
|
||||
struct cxl_ctx *cxl_decoder_get_ctx(struct cxl_decoder *decoder);
|
||||
int cxl_decoder_get_id(struct cxl_decoder *decoder);
|
||||
struct cxl_port *cxl_decoder_get_port(struct cxl_decoder *decoder);
|
||||
@@ -126,6 +131,20 @@ bool cxl_decoder_is_locked(struct cxl_decoder *decoder);
|
||||
for (decoder = cxl_decoder_get_first(port); decoder != NULL; \
|
||||
decoder = cxl_decoder_get_next(decoder))
|
||||
|
||||
+struct cxl_target;
|
||||
+struct cxl_target *cxl_target_get_first(struct cxl_decoder *decoder);
|
||||
+struct cxl_target *cxl_target_get_next(struct cxl_target *target);
|
||||
+struct cxl_decoder *cxl_target_get_decoder(struct cxl_target *target);
|
||||
+int cxl_target_get_position(struct cxl_target *target);
|
||||
+unsigned long cxl_target_get_id(struct cxl_target *target);
|
||||
+const char *cxl_target_get_devname(struct cxl_target *target);
|
||||
+bool cxl_target_maps_memdev(struct cxl_target *target,
|
||||
+ struct cxl_memdev *memdev);
|
||||
+
|
||||
+#define cxl_target_foreach(decoder, target) \
|
||||
+ for (target = cxl_target_get_first(decoder); target != NULL; \
|
||||
+ target = cxl_target_get_next(target))
|
||||
+
|
||||
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);
|
||||
diff --git a/cxl/list.c b/cxl/list.c
|
||||
index d70192a..27c963a 100644
|
||||
--- a/cxl/list.c
|
||||
+++ b/cxl/list.c
|
||||
@@ -41,6 +41,8 @@ static const struct option options[] = {
|
||||
"filter by CXL decoder device name(s) / class"),
|
||||
OPT_BOOLEAN('D', "decoders", ¶m.decoders,
|
||||
"include CXL decoder info"),
|
||||
+ OPT_BOOLEAN('T', "targets", ¶m.targets,
|
||||
+ "include CXL target data with decoders"),
|
||||
OPT_BOOLEAN('i', "idle", ¶m.idle, "include disabled devices"),
|
||||
OPT_BOOLEAN('u', "human", ¶m.human,
|
||||
"use human friendly number formats "),
|
||||
--
|
||||
2.27.0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user