[PATCH] pmem: fix BUG() error in pmem.h:48 on X86_32
by Toshi Kani
After 'commit fc0c2028135c ("x86, pmem: use memcpy_mcsafe()
for memcpy_from_pmem()")', probing a PMEM device hits the BUG()
error below on X86_32 kernel.
kernel BUG at include/linux/pmem.h:48!
memcpy_from_pmem() calls arch_memcpy_from_pmem(), which is
unimplemented since CONFIG_ARCH_HAS_PMEM_API is undefined on
X86_32.
Fix the BUG() error by adding default_memcpy_from_pmem().
Signed-off-by: Toshi Kani <toshi.kani(a)hpe.com>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Cc: Ross Zwisler <ross.zwisler(a)linux.intel.com>
---
include/linux/pmem.h | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/include/linux/pmem.h b/include/linux/pmem.h
index ac6d872..57d146f 100644
--- a/include/linux/pmem.h
+++ b/include/linux/pmem.h
@@ -72,6 +72,18 @@ static inline void arch_invalidate_pmem(void __pmem *addr, size_t size)
}
#endif
+static inline bool arch_has_pmem_api(void)
+{
+ return IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API);
+}
+
+static inline int default_memcpy_from_pmem(void *dst, void __pmem const *src,
+ size_t size)
+{
+ memcpy(dst, (void __force *) src, size);
+ return 0;
+}
+
/*
* memcpy_from_pmem - read from persistent memory with error handling
* @dst: destination buffer
@@ -83,12 +95,10 @@ static inline void arch_invalidate_pmem(void __pmem *addr, size_t size)
static inline int memcpy_from_pmem(void *dst, void __pmem const *src,
size_t size)
{
- return arch_memcpy_from_pmem(dst, src, size);
-}
-
-static inline bool arch_has_pmem_api(void)
-{
- return IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API);
+ if (arch_has_pmem_api())
+ return arch_memcpy_from_pmem(dst, src, size);
+ else
+ return default_memcpy_from_pmem(dst, src, size);
}
/**
6 years, 2 months
[PATCH v2 0/5] Align mmap address for DAX pmd mappings
by Toshi Kani
When CONFIG_FS_DAX_PMD is set, DAX supports mmap() using pmd page
size. This feature relies on both mmap virtual address and FS
block (i.e. physical address) to be aligned by the pmd page size.
Users can use mkfs options to specify FS to align block allocations.
However, aligning mmap address requires code changes to existing
applications for providing a pmd-aligned address to mmap().
For instance, fio with "ioengine=mmap" performs I/Os with mmap() [1].
It calls mmap() with a NULL address, which needs to be changed to
provide a pmd-aligned address for testing with DAX pmd mappings.
Changing all applications that call mmap() with NULL is undesirable.
This patch-set extends filesystems to align an mmap address for
a DAX file so that unmodified applications can use DAX pmd mappings.
[1]: https://github.com/axboe/fio/blob/master/engines/mmap.c
v2:
- Change filesystems to provide their get_unmapped_area().
(Matthew Wilcox)
- Add more description about the benefit. (Matthew Wilcox)
---
Toshi Kani (5):
1/5 dax: add dax_get_unmapped_area for pmd mappings
2/5 ext4: call dax_get_unmapped_area() for DAX pmd mappings
3/5 xfs: call dax_get_unmapped_area() for DAX pmd mappings
4/5 ext2: call dax_get_unmapped_area() for DAX pmd mappings
5/5 block: call dax_get_unmapped_area() for DAX pmd mappings
---
fs/block_dev.c | 3 +++
fs/dax.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
fs/ext2/file.c | 3 +++
fs/ext4/file.c | 3 +++
fs/xfs/xfs_file.c | 3 +++
include/linux/dax.h | 2 ++
6 files changed, 59 insertions(+)
6 years, 2 months
[ndctl PATCH 0/4] read-labels, destroy-namespace, and misc updates
by Dan Williams
For debug it is useful to be able to dump a DIMM's label area, this
includes a json dump option in addition to a raw binary format.
For completeness with create-namespace, add a destroy-namespace
facility. This simply refactors the namespace teardown that occurs
during reconfiguration into its own utility.
Finally, a few cleanups and fixups for compiling against older ndctl.h
headers.
---
Dan Williams (4):
ndctl: fix compile in the HAVE_NDCTL_{ARS|CLEAR_ERROR}=n cases
ndctl: use filter utility routines zero-labels
ndctl: new 'read-labels' utility
ndctl: new 'destroy-namespace' utility
Documentation/Makefile.am | 6
Documentation/labels-description.txt | 6
Documentation/labels-options.txt | 13 +
Documentation/ndctl-destroy-namespace.txt | 27 ++
Documentation/ndctl-read-labels.txt | 30 ++
Documentation/ndctl-zero-labels.txt | 23 --
Makefile.am | 1
builtin-list.c | 21 -
builtin-read-labels.c | 420 +++++++++++++++++++++++++++++
builtin-xaction-namespace.c | 61 ++++
builtin-zero-labels.c | 27 --
builtin.h | 2
lib/libndctl-ars.c | 18 +
lib/libndctl.c | 10 +
ndctl.c | 4
test/libndctl.c | 55 +---
util/json.c | 15 +
util/json.h | 3
18 files changed, 638 insertions(+), 104 deletions(-)
create mode 100644 Documentation/labels-description.txt
create mode 100644 Documentation/labels-options.txt
create mode 100644 Documentation/ndctl-destroy-namespace.txt
create mode 100644 Documentation/ndctl-read-labels.txt
create mode 100644 builtin-read-labels.c
6 years, 2 months
[GIT PULL] libnvdimm fixes for 4.6-rc3
by Williams, Dan J
Hi Linus, please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm libnvdimm-fixes
...to receive 3 fixes, the first 2 are tagged for -stable.
1/ The ndctl utility/library gained expanded unit tests illuminating a
long standing bug in the libnvdimm SMART data retrieval implementation.
It has been broken since its initial implementation, now fixed.
2/ Another one line fix for the detection of stale info blocks.
Without this change userspace can get into a situation where it is
unable to reconfigure a namespace.
3/ Fix the badblock initialization path in the presence of the new (in
4,6-rc1) section alignment workarounds. Without this change badblocks
will be reported at the wrong offset.
These have received a build success report from the kbuild robot and
have appeared in -next with no reported issues.
The following changes since commit 9735a22799b9214d17d3c231fe377fc852f042e9:
Linux 4.6-rc2 (2016-04-03 09:09:40 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm libnvdimm-fixes
for you to fetch changes up to a390180291dd9a2392bbab4242cde712c326efc6:
libnvdimm, pfn: fix nvdimm_namespace_add_poison() vs section alignment (2016-04-07 20:02:06 -0700)
----------------------------------------------------------------
Dan Williams (3):
libnvdimm: fix smart data retrieval
libnvdimm, pfn: fix uuid validation
libnvdimm, pfn: fix nvdimm_namespace_add_poison() vs section alignment
drivers/nvdimm/bus.c | 2 +-
drivers/nvdimm/core.c | 41 ++++++++++++++++++++---------------------
drivers/nvdimm/nd.h | 4 ++--
drivers/nvdimm/pfn_devs.c | 2 +-
drivers/nvdimm/pmem.c | 36 +++++++++++++++++++++++++++++-------
5 files changed, 53 insertions(+), 32 deletions(-)
6 years, 2 months
[PATCH v1 00/10] uuid: convert users to generic UUID API
by Andy Shevchenko
There are few fumctions here and there along with type definitions that provide
UUID API. This series consolidates everything under one hood and converts
current users.
This has been tested for a while internally, however it doesn't mean we covered
all possible cases (especially accuracy of UUID constants after conversion).
So, please test this as much as you can and provide your tag. We appreciate the
effort.
Andy Shevchenko (10):
lib/vsprintf: simplify UUID printing
lib/uuid: move generate_random_uuid() to uuid.c
lib/uuid: introduce few more generic helpers for UUID
lib/uuid: remove FSF address
ACPI: switch to use generic UUID API
device property: switch to use UUID API
sysctl: drop away useless label
sysctl: use generic UUID library
efi: redefine type, constant, macro from generic code
efivars: use generic UUID library
drivers/acpi/acpi_extlog.c | 8 +-
drivers/acpi/bus.c | 29 +------
drivers/acpi/nfit.c | 34 ++++----
drivers/acpi/nfit.h | 3 +-
drivers/acpi/property.c | 18 ++---
drivers/acpi/utils.c | 4 +-
drivers/char/random.c | 21 +----
drivers/char/tpm/tpm_crb.c | 9 +--
drivers/char/tpm/tpm_ppi.c | 20 ++---
drivers/gpu/drm/i915/intel_acpi.c | 14 ++--
drivers/gpu/drm/nouveau/nouveau_acpi.c | 20 +++--
drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c | 9 +--
drivers/hid/i2c-hid/i2c-hid.c | 9 +--
drivers/iommu/dmar.c | 11 ++-
drivers/pci/pci-acpi.c | 11 ++-
drivers/pci/pci-label.c | 4 +-
drivers/thermal/int340x_thermal/int3400_thermal.c | 6 +-
drivers/usb/host/xhci-pci.c | 9 +--
fs/btrfs/volumes.c | 2 +-
fs/efivarfs/inode.c | 40 +---------
fs/ext4/ioctl.c | 1 +
fs/f2fs/file.c | 2 +-
fs/reiserfs/objectid.c | 2 +-
fs/ubifs/sb.c | 2 +-
include/acpi/acpi_bus.h | 10 ++-
include/linux/acpi.h | 2 +-
include/linux/efi.h | 14 +---
include/linux/pci-acpi.h | 2 +-
include/linux/random.h | 1 -
include/linux/uuid.h | 21 +++--
include/uapi/linux/uuid.h | 4 -
kernel/sysctl_binary.c | 30 +++----
lib/uuid.c | 96 +++++++++++++++++++++--
lib/vsprintf.c | 21 ++---
sound/soc/intel/skylake/skl-nhlt.c | 7 +-
35 files changed, 237 insertions(+), 259 deletions(-)
--
2.7.0
6 years, 2 months
[PATCH] libnvdimm, test: add mock SMART data payload
by Dan Williams
Provide simulated SMART data to enable the ndctl implementation of SMART
data retrieval and parsing.
The payload is defined here, "Section 4.1 SMART and Health Info
(Function Index 1)":
http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/bus.c | 2 ++
include/uapi/linux/ndctl.h | 31 ++++++++++++++++++++++++++++++-
tools/testing/nvdimm/test/nfit.c | 25 +++++++++++++++++++++++++
3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 19f822d7f652..ea805ac641e2 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -783,6 +783,8 @@ int __init nvdimm_bus_init(void)
{
int rc;
+ BUILD_BUG_ON(sizeof(struct nd_smart_payload) != 128);
+
rc = bus_register(&nvdimm_bus_type);
if (rc)
return rc;
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
index 7cc28ab05b87..f6747b90db90 100644
--- a/include/uapi/linux/ndctl.h
+++ b/include/uapi/linux/ndctl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015, Intel Corporation.
+ * Copyright (c) 2014-2016, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
@@ -20,6 +20,35 @@ struct nd_cmd_smart {
__u8 data[128];
} __packed;
+enum {
+ ND_SMART_HEALTH_VALID = 1 << 0,
+ ND_SMART_TEMP_VALID = 1 << 1,
+ ND_SMART_SPARES_VALID = 1 << 2,
+ ND_SMART_ALARM_VALID = 1 << 3,
+ ND_SMART_USED_VALID = 1 << 4,
+ ND_SMART_SHUTDOWN_VALID = 1 << 5,
+ ND_SMART_VENDOR_VALID = 1 << 6,
+ ND_SMART_TEMP_TRIP = 1 << 0,
+ ND_SMART_SPARE_TRIP = 1 << 1,
+ ND_SMART_NON_CRITICAL_HEALTH = 1 << 0,
+ ND_SMART_CRITICAL_HEALTH = 1 << 1,
+ ND_SMART_FATAL_HEALTH = 1 << 2,
+};
+
+struct nd_smart_payload {
+ __u32 flags;
+ __u8 reserved0[4];
+ __u8 health;
+ __u16 temperature;
+ __u8 spares;
+ __u8 alarm_flags;
+ __u8 life_used;
+ __u8 shutdown_state;
+ __u8 reserved1;
+ __u32 vendor_size;
+ __u8 vendor_data[108];
+} __packed;
+
struct nd_cmd_smart_threshold {
__u32 status;
__u8 data[8];
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 3187322eeed7..54c9f3cc3d34 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -330,6 +330,27 @@ static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error *clear_err,
return 0;
}
+static int nfit_test_cmd_smart(struct nd_cmd_smart *smart, unsigned int buf_len)
+{
+ static const struct nd_smart_payload smart_data = {
+ .flags = ND_SMART_HEALTH_VALID | ND_SMART_TEMP_VALID
+ | ND_SMART_SPARES_VALID | ND_SMART_ALARM_VALID
+ | ND_SMART_USED_VALID | ND_SMART_SHUTDOWN_VALID,
+ .health = ND_SMART_NON_CRITICAL_HEALTH,
+ .temperature = 23 * 16,
+ .spares = 75,
+ .alarm_flags = ND_SMART_SPARE_TRIP | ND_SMART_TEMP_TRIP,
+ .life_used = 5,
+ .shutdown_state = 0,
+ .vendor_size = 0,
+ };
+
+ if (buf_len < sizeof(*smart))
+ return -EINVAL;
+ memcpy(smart->data, &smart_data, sizeof(*smart));
+ return 0;
+}
+
static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc)
@@ -368,6 +389,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
rc = nfit_test_cmd_set_config_data(buf, buf_len,
t->label[i]);
break;
+ case ND_CMD_SMART:
+ rc = nfit_test_cmd_smart(buf, buf_len);
+ break;
default:
return -ENOTTY;
}
@@ -1254,6 +1278,7 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en);
+ set_bit(ND_CMD_SMART, &acpi_desc->dimm_dsm_force_en);
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_dsm_force_en);
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_dsm_force_en);
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_dsm_force_en);
6 years, 2 months
[ndctl PATCH 0/5] smart support and 'list' enhancements
by Dan Williams
1/ Provide helper routines for higher level management software to issue
SMART data retrieval commands.
2/ Add a reference implementation of SMART data retrieval by extending
the 'list' command to emit json with SMART key/value data.
3/ With health information available it is useful to know which
namespaces are impacted by a dimm that reports a bad health status,
so a 'filter by dimm' mechanism is added to the 'list' command.
---
Dan Williams (5):
ndctl: rebuild libndctl.h when libndctl.h.in changes
ndctl: helper for S.M.A.R.T. data retrieval
ndctl, list: clean up default behavior
ndctl, list: add a '--health' option
ndctl, list: add 'filter by dimm' capability
Documentation/ndctl-list.txt | 29 ++++++++++++-
Makefile.am | 8 +++
builtin-list.c | 31 +++++++++++--
configure.ac | 26 +++++++++++
lib/libndctl-private.h | 1
lib/libndctl-smart.c | 81 +++++++++++++++++++++++++++++++++++
lib/libndctl.c | 1
lib/libndctl.sym | 10 ++++
lib/ndctl/libndctl.h.in | 55 ++++++++++++++++++++++++
ndctl.h | 29 +++++++++++++
test/libndctl.c | 68 +++++++++++++++++++++++++++++
util/filter.c | 83 ++++++++++++++++++++++++++++++++++++
util/filter.h | 5 ++
util/json.c | 97 ++++++++++++++++++++++++++++++++++++++++++
util/json.h | 1
15 files changed, 516 insertions(+), 9 deletions(-)
create mode 100644 lib/libndctl-smart.c
6 years, 2 months
[PATCH] x86 get_unmapped_area: Add PMD alignment for DAX PMD mmap
by Toshi Kani
When CONFIG_FS_DAX_PMD is set, DAX supports mmap() using PMD page
size. This feature relies on both mmap virtual address and FS
block data (i.e. physical address) to be aligned by the PMD page
size. Users can use mkfs options to specify FS to align block
allocations. However, aligning mmap() address requires application
changes to mmap() calls, such as:
- /* let the kernel to assign a mmap addr */
- mptr = mmap(NULL, fsize, PROT_READ|PROT_WRITE, FLAGS, fd, 0);
+ /* 1. obtain a PMD-aligned virtual address */
+ ret = posix_memalign(&mptr, PMD_SIZE, fsize);
+ if (!ret)
+ free(mptr); /* 2. release the virt addr */
+
+ /* 3. then pass the PMD-aligned virt addr to mmap() */
+ mptr = mmap(mptr, fsize, PROT_READ|PROT_WRITE, FLAGS, fd, 0);
These changes add unnecessary dependency to DAX and PMD page size
into application code. The kernel should assign a mmap address
appropriate for the operation.
Change arch_get_unmapped_area() and arch_get_unmapped_area_topdown()
to request PMD_SIZE alignment when the request is for a DAX file and
its mapping range is large enough for using a PMD page.
Signed-off-by: Toshi Kani <toshi.kani(a)hpe.com>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: Ingo Molnar <mingo(a)kernel.org>
Cc: H. Peter Anvin <hpa(a)zytor.com>
Cc: Borislav Petkov <bp(a)suse.de>
Cc: Dan Williams <dan.j.williams(a)intel.com>
Cc: Matthew Wilcox <willy(a)linux.intel.com>
Cc: Kirill A. Shutemov <kirill.shutemov(a)linux.intel.com>
---
arch/x86/kernel/sys_x86_64.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index 10e0272..a294c66 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -157,6 +157,13 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
info.align_mask = get_align_mask();
info.align_offset += get_align_bits();
}
+ if (filp && IS_ENABLED(CONFIG_FS_DAX_PMD) && IS_DAX(file_inode(filp))) {
+ unsigned long off_end = info.align_offset + len;
+ unsigned long off_pmd = round_up(info.align_offset, PMD_SIZE);
+
+ if ((off_end > off_pmd) && ((off_end - off_pmd) >= PMD_SIZE))
+ info.align_mask |= (PMD_SIZE - 1);
+ }
return vm_unmapped_area(&info);
}
@@ -200,6 +207,13 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
info.align_mask = get_align_mask();
info.align_offset += get_align_bits();
}
+ if (filp && IS_ENABLED(CONFIG_FS_DAX_PMD) && IS_DAX(file_inode(filp))) {
+ unsigned long off_end = info.align_offset + len;
+ unsigned long off_pmd = round_up(info.align_offset, PMD_SIZE);
+
+ if ((off_end > off_pmd) && ((off_end - off_pmd) >= PMD_SIZE))
+ info.align_mask |= (PMD_SIZE - 1);
+ }
addr = vm_unmapped_area(&info);
if (!(addr & ~PAGE_MASK))
return addr;
6 years, 2 months
[PATCH] libnvdimm: fix smart data retrieval
by Dan Williams
It appears that smart data retrieval has been broken the since the
initial implementation. Fix the payload size to be 128-bytes per the
specification.
Cc: <stable(a)vger.kernel.org>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/bus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index fc82743aefb6..19f822d7f652 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -407,7 +407,7 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = {
[ND_CMD_IMPLEMENTED] = { },
[ND_CMD_SMART] = {
.out_num = 2,
- .out_sizes = { 4, 8, },
+ .out_sizes = { 4, 128, },
},
[ND_CMD_SMART_THRESHOLD] = {
.out_num = 2,
6 years, 2 months
[ndctl PATCH] ndctl: add ndctl_dimm_get_{formats|formatN}
by Dan Williams
Add apis to return the alternative format interface codes that a given
dimm supports.
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
lib/libndctl.c | 42 +++++++++++++++++++++++++++++++++++-------
lib/libndctl.sym | 2 ++
lib/ndctl/libndctl.h.in | 2 ++
test/libndctl.c | 33 +++++++++++++++++++++++++--------
4 files changed, 64 insertions(+), 15 deletions(-)
diff --git a/lib/libndctl.c b/lib/libndctl.c
index b628243df651..26de91af8a63 100644
--- a/lib/libndctl.c
+++ b/lib/libndctl.c
@@ -111,12 +111,13 @@ struct ndctl_bus {
* @vendor_id: hardware component vendor
* @device_id: hardware device id
* @revision_id: hardware revision id
- * @format_id: format interface code number
* @node: system node-id
* @socket: socket-id in the node
* @imc: memory-controller-id in the socket
* @channel: channel-id in the memory-controller
* @dimm: dimm-id in the channel
+ * @formats: number of support interfaces
+ * @format: array of format interface code numbers
*/
struct ndctl_dimm {
struct kmod_module *module;
@@ -126,7 +127,6 @@ struct ndctl_dimm {
unsigned short vendor_id;
unsigned short device_id;
unsigned short revision_id;
- unsigned short format_id;
unsigned long dsm_mask;
char *dimm_path;
char *dimm_buf;
@@ -143,6 +143,8 @@ struct ndctl_dimm {
};
};
struct list_node list;
+ int formats;
+ int format[0];
};
/**
@@ -1179,7 +1181,7 @@ static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias);
static int add_dimm(void *parent, int id, const char *dimm_base)
{
- int rc = -ENOMEM;
+ int rc, formats, i;
struct ndctl_dimm *dimm;
char buf[SYSFS_ATTR_SIZE];
struct ndctl_bus *bus = parent;
@@ -1189,7 +1191,13 @@ static int add_dimm(void *parent, int id, const char *dimm_base)
if (!path)
return -ENOMEM;
- dimm = calloc(1, sizeof(*dimm));
+ sprintf(path, "%s/nfit/formats", dimm_base);
+ if (sysfs_read_attr(ctx, path, buf) < 0)
+ formats = 1;
+ else
+ formats = strtoul(buf, NULL, 0);
+
+ dimm = calloc(1, sizeof(*dimm) + sizeof(int) * formats);
if (!dimm)
goto err_dimm;
dimm->bus = bus;
@@ -1228,7 +1236,9 @@ static int add_dimm(void *parent, int id, const char *dimm_base)
dimm->serial = -1;
dimm->device_id = -1;
dimm->revision_id = -1;
- dimm->format_id = -1;
+ for (i = 0; i < formats; i++)
+ dimm->format[i] = -1;
+
if (!ndctl_bus_has_nfit(bus))
goto out;
@@ -1260,9 +1270,15 @@ static int add_dimm(void *parent, int id, const char *dimm_base)
if (sysfs_read_attr(ctx, path, buf) == 0)
dimm->revision_id = strtoul(buf, NULL, 0);
+ dimm->formats = formats;
sprintf(path, "%s/nfit/format", dimm_base);
if (sysfs_read_attr(ctx, path, buf) == 0)
- dimm->format_id = strtoul(buf, NULL, 0);
+ dimm->format[0] = strtoul(buf, NULL, 0);
+ for (i = 1; i < formats; i++) {
+ sprintf(path, "%s/nfit/format%d", dimm_base, i);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
+ dimm->format[i] = strtoul(buf, NULL, 0);
+ }
sprintf(path, "%s/nfit/flags", dimm_base);
if (sysfs_read_attr(ctx, path, buf) == 0)
@@ -1332,7 +1348,19 @@ NDCTL_EXPORT unsigned short ndctl_dimm_get_revision(struct ndctl_dimm *dimm)
NDCTL_EXPORT unsigned short ndctl_dimm_get_format(struct ndctl_dimm *dimm)
{
- return dimm->format_id;
+ return dimm->format[0];
+}
+
+NDCTL_EXPORT int ndctl_dimm_get_formats(struct ndctl_dimm *dimm)
+{
+ return dimm->formats;
+}
+
+NDCTL_EXPORT int ndctl_dimm_get_formatN(struct ndctl_dimm *dimm, int i)
+{
+ if (i < dimm->formats && i >= 0)
+ return dimm->format[i];
+ return -EINVAL;
}
NDCTL_EXPORT unsigned int ndctl_dimm_get_major(struct ndctl_dimm *dimm)
diff --git a/lib/libndctl.sym b/lib/libndctl.sym
index 9df2b5a6e89d..5ff8848ee6d3 100644
--- a/lib/libndctl.sym
+++ b/lib/libndctl.sym
@@ -41,6 +41,8 @@ global:
ndctl_dimm_get_device;
ndctl_dimm_get_revision;
ndctl_dimm_get_format;
+ ndctl_dimm_get_formats;
+ ndctl_dimm_get_formatN;
ndctl_dimm_get_major;
ndctl_dimm_get_minor;
ndctl_dimm_get_serial;
diff --git a/lib/ndctl/libndctl.h.in b/lib/ndctl/libndctl.h.in
index 831f7822e91f..2a05e0ba477c 100644
--- a/lib/ndctl/libndctl.h.in
+++ b/lib/ndctl/libndctl.h.in
@@ -121,6 +121,8 @@ unsigned short ndctl_dimm_get_vendor(struct ndctl_dimm *dimm);
unsigned short ndctl_dimm_get_device(struct ndctl_dimm *dimm);
unsigned short ndctl_dimm_get_revision(struct ndctl_dimm *dimm);
unsigned short ndctl_dimm_get_format(struct ndctl_dimm *dimm);
+int ndctl_dimm_get_formats(struct ndctl_dimm *dimm);
+int ndctl_dimm_get_formatN(struct ndctl_dimm *dimm, int i);
unsigned int ndctl_dimm_get_major(struct ndctl_dimm *dimm);
unsigned int ndctl_dimm_get_minor(struct ndctl_dimm *dimm);
unsigned int ndctl_dimm_get_id(struct ndctl_dimm *dimm);
diff --git a/test/libndctl.c b/test/libndctl.c
index 0cab89208867..0e9c830e68a1 100644
--- a/test/libndctl.c
+++ b/test/libndctl.c
@@ -126,29 +126,31 @@ struct dimm {
unsigned int f_restore:1;
};
};
+ int formats;
+ int format[2];
};
#define DIMM_HANDLE(n, s, i, c, d) \
(((n & 0xfff) << 16) | ((s & 0xf) << 12) | ((i & 0xf) << 8) \
| ((c & 0xf) << 4) | (d & 0xf))
static struct dimm dimms0[] = {
- { DIMM_HANDLE(0, 0, 0, 0, 0), 0, { 0 }, },
- { DIMM_HANDLE(0, 0, 0, 0, 1), 1, { 0 }, },
- { DIMM_HANDLE(0, 0, 1, 0, 0), 2, { 0 }, },
- { DIMM_HANDLE(0, 0, 1, 0, 1), 3, { 0 }, },
+ { DIMM_HANDLE(0, 0, 0, 0, 0), 0, { 0 }, 2, { 0x201, 0x301, }, },
+ { DIMM_HANDLE(0, 0, 0, 0, 1), 1, { 0 }, 2, { 0x201, 0x301, }, },
+ { DIMM_HANDLE(0, 0, 1, 0, 0), 2, { 0 }, 2, { 0x201, 0x301, }, },
+ { DIMM_HANDLE(0, 0, 1, 0, 1), 3, { 0 }, 2, { 0x201, 0x301, }, },
};
static struct dimm dimms1[] = {
{
- DIMM_HANDLE(0, 0, 0, 0, 0), 0,
- {
+ DIMM_HANDLE(0, 0, 0, 0, 0), 0, {
.f_arm = 1,
.f_save = 1,
.f_flush = 1,
.f_smart = 1,
.f_restore = 1,
},
- }
+ 1, { 0x101, },
+ },
};
static struct btt {
@@ -1886,7 +1888,7 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
unsigned long bus_commands, unsigned long dimm_commands,
struct ndctl_test *test)
{
- int i, rc;
+ int i, j, rc;
for (i = 0; i < n; i++) {
struct ndctl_dimm *dimm = get_dimm_by_handle(bus, dimms[i].handle);
@@ -1930,6 +1932,21 @@ static int check_dimms(struct ndctl_bus *bus, struct dimm *dimms, int n,
return -ENXIO;
}
+ if (ndctl_dimm_get_formats(dimm) != dimms[i].formats) {
+ fprintf(stderr, "dimm%d expected formats: %d got: %d\n",
+ i, dimms[i].formats,
+ ndctl_dimm_get_formats(dimm));
+ return -ENXIO;
+ }
+ for (j = 0; j < dimms[i].formats; j++) {
+ if (ndctl_dimm_get_formatN(dimm, j) != dimms[i].format[j]) {
+ fprintf(stderr, "dimm%d expected format[%d]: %d got: %d\n",
+ i, j, dimms[i].format[j],
+ ndctl_dimm_get_formatN(dimm, j));
+ return -ENXIO;
+ }
+ }
+
rc = check_commands(bus, dimm, bus_commands, dimm_commands, test);
if (rc)
return rc;
6 years, 2 months