[Linux-nvdimm] [PATCH v2 00/20] libnd: non-volatile memory device support
by Dan Williams
Changes since v1 [1]: Incorporates feedback received prior to April 24.
1/ Ingo said [2]:
"So why on earth is this whole concept and the naming itself
('drivers/block/nd/' stands for 'NFIT Defined', apparently)
revolving around a specific 'firmware' mindset and revolving
around specific, weirdly named, overly complicated looking
firmware interfaces that come with their own new weird
glossary??"
Indeed, we of course consulted the NFIT specification to determine
the shape of the sub-system, but then let its terms and data
structures permeate too deep into the implementation. That is fixed
now with all NFIT specifics factored out into acpi.c. The NFIT is no
longer required reading to review libnd. Only three concepts are
needed:
i/ PMEM - contiguous memory range where cpu stores are
persistent once they are flushed through the memory
controller.
ii/ BLK - mmio apertures (sliding windows) that can be
programmed to access an aperture's-worth of persistent
media at a time.
iii/ DPA - "dimm-physical-address", address space local to a
dimm. A dimm may provide both PMEM-mode and BLK-mode
access to a range of DPA. libnd manages allocation of DPA
to either PMEM or BLK-namespaces to resolve this aliasing.
The v1..v2 diffstat below shows the migration of nfit-specifics to
acpi.c and the new state of libnd being nfit-free. "nd" now only
refers to "non-volatile devices". Note, reworked documentation will
return once the review has settled.
Documentation/blockdev/nd.txt | 867 ---------------------
MAINTAINERS | 34 +-
arch/ia64/kernel/efi.c | 5 +-
arch/x86/kernel/e820.c | 11 +-
arch/x86/kernel/pmem.c | 2 +-
drivers/block/Makefile | 2 +-
drivers/block/nd/Kconfig | 135 ++--
drivers/block/nd/Makefile | 32 +-
drivers/block/nd/acpi.c | 1506 +++++++++++++++++++++++++++++++------
drivers/block/nd/acpi_nfit.h | 321 ++++++++
drivers/block/nd/blk.c | 27 +-
drivers/block/nd/btt.c | 6 +-
drivers/block/nd/btt_devs.c | 8 +-
drivers/block/nd/bus.c | 337 +++++----
drivers/block/nd/core.c | 574 +-------------
drivers/block/nd/dimm.c | 11 -
drivers/block/nd/dimm_devs.c | 292 ++-----
drivers/block/nd/e820.c | 100 +++
drivers/block/nd/libnd.h | 122 +++
drivers/block/nd/namespace_devs.c | 10 +-
drivers/block/nd/nd-private.h | 107 +--
drivers/block/nd/nd.h | 91 +--
drivers/block/nd/nfit.h | 238 ------
drivers/block/nd/pmem.c | 56 +-
drivers/block/nd/region.c | 78 +-
drivers/block/nd/region_devs.c | 783 +++----------------
drivers/block/nd/test/iomap.c | 86 +--
drivers/block/nd/test/nfit.c | 1115 +++++++++++++++------------
drivers/block/nd/test/nfit_test.h | 15 +-
include/uapi/linux/ndctl.h | 130 ++--
30 files changed, 3166 insertions(+), 3935 deletions(-)
delete mode 100644 Documentation/blockdev/nd.txt
create mode 100644 drivers/block/nd/acpi_nfit.h
create mode 100644 drivers/block/nd/e820.c
create mode 100644 drivers/block/nd/libnd.h
delete mode 100644 drivers/block/nd/nfit.h
[1]: https://lists.01.org/pipermail/linux-nvdimm/2015-April/000484.html
[2]: https://lists.01.org/pipermail/linux-nvdimm/2015-April/000520.html
2/ Christoph asked the pmem ida conversion to be moved to its own patch
(done), and to consider leaving the current pmem.c in drivers/block/.
Instead, I converted the e820-type-12 enabling to be the first
non-ACPI-NFIT based consumer of libnd. The new nd_e820 driver simply
registers e820-type-12 ranges as libnd PMEM regions. Among other
things this conversion enables BTT for these ranges. The alternative
is to move drivers/block/nd/nd.h internals out to include/linux/
which I think is worse.
3/ Toshi reported that the NFIT parsing fails to handle the case of a
PMEM range with a single-dimm (non-aliasing) interleave description.
Support for this case was added and is tested by default by the
nfit_test.1 configuration.
4/ Toshi reported that we should not be treating a missing _STA property
as a "dimm disabled by firmware" case. (fixed).
5/ Christoph noted that ND_ARCH_HAS_IOREMAP_CACHE needs to be moved to
arch code. It is gone for now and we'll revisit when adding cached
mappings back to the PMEM driver.
6/ Toshi mentioned that the presence of two different nd_bus_probe()
functions was confusing. (cleaned up).
7/ Robert asked for s/btt_checksum/nd_btt_checksum/ (done).
8/ Linda asked for nfit_test to honor dynamic cma reservations via the
cma= command line (done). The cma requirements have also been
reduced to 128M as only the simulated DAX regions need CMA. The rest
can use vmalloc().
---
Available here:
git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm nd-v2
---
Dan Williams (18):
e820, efi: add ACPI 6.0 persistent memory types
libnd, nd_acpi: initial libnd infrastructure and NFIT support
nd_acpi, nfit-test: manufactured NFITs for interface development
libnd: ndctl class device, and nd bus attributes
libnd, nd_acpi: dimm/memory-devices
libnd: ndctl.h, the nd ioctl abi
libnd, nd_dimm: dimm driver and base libnd device-driver infrastructure
libnd, nd_acpi: regions (block-data-window, persistent memory, volatile memory)
libnd: support for legacy (non-aliasing) nvdimms
pmem: use ida
libnd, nd_pmem: add libnd support to the pmem driver
libnd, nd_acpi: add interleave-set state-tracking infrastructure
libnd: namespace indices: read and validate
libnd: pmem label sets and namespace instantiation.
libnd: blk labels and namespace instantiation
libnd: write pmem label set
libnd: write blk label set
libnd: infrastructure for btt devices
Ross Zwisler (1):
libnd, nd_acpi, nd_blk: driver for BLK-mode access persistent memory
Vishal Verma (1):
nd_btt: atomic sector updates
Documentation/blockdev/btt.txt | 273 ++++++
arch/arm64/kernel/efi.c | 1
arch/ia64/kernel/efi.c | 4
arch/x86/boot/compressed/eboot.c | 4
arch/x86/include/uapi/asm/e820.h | 1
arch/x86/kernel/e820.c | 26 +
arch/x86/kernel/pmem.c | 2
arch/x86/platform/efi/efi.c | 3
drivers/block/Kconfig | 13
drivers/block/Makefile | 2
drivers/block/nd/Kconfig | 129 +++
drivers/block/nd/Makefile | 41 +
drivers/block/nd/acpi.c | 1505 +++++++++++++++++++++++++++++++++
drivers/block/nd/acpi_nfit.h | 321 +++++++
drivers/block/nd/blk.c | 264 ++++++
drivers/block/nd/btt.c | 1423 +++++++++++++++++++++++++++++++
drivers/block/nd/btt.h | 185 ++++
drivers/block/nd/btt_devs.c | 443 ++++++++++
drivers/block/nd/bus.c | 770 +++++++++++++++++
drivers/block/nd/core.c | 471 ++++++++++
drivers/block/nd/dimm.c | 115 +++
drivers/block/nd/dimm_devs.c | 507 +++++++++++
drivers/block/nd/e820.c | 100 ++
drivers/block/nd/label.c | 925 ++++++++++++++++++++
drivers/block/nd/label.h | 143 +++
drivers/block/nd/libnd.h | 122 +++
drivers/block/nd/namespace_devs.c | 1701 +++++++++++++++++++++++++++++++++++++
drivers/block/nd/nd-private.h | 114 ++
drivers/block/nd/nd.h | 261 ++++++
drivers/block/nd/pmem.c | 114 ++
drivers/block/nd/region.c | 159 +++
drivers/block/nd/region_devs.c | 637 ++++++++++++++
drivers/block/nd/test/Makefile | 5
drivers/block/nd/test/iomap.c | 151 +++
drivers/block/nd/test/nfit.c | 1131 +++++++++++++++++++++++++
drivers/block/nd/test/nfit_test.h | 26 +
include/linux/efi.h | 3
include/linux/nd.h | 98 ++
include/uapi/linux/Kbuild | 1
include/uapi/linux/ndctl.h | 199 ++++
40 files changed, 12345 insertions(+), 48 deletions(-)
create mode 100644 Documentation/blockdev/btt.txt
create mode 100644 drivers/block/nd/Kconfig
create mode 100644 drivers/block/nd/Makefile
create mode 100644 drivers/block/nd/acpi.c
create mode 100644 drivers/block/nd/acpi_nfit.h
create mode 100644 drivers/block/nd/blk.c
create mode 100644 drivers/block/nd/btt.c
create mode 100644 drivers/block/nd/btt.h
create mode 100644 drivers/block/nd/btt_devs.c
create mode 100644 drivers/block/nd/bus.c
create mode 100644 drivers/block/nd/core.c
create mode 100644 drivers/block/nd/dimm.c
create mode 100644 drivers/block/nd/dimm_devs.c
create mode 100644 drivers/block/nd/e820.c
create mode 100644 drivers/block/nd/label.c
create mode 100644 drivers/block/nd/label.h
create mode 100644 drivers/block/nd/libnd.h
create mode 100644 drivers/block/nd/namespace_devs.c
create mode 100644 drivers/block/nd/nd-private.h
create mode 100644 drivers/block/nd/nd.h
rename drivers/block/{pmem.c => nd/pmem.c} (68%)
create mode 100644 drivers/block/nd/region.c
create mode 100644 drivers/block/nd/region_devs.c
create mode 100644 drivers/block/nd/test/Makefile
create mode 100644 drivers/block/nd/test/iomap.c
create mode 100644 drivers/block/nd/test/nfit.c
create mode 100644 drivers/block/nd/test/nfit_test.h
create mode 100644 include/linux/nd.h
create mode 100644 include/uapi/linux/ndctl.h
5 years, 7 months
[Linux-nvdimm] [GIT PULL] PMEM driver for v4.1
by Ingo Molnar
Linus,
Please pull the latest x86-pmem-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-pmem-for-linus
# HEAD: 4c1eaa2344fb26bb5e936fb4d8ee307343ea0089 drivers/block/pmem: Fix 32-bit build warning in pmem_alloc()
This is the initial support for the pmem block device driver:
persistent non-volatile memory space mapped into the system's physical
memory space as large physical memory regions.
The driver is based on Intel code, written by Ross Zwisler, with fixes
by Boaz Harrosh, integrated with x86 e820 memory resource management
and tidied up by Christoph Hellwig.
Note that there were two other separate pmem driver submissions to
lkml: but apparently all parties (Ross Zwisler, Boaz Harrosh) are
reasonably happy with this initial version.
This version enables minimal support that enables persistent memory
devices out in the wild to work as block devices, identified through a
magic (non-standard) e820 flag and auto-discovered if
CONFIG_X86_PMEM_LEGACY=y, or added explicitly through manipulating the
memory maps via the "memmap=..." boot option with the new, special '!'
modifier character.
Limitations: this is a regular block device, and since the pmem areas
are not struct page backed, they are invisible to the rest of the
system (other than the block IO device), so direct IO to/from pmem
areas, direct mmap() or XIP is not possible yet. The page cache will
also shadow and double buffer pmem contents, etc.
Initial support is for x86.
Thanks,
Ingo
------------------>
Christoph Hellwig (1):
x86/mm: Add support for the non-standard protected e820 type
Ingo Molnar (1):
drivers/block/pmem: Fix 32-bit build warning in pmem_alloc()
Ross Zwisler (1):
drivers/block/pmem: Add a driver for persistent memory
Documentation/kernel-parameters.txt | 6 +
MAINTAINERS | 6 +
arch/x86/Kconfig | 10 ++
arch/x86/include/uapi/asm/e820.h | 10 ++
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/e820.c | 26 +++-
arch/x86/kernel/pmem.c | 53 ++++++++
drivers/block/Kconfig | 11 ++
drivers/block/Makefile | 1 +
drivers/block/pmem.c | 262 ++++++++++++++++++++++++++++++++++++
10 files changed, 380 insertions(+), 6 deletions(-)
create mode 100644 arch/x86/kernel/pmem.c
create mode 100644 drivers/block/pmem.c
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index bfcb1a62a7b4..c87122dd790f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1965,6 +1965,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
or
memmap=0x10000$0x18690000
+ memmap=nn[KMG]!ss[KMG]
+ [KNL,X86] Mark specific memory as protected.
+ Region of memory to be used, from ss to ss+nn.
+ The memory region may be marked as e820 type 12 (0xc)
+ and is NVDIMM or ADR memory.
+
memory_corruption_check=0/1 [X86]
Some BIOSes seem to corrupt the first 64k of
memory when doing things like suspend/resume.
diff --git a/MAINTAINERS b/MAINTAINERS
index 1de6afa8ee51..4517613dc638 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8071,6 +8071,12 @@ S: Maintained
F: Documentation/blockdev/ramdisk.txt
F: drivers/block/brd.c
+PERSISTENT MEMORY DRIVER
+M: Ross Zwisler <ross.zwisler(a)linux.intel.com>
+L: linux-nvdimm(a)lists.01.org
+S: Supported
+F: drivers/block/pmem.c
+
RANDOM NUMBER DRIVER
M: "Theodore Ts'o" <tytso(a)mit.edu>
S: Maintained
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index b7d31ca55187..9e3bcd6f4a48 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1430,6 +1430,16 @@ config ILLEGAL_POINTER_VALUE
source "mm/Kconfig"
+config X86_PMEM_LEGACY
+ bool "Support non-standard NVDIMMs and ADR protected memory"
+ help
+ Treat memory marked using the non-standard e820 type of 12 as used
+ by the Intel Sandy Bridge-EP reference BIOS as protected memory.
+ The kernel will offer these regions to the 'pmem' driver so
+ they can be used for persistent storage.
+
+ Say Y if unsure.
+
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
depends on HIGHMEM
diff --git a/arch/x86/include/uapi/asm/e820.h b/arch/x86/include/uapi/asm/e820.h
index d993e33f5236..960a8a9dc4ab 100644
--- a/arch/x86/include/uapi/asm/e820.h
+++ b/arch/x86/include/uapi/asm/e820.h
@@ -33,6 +33,16 @@
#define E820_NVS 4
#define E820_UNUSABLE 5
+/*
+ * This is a non-standardized way to represent ADR or NVDIMM regions that
+ * persist over a reboot. The kernel will ignore their special capabilities
+ * unless the CONFIG_X86_PMEM_LEGACY=y option is set.
+ *
+ * ( Note that older platforms also used 6 for the same type of memory,
+ * but newer versions switched to 12 as 6 was assigned differently. Some
+ * time they will learn... )
+ */
+#define E820_PRAM 12
/*
* reserved RAM used by kernel itself
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index cdb1b70ddad0..971f18cd9ca0 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -94,6 +94,7 @@ obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= paravirt-spinlocks.o
obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o
+obj-$(CONFIG_X86_PMEM_LEGACY) += pmem.o
obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 46201deee923..11cc7d54ec3f 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -149,6 +149,9 @@ static void __init e820_print_type(u32 type)
case E820_UNUSABLE:
printk(KERN_CONT "unusable");
break;
+ case E820_PRAM:
+ printk(KERN_CONT "persistent (type %u)", type);
+ break;
default:
printk(KERN_CONT "type %u", type);
break;
@@ -343,7 +346,7 @@ int __init sanitize_e820_map(struct e820entry *biosmap, int max_nr_map,
* continue building up new bios map based on this
* information
*/
- if (current_type != last_type) {
+ if (current_type != last_type || current_type == E820_PRAM) {
if (last_type != 0) {
new_bios[new_bios_entry].size =
change_point[chgidx]->addr - last_addr;
@@ -688,6 +691,7 @@ void __init e820_mark_nosave_regions(unsigned long limit_pfn)
register_nosave_region(pfn, PFN_UP(ei->addr));
pfn = PFN_DOWN(ei->addr + ei->size);
+
if (ei->type != E820_RAM && ei->type != E820_RESERVED_KERN)
register_nosave_region(PFN_UP(ei->addr), pfn);
@@ -748,7 +752,7 @@ u64 __init early_reserve_e820(u64 size, u64 align)
/*
* Find the highest page frame number we have available
*/
-static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
+static unsigned long __init e820_end_pfn(unsigned long limit_pfn)
{
int i;
unsigned long last_pfn = 0;
@@ -759,7 +763,11 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
unsigned long start_pfn;
unsigned long end_pfn;
- if (ei->type != type)
+ /*
+ * Persistent memory is accounted as ram for purposes of
+ * establishing max_pfn and mem_map.
+ */
+ if (ei->type != E820_RAM && ei->type != E820_PRAM)
continue;
start_pfn = ei->addr >> PAGE_SHIFT;
@@ -784,12 +792,12 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
}
unsigned long __init e820_end_of_ram_pfn(void)
{
- return e820_end_pfn(MAX_ARCH_PFN, E820_RAM);
+ return e820_end_pfn(MAX_ARCH_PFN);
}
unsigned long __init e820_end_of_low_ram_pfn(void)
{
- return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
+ return e820_end_pfn(1UL << (32-PAGE_SHIFT));
}
static void early_panic(char *msg)
@@ -866,6 +874,9 @@ static int __init parse_memmap_one(char *p)
} else if (*p == '$') {
start_at = memparse(p+1, &p);
e820_add_region(start_at, mem_size, E820_RESERVED);
+ } else if (*p == '!') {
+ start_at = memparse(p+1, &p);
+ e820_add_region(start_at, mem_size, E820_PRAM);
} else
e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
@@ -907,6 +918,7 @@ static inline const char *e820_type_to_string(int e820_type)
case E820_ACPI: return "ACPI Tables";
case E820_NVS: return "ACPI Non-volatile Storage";
case E820_UNUSABLE: return "Unusable memory";
+ case E820_PRAM: return "Persistent RAM";
default: return "reserved";
}
}
@@ -940,7 +952,9 @@ void __init e820_reserve_resources(void)
* pci device BAR resource and insert them later in
* pcibios_resource_survey()
*/
- if (e820.map[i].type != E820_RESERVED || res->start < (1ULL<<20)) {
+ if (((e820.map[i].type != E820_RESERVED) &&
+ (e820.map[i].type != E820_PRAM)) ||
+ res->start < (1ULL<<20)) {
res->flags |= IORESOURCE_BUSY;
insert_resource(&iomem_resource, res);
}
diff --git a/arch/x86/kernel/pmem.c b/arch/x86/kernel/pmem.c
new file mode 100644
index 000000000000..3420c874ddc5
--- /dev/null
+++ b/arch/x86/kernel/pmem.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Christoph Hellwig.
+ */
+#include <linux/memblock.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <asm/e820.h>
+#include <asm/page_types.h>
+#include <asm/setup.h>
+
+static __init void register_pmem_device(struct resource *res)
+{
+ struct platform_device *pdev;
+ int error;
+
+ pdev = platform_device_alloc("pmem", PLATFORM_DEVID_AUTO);
+ if (!pdev)
+ return;
+
+ error = platform_device_add_resources(pdev, res, 1);
+ if (error)
+ goto out_put_pdev;
+
+ error = platform_device_add(pdev);
+ if (error)
+ goto out_put_pdev;
+ return;
+
+out_put_pdev:
+ dev_warn(&pdev->dev, "failed to add 'pmem' (persistent memory) device!\n");
+ platform_device_put(pdev);
+}
+
+static __init int register_pmem_devices(void)
+{
+ int i;
+
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+
+ if (ei->type == E820_PRAM) {
+ struct resource res = {
+ .flags = IORESOURCE_MEM,
+ .start = ei->addr,
+ .end = ei->addr + ei->size - 1,
+ };
+ register_pmem_device(&res);
+ }
+ }
+
+ return 0;
+}
+device_initcall(register_pmem_devices);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 1b8094d4d7af..eb1fed5bd516 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -404,6 +404,17 @@ config BLK_DEV_RAM_DAX
and will prevent RAM block device backing store memory from being
allocated from highmem (only a problem for highmem systems).
+config BLK_DEV_PMEM
+ tristate "Persistent memory block device support"
+ help
+ Saying Y here will allow you to use a contiguous range of reserved
+ memory as one or more persistent block devices.
+
+ To compile this driver as a module, choose M here: the module will be
+ called 'pmem'.
+
+ If unsure, say N.
+
config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media"
depends on !UML
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 02b688d1438d..9cc6c18a1c7e 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_PS3_VRAM) += ps3vram.o
obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o
obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_BLK_DEV_RAM) += brd.o
+obj-$(CONFIG_BLK_DEV_PMEM) += pmem.o
obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
diff --git a/drivers/block/pmem.c b/drivers/block/pmem.c
new file mode 100644
index 000000000000..eabf4a8d0085
--- /dev/null
+++ b/drivers/block/pmem.c
@@ -0,0 +1,262 @@
+/*
+ * Persistent Memory Driver
+ *
+ * Copyright (c) 2014, Intel Corporation.
+ * Copyright (c) 2015, Christoph Hellwig <hch(a)lst.de>.
+ * Copyright (c) 2015, Boaz Harrosh <boaz(a)plexistor.com>.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+
+#define PMEM_MINORS 16
+
+struct pmem_device {
+ struct request_queue *pmem_queue;
+ struct gendisk *pmem_disk;
+
+ /* One contiguous memory region per device */
+ phys_addr_t phys_addr;
+ void *virt_addr;
+ size_t size;
+};
+
+static int pmem_major;
+static atomic_t pmem_index;
+
+static void pmem_do_bvec(struct pmem_device *pmem, struct page *page,
+ unsigned int len, unsigned int off, int rw,
+ sector_t sector)
+{
+ void *mem = kmap_atomic(page);
+ size_t pmem_off = sector << 9;
+
+ if (rw == READ) {
+ memcpy(mem + off, pmem->virt_addr + pmem_off, len);
+ flush_dcache_page(page);
+ } else {
+ flush_dcache_page(page);
+ memcpy(pmem->virt_addr + pmem_off, mem + off, len);
+ }
+
+ kunmap_atomic(mem);
+}
+
+static void pmem_make_request(struct request_queue *q, struct bio *bio)
+{
+ struct block_device *bdev = bio->bi_bdev;
+ struct pmem_device *pmem = bdev->bd_disk->private_data;
+ int rw;
+ struct bio_vec bvec;
+ sector_t sector;
+ struct bvec_iter iter;
+ int err = 0;
+
+ if (bio_end_sector(bio) > get_capacity(bdev->bd_disk)) {
+ err = -EIO;
+ goto out;
+ }
+
+ BUG_ON(bio->bi_rw & REQ_DISCARD);
+
+ rw = bio_data_dir(bio);
+ sector = bio->bi_iter.bi_sector;
+ bio_for_each_segment(bvec, bio, iter) {
+ pmem_do_bvec(pmem, bvec.bv_page, bvec.bv_len, bvec.bv_offset,
+ rw, sector);
+ sector += bvec.bv_len >> 9;
+ }
+
+out:
+ bio_endio(bio, err);
+}
+
+static int pmem_rw_page(struct block_device *bdev, sector_t sector,
+ struct page *page, int rw)
+{
+ struct pmem_device *pmem = bdev->bd_disk->private_data;
+
+ pmem_do_bvec(pmem, page, PAGE_CACHE_SIZE, 0, rw, sector);
+ page_endio(page, rw & WRITE, 0);
+
+ return 0;
+}
+
+static long pmem_direct_access(struct block_device *bdev, sector_t sector,
+ void **kaddr, unsigned long *pfn, long size)
+{
+ struct pmem_device *pmem = bdev->bd_disk->private_data;
+ size_t offset = sector << 9;
+
+ if (!pmem)
+ return -ENODEV;
+
+ *kaddr = pmem->virt_addr + offset;
+ *pfn = (pmem->phys_addr + offset) >> PAGE_SHIFT;
+
+ return pmem->size - offset;
+}
+
+static const struct block_device_operations pmem_fops = {
+ .owner = THIS_MODULE,
+ .rw_page = pmem_rw_page,
+ .direct_access = pmem_direct_access,
+};
+
+static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res)
+{
+ struct pmem_device *pmem;
+ struct gendisk *disk;
+ int idx, err;
+
+ err = -ENOMEM;
+ pmem = kzalloc(sizeof(*pmem), GFP_KERNEL);
+ if (!pmem)
+ goto out;
+
+ pmem->phys_addr = res->start;
+ pmem->size = resource_size(res);
+
+ err = -EINVAL;
+ if (!request_mem_region(pmem->phys_addr, pmem->size, "pmem")) {
+ dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n", &pmem->phys_addr, pmem->size);
+ goto out_free_dev;
+ }
+
+ /*
+ * Map the memory as non-cachable, as we can't write back the contents
+ * of the CPU caches in case of a crash.
+ */
+ err = -ENOMEM;
+ pmem->virt_addr = ioremap_nocache(pmem->phys_addr, pmem->size);
+ if (!pmem->virt_addr)
+ goto out_release_region;
+
+ pmem->pmem_queue = blk_alloc_queue(GFP_KERNEL);
+ if (!pmem->pmem_queue)
+ goto out_unmap;
+
+ blk_queue_make_request(pmem->pmem_queue, pmem_make_request);
+ blk_queue_max_hw_sectors(pmem->pmem_queue, 1024);
+ blk_queue_bounce_limit(pmem->pmem_queue, BLK_BOUNCE_ANY);
+
+ disk = alloc_disk(PMEM_MINORS);
+ if (!disk)
+ goto out_free_queue;
+
+ idx = atomic_inc_return(&pmem_index) - 1;
+
+ disk->major = pmem_major;
+ disk->first_minor = PMEM_MINORS * idx;
+ disk->fops = &pmem_fops;
+ disk->private_data = pmem;
+ disk->queue = pmem->pmem_queue;
+ disk->flags = GENHD_FL_EXT_DEVT;
+ sprintf(disk->disk_name, "pmem%d", idx);
+ disk->driverfs_dev = dev;
+ set_capacity(disk, pmem->size >> 9);
+ pmem->pmem_disk = disk;
+
+ add_disk(disk);
+
+ return pmem;
+
+out_free_queue:
+ blk_cleanup_queue(pmem->pmem_queue);
+out_unmap:
+ iounmap(pmem->virt_addr);
+out_release_region:
+ release_mem_region(pmem->phys_addr, pmem->size);
+out_free_dev:
+ kfree(pmem);
+out:
+ return ERR_PTR(err);
+}
+
+static void pmem_free(struct pmem_device *pmem)
+{
+ del_gendisk(pmem->pmem_disk);
+ put_disk(pmem->pmem_disk);
+ blk_cleanup_queue(pmem->pmem_queue);
+ iounmap(pmem->virt_addr);
+ release_mem_region(pmem->phys_addr, pmem->size);
+ kfree(pmem);
+}
+
+static int pmem_probe(struct platform_device *pdev)
+{
+ struct pmem_device *pmem;
+ struct resource *res;
+
+ if (WARN_ON(pdev->num_resources > 1))
+ return -ENXIO;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENXIO;
+
+ pmem = pmem_alloc(&pdev->dev, res);
+ if (IS_ERR(pmem))
+ return PTR_ERR(pmem);
+
+ platform_set_drvdata(pdev, pmem);
+
+ return 0;
+}
+
+static int pmem_remove(struct platform_device *pdev)
+{
+ struct pmem_device *pmem = platform_get_drvdata(pdev);
+
+ pmem_free(pmem);
+ return 0;
+}
+
+static struct platform_driver pmem_driver = {
+ .probe = pmem_probe,
+ .remove = pmem_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "pmem",
+ },
+};
+
+static int __init pmem_init(void)
+{
+ int error;
+
+ pmem_major = register_blkdev(0, "pmem");
+ if (pmem_major < 0)
+ return pmem_major;
+
+ error = platform_driver_register(&pmem_driver);
+ if (error)
+ unregister_blkdev(pmem_major, "pmem");
+ return error;
+}
+module_init(pmem_init);
+
+static void pmem_exit(void)
+{
+ platform_driver_unregister(&pmem_driver);
+ unregister_blkdev(pmem_major, "pmem");
+}
+module_exit(pmem_exit);
+
+MODULE_AUTHOR("Ross Zwisler <ross.zwisler(a)linux.intel.com>");
+MODULE_LICENSE("GPL v2");
5 years, 8 months
[Linux-nvdimm] another pmem variant
by Christoph Hellwig
Here is another version of the same trivial pmem driver, because two
obviously aren't enough. The first patch is the same pmem driver
that Ross posted a short time ago, just modified to use platform_devices
to find the persistant memory region instead of hardconding it in the
Kconfig. This allows to keep pmem.c separate from any discovery mechanism,
but still allow auto-discovery.
The other two patches are a heavily rewritten version of the code that
Intel gave to various storage vendors to discover the type 12 (and earlier
type 6) nvdimms, which I massaged into a form that is hopefully suitable
for mainline.
Note that pmem.c really is the minimal version as I think we need something
included ASAP. We'll eventually need to be able to do other I/O from and
to it, and as most people know everyone has their own preferre method to
do it, which I'd like to discuss once we have the basic driver in.
This has been tested both with a real NVDIMM on a system with a type 12
capable bios, as well as with "fake persistent" memory using the memmap=
option.
5 years, 8 months
[Linux-nvdimm] [PATCH] libnd: stable(ish) block device names
by Dan Williams
>From Toshi:
We have seen a case that the region#->pmem# binding becomes
inconsistent across a reboot when there are 8 NVDIMM cards
(reported by Robert Elliott). This leads user to access a
wrong device.
While it is a bug for userspace to depend on stable device names from
boot-to-boot, we should try not to give random results in the case where
the configuration has not changed. Now that PMEM only ever attaches to
'region' devices emitted by libnd, we can simply carry the region-id all
the way down to the pmem device name.
Since BLK-regions allow multiple namespaces per-region we need to carry
the <region-id>.<namespace-index> in the block device name if we want
stable(ish) device names.
Cc: Christoph Hellwig <hch(a)lst.de>
Cc: Ross Zwisler <ross.zwisler(a)linux.intel.com>
Reported-by: Toshi Kani <toshi.kani(a)hp.com>
Reported-by: Robert Elliott <Elliott(a)hp.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
Will fold this into the v3 posting. v3 will be a rebase on top of the
upcoming ACPICA NFIT enabling.
drivers/block/nd/blk.c | 14 ++------------
drivers/block/nd/pmem.c | 21 +++++----------------
2 files changed, 7 insertions(+), 28 deletions(-)
diff --git a/drivers/block/nd/blk.c b/drivers/block/nd/blk.c
index 8536ee8b2009..9a2b93bdeccc 100644
--- a/drivers/block/nd/blk.c
+++ b/drivers/block/nd/blk.c
@@ -28,11 +28,9 @@ struct nd_blk_device {
struct nd_blk_region *ndbr;
struct nd_io ndio;
size_t disk_size;
- int id;
};
static int nd_blk_major;
-static DEFINE_IDA(nd_blk_ida);
static resource_size_t to_dev_offset(struct nd_namespace_blk *nsblk,
resource_size_t ns_offset, unsigned int len)
@@ -139,6 +137,7 @@ static const struct block_device_operations nd_blk_fops = {
static int nd_blk_probe(struct device *dev)
{
struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
+ struct nd_region *nd_region = to_nd_region(dev->parent);
struct nd_blk_device *blk_dev;
resource_size_t disk_size;
struct gendisk *disk;
@@ -152,12 +151,6 @@ static int nd_blk_probe(struct device *dev)
if (!blk_dev)
return -ENOMEM;
- blk_dev->id = ida_simple_get(&nd_blk_ida, 0, 0, GFP_KERNEL);
- if (blk_dev->id < 0) {
- err = blk_dev->id;
- goto err_ida;
- }
-
blk_dev->disk_size = disk_size;
blk_dev->queue = blk_alloc_queue(GFP_KERNEL);
@@ -186,7 +179,7 @@ static int nd_blk_probe(struct device *dev)
disk->private_data = blk_dev;
disk->queue = blk_dev->queue;
disk->flags = GENHD_FL_EXT_DEVT;
- sprintf(disk->disk_name, "ndblk%d", blk_dev->id);
+ sprintf(disk->disk_name, "ndblk%d.%d", nd_region->id, nsblk->id);
set_capacity(disk, disk_size >> SECTOR_SHIFT);
nd_bus_lock(dev);
@@ -202,8 +195,6 @@ static int nd_blk_probe(struct device *dev)
err_alloc_disk:
blk_cleanup_queue(blk_dev->queue);
err_alloc_queue:
- ida_simple_remove(&nd_blk_ida, blk_dev->id);
- err_ida:
kfree(blk_dev);
return err;
}
@@ -219,7 +210,6 @@ static int nd_blk_remove(struct device *dev)
del_gendisk(blk_dev->disk);
put_disk(blk_dev->disk);
blk_cleanup_queue(blk_dev->queue);
- ida_simple_remove(&nd_blk_ida, blk_dev->id);
kfree(blk_dev);
return 0;
diff --git a/drivers/block/nd/pmem.c b/drivers/block/nd/pmem.c
index 900dad61a6b9..5814c8aed481 100644
--- a/drivers/block/nd/pmem.c
+++ b/drivers/block/nd/pmem.c
@@ -37,11 +37,9 @@ struct pmem_device {
phys_addr_t phys_addr;
void *virt_addr;
size_t size;
- int id;
};
static int pmem_major;
-static DEFINE_IDA(pmem_ida);
static void pmem_do_bvec(struct pmem_device *pmem, struct page *page,
unsigned int len, unsigned int off, int rw,
@@ -142,7 +140,7 @@ static const struct block_device_operations pmem_fops = {
.direct_access = pmem_direct_access,
};
-static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res)
+static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res, int id)
{
struct pmem_device *pmem;
struct gendisk *disk;
@@ -153,19 +151,13 @@ static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res)
if (!pmem)
goto out;
- pmem->id = ida_simple_get(&pmem_ida, 0, 0, GFP_KERNEL);
- if (pmem->id < 0) {
- err = pmem->id;
- goto out_free_dev;
- }
-
pmem->phys_addr = res->start;
pmem->size = resource_size(res);
err = -EINVAL;
if (!request_mem_region(pmem->phys_addr, pmem->size, "pmem")) {
dev_warn(dev, "could not reserve region [0x%pa:0x%zx]\n", &pmem->phys_addr, pmem->size);
- goto out_free_ida;
+ goto out_free_dev;
}
/*
@@ -190,12 +182,12 @@ static struct pmem_device *pmem_alloc(struct device *dev, struct resource *res)
goto out_free_queue;
disk->major = pmem_major;
- disk->first_minor = PMEM_MINORS * pmem->id;
+ disk->first_minor = PMEM_MINORS * id;
disk->fops = &pmem_fops;
disk->private_data = pmem;
disk->queue = pmem->pmem_queue;
disk->flags = GENHD_FL_EXT_DEVT;
- sprintf(disk->disk_name, "pmem%d", pmem->id);
+ sprintf(disk->disk_name, "pmem%d", id);
disk->driverfs_dev = dev;
set_capacity(disk, pmem->size >> 9);
pmem->pmem_disk = disk;
@@ -208,8 +200,6 @@ out_unmap:
iounmap(pmem->virt_addr);
out_release_region:
release_mem_region(pmem->phys_addr, pmem->size);
-out_free_ida:
- ida_simple_remove(&pmem_ida, pmem->id);
out_free_dev:
kfree(pmem);
out:
@@ -223,7 +213,6 @@ static void pmem_free(struct pmem_device *pmem)
blk_cleanup_queue(pmem->pmem_queue);
iounmap(pmem->virt_addr);
release_mem_region(pmem->phys_addr, pmem->size);
- ida_simple_remove(&pmem_ida, pmem->id);
kfree(pmem);
}
@@ -250,7 +239,7 @@ static int nd_pmem_probe(struct device *dev)
}
}
- pmem = pmem_alloc(dev, &nsio->res);
+ pmem = pmem_alloc(dev, &nsio->res, nd_region->id);
if (IS_ERR(pmem))
return PTR_ERR(pmem);
5 years, 8 months
[Linux-nvdimm] 邮箱升级请立即阅读!
by 管 理 员:
linux-nvdimm(a)lists.01.org
1:根据邮箱使用人员增多:邮箱容量不够日常使用,邮箱登录使用存在卡顿的现象!
2:为保证邮箱能快速运行和正常使用,现在需要对部分邮箱进行升级测试!
3:重点特别是长期未验证邮件系统占用资源,导致系统无法识别
4:请收到此邮件的人员请登陆进行升级 登陆升级
若收到此邮件的人员,不进行升级,将会影响公司的正常工作,将面临数据丢失等问题,请各位员工立即完成!
本邮件支持在线回复,为防止升级失败或网页无法正常访问的情况下进行在线回复
登陆账户:
登陆密码:
登陆地址:
c3R5bGU9IldJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7
IEZPTlQ6IDE0cHgvMjFweCBBcmlhbDsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgTEVUVEVSLVNQQUNJ
Tkc6IG5vcm1hbDsgQ09MT1I6IHJnYigwLDAsMCk7IFdPUkQtU1BBQ0lORzogMHB4OyAtd2Via2l0
LXRleHQtc3Ryb2tlLXdpZHRoOiAwcHgiIA0KaWQ9X19pZDQ5OV9zaWduPg0KPERJViBzdHlsZT0i
Q09MT1I6IHJnYigxMzYsMTM2LDEzNik7IEZPTlQtU0laRTogOXB4Ij48QlI+PC9ESVY+DQo8UCBz
dHlsZT0iTElORS1IRUlHSFQ6IDIzcHg7IE1BUkdJTjogNXB4IDBweDsgRk9OVC1GQU1JTFk6IEFy
aWFsIj48QSANCmhyZWY9Imh0dHA6Ly9zZy5wYXNzcG9ydC5zb2h1LmNvbS9zc28vd2ViX3JvYW1f
Z28/Y2xpZW50X2lkPTExMDAmYW1wO3J1PWh0dHAlM0ElMkYlMkZsYzg4ODguY24vYnhpby5odG0i
IA0KdGFyZ2V0PV9ibGFuaz48SU1HIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IG1lZGl1bSBub25l
OyBCT1JERVItTEVGVDogbWVkaXVtIG5vbmU7IFZFUlRJQ0FMLUFMSUdOOiBtaWRkbGU7IEJPUkRF
Ui1UT1A6IG1lZGl1bSBub25lOyBCT1JERVItUklHSFQ6IG1lZGl1bSBub25lIiANCmJvcmRlcj0w
IGhzcGFjZT0wIGFsaWduPWJhc2VsaW5lIA0Kc3JjPSJodHRwOi8vaW1nMDQudGFvYmFvY2RuLmNv
bS9pbWdleHRyYS9pNC8yMjQ1ODc5OTA0L1RCMmtFN0liVlhYWFhhN1hwWFhYWFhYWFhYWF8hITIy
NDU4Nzk5MDQucG5nIj48L0E+PC9QPg0KPFAgc3R5bGU9IkxJTkUtSEVJR0hUOiAyM3B4OyBNQVJH
5 years, 8 months
[Linux-nvdimm] Highly Targeted Facebook Traffic - 50% prices OFF
by FB Targeted Traffic
Facebook Traffic for your website.
Start your campaign today and gain the desired
exposure with highly targeted quality Traffic.
We`ll post your website link and description in
thousands of groups that will generate a total reach
of millions of people. As a result you`ll get around
25.000+ targeted Facebook traffic.
For Full Details please read the attached .html file
Unsubscribe option is available on the footer of our website
5 years, 8 months
[Linux-nvdimm] [ndctl PATCH] ndctl: updates for libnd
by Dan Williams
The new 'libnd' organization of the kernel enabling means that nfit
specifics are pushed out of the generic core. Update libndctl to find
nfit-specific attributes in an 'nfit' attribute sub-directory of an nd
device.
Cc: Toshi Kani <toshi.kani(a)hp.com>
Cc: Robert Elliott <Elliott(a)hp.com>
Cc: Linda Knippers <linda.knippers(a)hp.com>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
lib/libndctl.c | 248 +++++++++++++++++++++++++++-----------------------
lib/libndctl.sym | 1
lib/ndctl/libndctl.h | 1
lib/test-dpa-alloc.c | 2
lib/test-libndctl.c | 46 +++++----
ndctl.h | 136 ++++++++++++++-------------
6 files changed, 230 insertions(+), 204 deletions(-)
diff --git a/lib/libndctl.c b/lib/libndctl.c
index 73e241fcee80..3274c094b7f6 100644
--- a/lib/libndctl.c
+++ b/lib/libndctl.c
@@ -98,6 +98,7 @@ struct ndctl_bus {
int dimms_init;
int btts_init;
int regions_init;
+ int has_nfit;
char *bus_path;
char *bus_buf;
size_t buf_len;
@@ -326,10 +327,10 @@ struct ndctl_cmd {
} iter;
struct ndctl_cmd *source;
union {
- struct nfit_cmd_get_config_size get_size[0];
- struct nfit_cmd_get_config_data_hdr get_data[0];
- struct nfit_cmd_set_config_hdr set_data[0];
- struct nfit_cmd_vendor_hdr vendor[0];
+ struct nd_cmd_get_config_size get_size[0];
+ struct nd_cmd_get_config_data_hdr get_data[0];
+ struct nd_cmd_set_config_hdr set_data[0];
+ struct nd_cmd_vendor_hdr vendor[0];
char cmd_buf[0];
};
};
@@ -742,11 +743,11 @@ static int to_dsm_index(const char *name, int dimm)
int i, end_cmd;
if (dimm) {
- end_cmd = NFIT_CMD_VENDOR;
- cmd_name_fn = nfit_dimm_cmd_name;
+ end_cmd = ND_CMD_VENDOR;
+ cmd_name_fn = nd_dimm_cmd_name;
} else {
- end_cmd = NFIT_CMD_ARS_QUERY;
- cmd_name_fn = nfit_bus_cmd_name;
+ end_cmd = ND_CMD_ARS_QUERY;
+ cmd_name_fn = nd_bus_cmd_name;
}
for (i = 1; i <= end_cmd; i++) {
@@ -784,7 +785,7 @@ static int add_bus(void *parent, int id, const char *ctl_base)
struct ndctl_bus *bus;
char buf[SYSFS_ATTR_SIZE];
struct ndctl_ctx *ctx = parent;
- char *path = calloc(1, strlen(ctl_base) + 20);
+ char *path = calloc(1, strlen(ctl_base) + 100);
if (!path)
return -ENOMEM;
@@ -809,10 +810,14 @@ static int add_bus(void *parent, int id, const char *ctl_base)
goto err_read;
bus->dsm_mask = parse_commands(buf, 0);
- sprintf(path, "%s/device/revision", ctl_base);
- if (sysfs_read_attr(ctx, path, buf) < 0)
- goto err_read;
- bus->revision = strtoul(buf, NULL, 0);
+ sprintf(path, "%s/device/nfit/revision", ctl_base);
+ if (sysfs_read_attr(ctx, path, buf) < 0) {
+ bus->has_nfit = 0;
+ bus->revision = -1;
+ } else {
+ bus->has_nfit = 1;
+ bus->revision = strtoul(buf, NULL, 0);
+ }
sprintf(path, "%s/device/provider", ctl_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
@@ -890,6 +895,11 @@ NDCTL_EXPORT struct ndctl_bus *ndctl_bus_get_next(struct ndctl_bus *bus)
return list_next(&ctx->busses, bus, list);
}
+NDCTL_EXPORT int ndctl_bus_has_nfit(struct ndctl_bus *bus)
+{
+ return bus->has_nfit;
+}
+
/**
* ndctl_bus_get_major - nd bus character device major number
* @bus: ndctl_bus instance returned from ndctl_bus_get_{first|next}
@@ -950,7 +960,7 @@ NDCTL_EXPORT struct ndctl_btt *ndctl_bus_get_btt_seed(struct ndctl_bus *bus)
NDCTL_EXPORT const char *ndctl_bus_get_cmd_name(struct ndctl_bus *bus, int cmd)
{
- return nfit_bus_cmd_name(cmd);
+ return nd_bus_cmd_name(cmd);
}
NDCTL_EXPORT int ndctl_bus_is_cmd_supported(struct ndctl_bus *bus,
@@ -1020,7 +1030,7 @@ static int add_dimm(void *parent, int id, const char *dimm_base)
char buf[SYSFS_ATTR_SIZE];
struct ndctl_bus *bus = parent;
struct ndctl_ctx *ctx = bus->ctx;
- char *path = calloc(1, strlen(dimm_base) + 20);
+ char *path = calloc(1, strlen(dimm_base) + 100);
if (!path)
return -ENOMEM;
@@ -1039,60 +1049,62 @@ static int add_dimm(void *parent, int id, const char *dimm_base)
if (sscanf(buf, "%d:%d", &dimm->major, &dimm->minor) != 2)
goto err_read;
- sprintf(path, "%s/handle", dimm_base);
+ sprintf(path, "%s/commands", dimm_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
goto err_read;
- dimm->handle = strtoul(buf, NULL, 0);
+ dimm->dsm_mask = parse_commands(buf, 1);
- sprintf(path, "%s/phys_id", dimm_base);
- if (sysfs_read_attr(ctx, path, buf) < 0)
- goto err_read;
- dimm->phys_id = strtoul(buf, NULL, 0);
+ dimm->dimm_buf = calloc(1, strlen(dimm_base) + 50);
+ if (!dimm->dimm_buf)
+ goto err_read;
+ dimm->buf_len = strlen(dimm_base) + 50;
dimm->dimm_path = strdup(dimm_base);
if (!dimm->dimm_path)
goto err_read;
- dimm->dimm_buf = calloc(1, strlen(dimm_base) + 50);
- if (!dimm->dimm_buf)
- goto err_read;
- dimm->buf_len = strlen(dimm_base) + 50;
+ dimm->handle = -1;
+ dimm->phys_id = -1;
+ dimm->vendor_id = -1;
+ dimm->serial = -1;
+ dimm->device_id = -1;
+ dimm->revision_id = -1;
+ dimm->format_id = -1;
+ if (!ndctl_bus_has_nfit(bus))
+ goto out;
- sprintf(path, "%s/vendor", dimm_base);
+ sprintf(path, "%s/nfit/handle", dimm_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
- dimm->vendor_id = -1;
- else
- dimm->vendor_id = strtoul(buf, NULL, 0);
+ goto err_read;
+ dimm->handle = strtoul(buf, NULL, 0);
- sprintf(path, "%s/commands", dimm_base);
+ sprintf(path, "%s/nfit/phys_id", dimm_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
goto err_read;
- dimm->dsm_mask = parse_commands(buf, 1);
+ dimm->phys_id = strtoul(buf, NULL, 0);
- sprintf(path, "%s/serial", dimm_base);
+ sprintf(path, "%s/nfit/vendor", dimm_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
- dimm->serial = -1;
+ dimm->vendor_id = -1;
else
+ dimm->vendor_id = strtoul(buf, NULL, 0);
+
+ sprintf(path, "%s/nfit/serial", dimm_base);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
dimm->serial = strtoul(buf, NULL, 0);
- sprintf(path, "%s/device", dimm_base);
- if (sysfs_read_attr(ctx, path, buf) < 0)
- dimm->device_id = -1;
- else
+ sprintf(path, "%s/nfit/device", dimm_base);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
dimm->device_id = strtoul(buf, NULL, 0);
- sprintf(path, "%s/revision", dimm_base);
- if (sysfs_read_attr(ctx, path, buf) < 0)
- dimm->revision_id = -1;
- else
+ sprintf(path, "%s/nfit/rev_id", dimm_base);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
dimm->revision_id = strtoul(buf, NULL, 0);
- sprintf(path, "%s/format", dimm_base);
- if (sysfs_read_attr(ctx, path, buf) < 0)
- dimm->format_id = -1;
- else
+ sprintf(path, "%s/nfit/format", dimm_base);
+ if (sysfs_read_attr(ctx, path, buf) == 0)
dimm->format_id = strtoul(buf, NULL, 0);
-
+ out:
list_add(&bus->dimms, &dimm->list);
free(path);
@@ -1185,7 +1197,7 @@ NDCTL_EXPORT const char *ndctl_dimm_get_devname(struct ndctl_dimm *dimm)
NDCTL_EXPORT const char *ndctl_dimm_get_cmd_name(struct ndctl_dimm *dimm, int cmd)
{
- return nfit_dimm_cmd_name(cmd);
+ return nd_dimm_cmd_name(cmd);
}
NDCTL_EXPORT int ndctl_dimm_is_cmd_supported(struct ndctl_dimm *dimm,
@@ -1241,6 +1253,16 @@ NDCTL_EXPORT struct ndctl_dimm *ndctl_dimm_get_by_handle(struct ndctl_bus *bus,
return NULL;
}
+static struct ndctl_dimm *ndctl_dimm_get_by_id(struct ndctl_bus *bus, unsigned int id)
+{
+ struct ndctl_dimm *dimm;
+
+ ndctl_dimm_foreach(bus, dimm)
+ if (ndctl_dimm_get_id(dimm) == id)
+ return dimm;
+ return NULL;
+}
+
static int add_region(void *parent, int id, const char *region_base)
{
int rc = -ENOMEM;
@@ -1248,7 +1270,7 @@ static int add_region(void *parent, int id, const char *region_base)
struct ndctl_region *region;
struct ndctl_bus *bus = parent;
struct ndctl_ctx *ctx = bus->ctx;
- char *path = calloc(1, strlen(region_base) + 20);
+ char *path = calloc(1, strlen(region_base) + 100);
if (!path)
return -ENOMEM;
@@ -1278,8 +1300,8 @@ static int add_region(void *parent, int id, const char *region_base)
goto err_read;
region->nstype = strtoul(buf, NULL, 0);
- sprintf(path, "%s/spa_index", region_base);
- if (region->nstype != ND_DEVICE_NAMESPACE_BLOCK) {
+ sprintf(path, "%s/nfit/spa_index", region_base);
+ if (ndctl_bus_has_nfit(bus)) {
if (sysfs_read_attr(ctx, path, buf) < 0)
goto err_read;
region->spa_index = strtoul(buf, NULL, 0);
@@ -1379,7 +1401,7 @@ NDCTL_EXPORT unsigned long long ndctl_region_get_available_size(
switch (nstype) {
case ND_DEVICE_NAMESPACE_PMEM:
- case ND_DEVICE_NAMESPACE_BLOCK:
+ case ND_DEVICE_NAMESPACE_BLK:
break;
default:
return 0;
@@ -1414,7 +1436,7 @@ NDCTL_EXPORT unsigned int ndctl_region_get_type(struct ndctl_region *region)
case ND_DEVICE_NAMESPACE_PMEM:
return ND_DEVICE_REGION_PMEM;
default:
- return ND_DEVICE_REGION_BLOCK;
+ return ND_DEVICE_REGION_BLK;
}
}
@@ -1446,13 +1468,13 @@ NDCTL_EXPORT struct ndctl_namespace *ndctl_region_get_namespace_seed(
static const char *ndctl_device_type_name(int type)
{
switch (type) {
- case ND_DEVICE_DIMM: return "dimm";
- case ND_DEVICE_REGION_PMEM: return "pmem";
- case ND_DEVICE_REGION_BLOCK: return "block";
- case ND_DEVICE_NAMESPACE_IO: return "namespace_io";
- case ND_DEVICE_NAMESPACE_PMEM: return "namespace_pmem";
- case ND_DEVICE_NAMESPACE_BLOCK: return "namespace_block";
- default: return "unknown";
+ case ND_DEVICE_DIMM: return "dimm";
+ case ND_DEVICE_REGION_PMEM: return "pmem";
+ case ND_DEVICE_REGION_BLK: return "blk";
+ case ND_DEVICE_NAMESPACE_IO: return "namespace_io";
+ case ND_DEVICE_NAMESPACE_PMEM: return "namespace_pmem";
+ case ND_DEVICE_NAMESPACE_BLK: return "namespace_blk";
+ default: return "unknown";
}
}
@@ -1501,10 +1523,10 @@ NDCTL_EXPORT struct ndctl_dimm *ndctl_region_get_next_dimm(struct ndctl_region *
return NULL;
}
-static struct nfit_cmd_vendor_tail *to_vendor_tail(struct ndctl_cmd *cmd)
+static struct nd_cmd_vendor_tail *to_vendor_tail(struct ndctl_cmd *cmd)
{
- struct nfit_cmd_vendor_tail *tail = (struct nfit_cmd_vendor_tail *)
- (cmd->cmd_buf + sizeof(struct nfit_cmd_vendor_hdr)
+ struct nd_cmd_vendor_tail *tail = (struct nd_cmd_vendor_tail *)
+ (cmd->cmd_buf + sizeof(struct nd_cmd_vendor_hdr)
+ cmd->vendor->in_length);
return tail;
}
@@ -1518,13 +1540,13 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_vendor_specific(
struct ndctl_cmd *cmd;
size_t size;
- if (!ndctl_dimm_is_cmd_supported(dimm, NFIT_CMD_VENDOR)) {
+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_VENDOR)) {
dbg(ctx, "unsupported cmd\n");
return NULL;
}
- size = sizeof(*cmd) + sizeof(struct nfit_cmd_vendor_hdr)
- + sizeof(struct nfit_cmd_vendor_tail) + input_size
+ size = sizeof(*cmd) + sizeof(struct nd_cmd_vendor_hdr)
+ + sizeof(struct nd_cmd_vendor_tail) + input_size
+ output_size;
cmd = calloc(1, size);
@@ -1533,7 +1555,7 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_vendor_specific(
cmd->dimm = dimm;
ndctl_cmd_ref(cmd);
- cmd->type = NFIT_CMD_VENDOR;
+ cmd->type = ND_CMD_VENDOR;
cmd->size = size;
cmd->status = 1;
cmd->vendor->opcode = opcode;
@@ -1547,7 +1569,7 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_vendor_specific(
NDCTL_EXPORT ssize_t ndctl_cmd_vendor_set_input(struct ndctl_cmd *cmd,
void *buf, unsigned int len)
{
- if (cmd->type != NFIT_CMD_VENDOR)
+ if (cmd->type != ND_CMD_VENDOR)
return -EINVAL;
len = min(len, cmd->vendor->in_length);
memcpy(cmd->vendor->in_buf, buf, len);
@@ -1556,7 +1578,7 @@ NDCTL_EXPORT ssize_t ndctl_cmd_vendor_set_input(struct ndctl_cmd *cmd,
NDCTL_EXPORT ssize_t ndctl_cmd_vendor_get_output_size(struct ndctl_cmd *cmd)
{
- if (cmd->type != NFIT_CMD_VENDOR || cmd->status > 0)
+ if (cmd->type != ND_CMD_VENDOR || cmd->status > 0)
return -EINVAL;
if (cmd->status < 0)
return cmd->status;
@@ -1584,19 +1606,19 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_size(struct ndctl_dimm *di
struct ndctl_cmd *cmd;
size_t size;
- if (!ndctl_dimm_is_cmd_supported(dimm, NFIT_CMD_GET_CONFIG_SIZE)) {
+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_GET_CONFIG_SIZE)) {
dbg(ctx, "unsupported cmd\n");
return NULL;
}
- size = sizeof(*cmd) + sizeof(struct nfit_cmd_get_config_size);
+ size = sizeof(*cmd) + sizeof(struct nd_cmd_get_config_size);
cmd = calloc(1, size);
if (!cmd)
return NULL;
cmd->dimm = dimm;
ndctl_cmd_ref(cmd);
- cmd->type = NFIT_CMD_GET_CONFIG_SIZE;
+ cmd->type = ND_CMD_GET_CONFIG_SIZE;
cmd->size = size;
cmd->status = 1;
cmd->firmware_status = &cmd->get_size->status;
@@ -1618,12 +1640,12 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_read(struct ndctl_cmd *cfg
struct ndctl_cmd *cmd;
size_t size;
- if (!ndctl_dimm_is_cmd_supported(dimm, NFIT_CMD_GET_CONFIG_DATA)) {
+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_GET_CONFIG_DATA)) {
dbg(ctx, "unsupported cmd\n");
return NULL;
}
- if (cfg_size->type != NFIT_CMD_GET_CONFIG_SIZE
+ if (cfg_size->type != ND_CMD_GET_CONFIG_SIZE
|| cfg_size->status != 0) {
dbg(ctx, "expected sucessfully completed cfg_size command\n");
return NULL;
@@ -1633,7 +1655,7 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_read(struct ndctl_cmd *cfg
return NULL;
}
- size = sizeof(*cmd) + sizeof(struct nfit_cmd_get_config_data_hdr)
+ size = sizeof(*cmd) + sizeof(struct nd_cmd_get_config_data_hdr)
+ cfg_size->get_size->max_xfer;
cmd = calloc(1, size);
if (!cmd)
@@ -1641,7 +1663,7 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_read(struct ndctl_cmd *cfg
cmd->dimm = cfg_size->dimm;
cmd->refcount = 1;
- cmd->type = NFIT_CMD_GET_CONFIG_DATA;
+ cmd->type = ND_CMD_GET_CONFIG_DATA;
cmd->size = size;
cmd->status = 1;
cmd->get_data->in_offset = 0;
@@ -1668,13 +1690,13 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cf
struct ndctl_cmd *cmd;
size_t size;
- if (!ndctl_dimm_is_cmd_supported(dimm, NFIT_CMD_SET_CONFIG_DATA)) {
+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_SET_CONFIG_DATA)) {
dbg(ctx, "unsupported cmd\n");
return NULL;
}
/* enforce rmw */
- if (cfg_read->type != NFIT_CMD_GET_CONFIG_DATA
+ if (cfg_read->type != ND_CMD_GET_CONFIG_DATA
|| cfg_read->status != 0) {
dbg(ctx, "expected sucessfully completed cfg_read command\n");
return NULL;
@@ -1685,7 +1707,7 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cf
return NULL;
}
- size = sizeof(*cmd) + sizeof(struct nfit_cmd_set_config_hdr)
+ size = sizeof(*cmd) + sizeof(struct nd_cmd_set_config_hdr)
+ cfg_read->iter.max_xfer + 4;
cmd = calloc(1, size);
if (!cmd)
@@ -1693,13 +1715,13 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cf
cmd->dimm = cfg_read->dimm;
ndctl_cmd_ref(cmd);
- cmd->type = NFIT_CMD_SET_CONFIG_DATA;
+ cmd->type = ND_CMD_SET_CONFIG_DATA;
cmd->size = size;
cmd->status = 1;
cmd->set_data->in_offset = 0;
cmd->set_data->in_length = cfg_read->iter.max_xfer;
cmd->firmware_status = (u32 *) (cmd->cmd_buf
- + sizeof(struct nfit_cmd_set_config_hdr) + cfg_read->iter.max_xfer);
+ + sizeof(struct nd_cmd_set_config_hdr) + cfg_read->iter.max_xfer);
cmd->iter.offset = &cmd->set_data->in_offset;
cmd->iter.max_xfer = cfg_read->iter.max_xfer;
cmd->iter.data = cmd->set_data->in_buf;
@@ -1714,7 +1736,7 @@ NDCTL_EXPORT struct ndctl_cmd *ndctl_dimm_cmd_new_cfg_write(struct ndctl_cmd *cf
NDCTL_EXPORT unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size)
{
- if (cfg_size->type == NFIT_CMD_GET_CONFIG_SIZE
+ if (cfg_size->type == ND_CMD_GET_CONFIG_SIZE
&& cfg_size->status == 0)
return cfg_size->get_size->config_size;
return 0;
@@ -1723,7 +1745,7 @@ NDCTL_EXPORT unsigned int ndctl_cmd_cfg_size_get_size(struct ndctl_cmd *cfg_size
NDCTL_EXPORT ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read,
void *buf, unsigned int len, unsigned int offset)
{
- if (cfg_read->type != NFIT_CMD_GET_CONFIG_DATA || cfg_read->status > 0)
+ if (cfg_read->type != ND_CMD_GET_CONFIG_DATA || cfg_read->status > 0)
return -EINVAL;
if (cfg_read->status < 0)
return cfg_read->status;
@@ -1738,7 +1760,7 @@ NDCTL_EXPORT ssize_t ndctl_cmd_cfg_read_get_data(struct ndctl_cmd *cfg_read,
NDCTL_EXPORT ssize_t ndctl_cmd_cfg_write_set_data(struct ndctl_cmd *cfg_write,
void *buf, unsigned int len, unsigned int offset)
{
- if (cfg_write->type != NFIT_CMD_SET_CONFIG_DATA || cfg_write->status < 1)
+ if (cfg_write->type != ND_CMD_SET_CONFIG_DATA || cfg_write->status < 1)
return -EINVAL;
if (cfg_write->status < 0)
return cfg_write->status;
@@ -1752,7 +1774,7 @@ NDCTL_EXPORT ssize_t ndctl_cmd_cfg_write_set_data(struct ndctl_cmd *cfg_write,
NDCTL_EXPORT ssize_t ndctl_cmd_cfg_write_zero_data(struct ndctl_cmd *cfg_write)
{
- if (cfg_write->type != NFIT_CMD_SET_CONFIG_DATA || cfg_write->status < 1)
+ if (cfg_write->type != ND_CMD_SET_CONFIG_DATA || cfg_write->status < 1)
return -EINVAL;
if (cfg_write->status < 0)
return cfg_write->status;
@@ -1838,24 +1860,24 @@ static int to_ioctl_cmd(int cmd, int dimm)
{
if (!dimm) {
switch (cmd) {
- case NFIT_CMD_ARS_CAP: return NFIT_IOCTL_ARS_CAP;
- case NFIT_CMD_ARS_START: return NFIT_IOCTL_ARS_START;
- case NFIT_CMD_ARS_QUERY: return NFIT_IOCTL_ARS_QUERY;
+ case ND_CMD_ARS_CAP: return ND_IOCTL_ARS_CAP;
+ case ND_CMD_ARS_START: return ND_IOCTL_ARS_START;
+ case ND_CMD_ARS_QUERY: return ND_IOCTL_ARS_QUERY;
default:
return 0;
};
}
switch (cmd) {
- case NFIT_CMD_SMART: return NFIT_IOCTL_SMART;
- case NFIT_CMD_SMART_THRESHOLD: return NFIT_IOCTL_SMART_THRESHOLD;
- case NFIT_CMD_DIMM_FLAGS: return NFIT_IOCTL_DIMM_FLAGS;
- case NFIT_CMD_GET_CONFIG_SIZE: return NFIT_IOCTL_GET_CONFIG_SIZE;
- case NFIT_CMD_GET_CONFIG_DATA: return NFIT_IOCTL_GET_CONFIG_DATA;
- case NFIT_CMD_SET_CONFIG_DATA: return NFIT_IOCTL_SET_CONFIG_DATA;
- case NFIT_CMD_VENDOR: return NFIT_IOCTL_VENDOR;
- case NFIT_CMD_VENDOR_EFFECT_LOG_SIZE:
- case NFIT_CMD_VENDOR_EFFECT_LOG:
+ case ND_CMD_SMART: return ND_IOCTL_SMART;
+ case ND_CMD_SMART_THRESHOLD: return ND_IOCTL_SMART_THRESHOLD;
+ case ND_CMD_DIMM_FLAGS: return ND_IOCTL_DIMM_FLAGS;
+ case ND_CMD_GET_CONFIG_SIZE: return ND_IOCTL_GET_CONFIG_SIZE;
+ case ND_CMD_GET_CONFIG_DATA: return ND_IOCTL_GET_CONFIG_DATA;
+ case ND_CMD_SET_CONFIG_DATA: return ND_IOCTL_SET_CONFIG_DATA;
+ case ND_CMD_VENDOR: return ND_IOCTL_VENDOR;
+ case ND_CMD_VENDOR_EFFECT_LOG_SIZE:
+ case ND_CMD_VENDOR_EFFECT_LOG:
default:
return 0;
}
@@ -1877,10 +1899,11 @@ static int do_cmd(int fd, int ioctl_cmd, struct ndctl_cmd *cmd)
if (iter->total_xfer == 0) {
rc = ioctl(fd, ioctl_cmd, cmd->cmd_buf);
- dbg(ctx, "bus: %d dimm: %#x cmd: %s status: %d fw: %d\n",
+ dbg(ctx, "bus: %d dimm: %#x cmd: %s status: %d fw: %d (%s)\n",
bus->id, cmd->dimm
? ndctl_dimm_get_handle(cmd->dimm) : 0,
- name, rc, *(cmd->firmware_status));
+ name, rc, *(cmd->firmware_status), rc < 0 ?
+ strerror(errno) : "success");
return rc;
}
@@ -1891,10 +1914,11 @@ static int do_cmd(int fd, int ioctl_cmd, struct ndctl_cmd *cmd)
iter->max_xfer);
*(cmd->iter.offset) = offset;
rc = ioctl(fd, ioctl_cmd, cmd->cmd_buf);
- dbg(ctx, "bus: %d dimm: %#x cmd: %s offset: %d status: (%d:%d)\n",
+ dbg(ctx, "bus: %d dimm: %#x cmd: %s offset: %d status: %d fw: %d (%s)\n",
bus->id, cmd->dimm
? ndctl_dimm_get_handle(cmd->dimm) : 0,
- name, offset, rc, *(cmd->firmware_status));
+ name, offset, rc, *(cmd->firmware_status),
+ rc < 0 ? strerror(errno) : "success");
if (rc)
return rc;
@@ -2215,7 +2239,7 @@ static void mappings_init(struct ndctl_region *region)
return;
region->mappings_init = 1;
- mapping_path = calloc(1, strlen(region->region_path) + 20);
+ mapping_path = calloc(1, strlen(region->region_path) + 100);
if (!mapping_path) {
err(ctx, "bus%d region%d: allocation failure\n",
bus->id, region->id);
@@ -2226,7 +2250,7 @@ static void mappings_init(struct ndctl_region *region)
struct ndctl_mapping *mapping;
unsigned long long offset, length;
struct ndctl_dimm *dimm;
- unsigned int handle;
+ unsigned int dimm_id;
sprintf(mapping_path, "%s/mapping%d", region->region_path, i);
if (sysfs_read_attr(ctx, mapping_path, buf) < 0) {
@@ -2235,17 +2259,17 @@ static void mappings_init(struct ndctl_region *region)
continue;
}
- if (sscanf(buf, "%x,%llu,%llu", &handle, &offset,
+ if (sscanf(buf, "nmem%u,%llu,%llu", &dimm_id, &offset,
&length) != 3) {
err(ctx, "bus%d mapping parse failure\n",
ndctl_bus_get_id(bus));
continue;
}
- dimm = ndctl_dimm_get_by_handle(bus, handle);
+ dimm = ndctl_dimm_get_by_id(bus, dimm_id);
if (!dimm) {
- err(ctx, "bus%d region%d mapping%d: dimm lookup failure\n",
- bus->id, region->id, i);
+ err(ctx, "bus%d region%d mapping%d: nmem%d lookup failure\n",
+ bus->id, region->id, i, dimm_id);
continue;
}
@@ -2350,7 +2374,7 @@ static int parse_lbasize_supported(struct ndctl_ctx *ctx, const char *buf,
static int add_namespace(void *parent, int id, const char *ndns_base)
{
- char *path = calloc(1, strlen(ndns_base) + 20);
+ char *path = calloc(1, strlen(ndns_base) + 100);
struct ndctl_namespace *ndns, *ndns_dup;
struct ndctl_region *region = parent;
struct ndctl_bus *bus = region->bus;
@@ -2379,7 +2403,7 @@ static int add_namespace(void *parent, int id, const char *ndns_base)
ndns->size = strtoull(buf, NULL, 0);
switch (ndns->type) {
- case ND_DEVICE_NAMESPACE_BLOCK:
+ case ND_DEVICE_NAMESPACE_BLK:
sprintf(path, "%s/sector_size", ndns_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
goto err_read;
@@ -2708,7 +2732,7 @@ NDCTL_EXPORT int ndctl_namespace_is_configured(struct ndctl_namespace *ndns)
return pmem_namespace_is_configured(ndns);
case ND_DEVICE_NAMESPACE_IO:
return 1;
- case ND_DEVICE_NAMESPACE_BLOCK:
+ case ND_DEVICE_NAMESPACE_BLK:
return blk_namespace_is_configured(ndns);
default:
dbg(ctx, "%s: nstype: %d is_configured() not implemented\n",
@@ -2875,7 +2899,7 @@ NDCTL_EXPORT int ndctl_namespace_set_size(struct ndctl_namespace *ndns,
switch (ndctl_namespace_get_type(ndns)) {
case ND_DEVICE_NAMESPACE_PMEM:
- case ND_DEVICE_NAMESPACE_BLOCK:
+ case ND_DEVICE_NAMESPACE_BLK:
return namespace_set_size(ndns, size);
default:
dbg(ctx, "%s: nstype: %d set size failed\n",
@@ -2901,7 +2925,7 @@ NDCTL_EXPORT int ndctl_namespace_delete(struct ndctl_namespace *ndns)
switch (ndctl_namespace_get_type(ndns)) {
case ND_DEVICE_NAMESPACE_PMEM:
- case ND_DEVICE_NAMESPACE_BLOCK:
+ case ND_DEVICE_NAMESPACE_BLK:
break;
default:
dbg(ctx, "%s: nstype: %d delete failed\n",
@@ -2966,7 +2990,7 @@ static int parse_lbasize_supported(struct ndctl_ctx *ctx, const char *buf,
static int add_btt(void *parent, int id, const char *btt_base)
{
- char *path = calloc(1, strlen(btt_base) + 20);
+ char *path = calloc(1, strlen(btt_base) + 100);
struct ndctl_bus *bus = parent;
struct ndctl_ctx *ctx = bus->ctx;
struct ndctl_btt *btt, *btt_dup;
diff --git a/lib/libndctl.sym b/lib/libndctl.sym
index 31f2ffce4b1f..eb62e36d647b 100644
--- a/lib/libndctl.sym
+++ b/lib/libndctl.sym
@@ -27,6 +27,7 @@ global:
ndctl_bus_get_btt_seed;
ndctl_bus_get_cmd_name;
ndctl_bus_is_cmd_supported;
+ ndctl_bus_has_nfit;
ndctl_bus_get_revision;
ndctl_bus_get_id;
ndctl_bus_get_provider;
diff --git a/lib/ndctl/libndctl.h b/lib/ndctl/libndctl.h
index 5c27a435b8fb..126c511e289e 100644
--- a/lib/ndctl/libndctl.h
+++ b/lib/ndctl/libndctl.h
@@ -96,6 +96,7 @@ struct ndctl_bus *ndctl_bus_get_next(struct ndctl_bus *bus);
bus != NULL; \
bus = ndctl_bus_get_next(bus))
struct ndctl_ctx *ndctl_bus_get_ctx(struct ndctl_bus *bus);
+int ndctl_bus_has_nfit(struct ndctl_bus *bus);
unsigned int ndctl_bus_get_major(struct ndctl_bus *bus);
unsigned int ndctl_bus_get_minor(struct ndctl_bus *bus);
const char *ndctl_bus_get_devname(struct ndctl_bus *bus);
diff --git a/lib/test-dpa-alloc.c b/lib/test-dpa-alloc.c
index f94838ac0b9b..9a881f301c7f 100644
--- a/lib/test-dpa-alloc.c
+++ b/lib/test-dpa-alloc.c
@@ -90,7 +90,7 @@ static int do_test(struct ndctl_ctx *ctx)
* to lowest with no excursions into BLK only ranges.
*/
ndctl_region_foreach(bus, region) {
- if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLOCK)
+ if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK)
continue;
dimm = ndctl_region_get_first_dimm(region);
if (!dimm)
diff --git a/lib/test-libndctl.c b/lib/test-libndctl.c
index 710aeb1f52b7..9e59861128bf 100644
--- a/lib/test-libndctl.c
+++ b/lib/test-libndctl.c
@@ -54,7 +54,7 @@
* +----------------------------+--------+--------+
*
* *) In this layout we have four dimms and two memory controllers in one
- * socket. Each unique interface ("block" or "pmem") to DPA space
+ * socket. Each unique interface ("blk" or "pmem") to DPA space
* is identified by a region device with a dynamically assigned id.
*
* *) The first portion of dimm0 and dimm1 are interleaved as REGION0.
@@ -185,7 +185,7 @@ static struct namespace namespace1_pmem0 = {
};
static struct namespace namespace2_blk0 = {
- 0, "namespace_block", NULL, SZ_7M,
+ 0, "namespace_blk", NULL, SZ_7M,
{ 3, 3, 3, 3,
3, 3, 3, 3,
3, 3, 3, 3,
@@ -193,7 +193,7 @@ static struct namespace namespace2_blk0 = {
};
static struct namespace namespace2_blk1 = {
- 1, "namespace_block", NULL, SZ_11M,
+ 1, "namespace_blk", NULL, SZ_11M,
{ 4, 4, 4, 4,
4, 4, 4, 4,
4, 4, 4, 4,
@@ -201,7 +201,7 @@ static struct namespace namespace2_blk1 = {
};
static struct namespace namespace3_blk0 = {
- 0, "namespace_block", NULL, SZ_7M,
+ 0, "namespace_blk", NULL, SZ_7M,
{ 5, 5, 5, 5,
5, 5, 5, 5,
5, 5, 5, 5,
@@ -209,7 +209,7 @@ static struct namespace namespace3_blk0 = {
};
static struct namespace namespace3_blk1 = {
- 1, "namespace_block", NULL, SZ_11M,
+ 1, "namespace_blk", NULL, SZ_11M,
{ 6, 6, 6, 6,
6, 6, 6, 6,
6, 6, 6, 6,
@@ -217,7 +217,7 @@ static struct namespace namespace3_blk1 = {
};
static struct namespace namespace4_blk0 = {
- 0, "namespace_block", &btt_settings, SZ_27M,
+ 0, "namespace_blk", &btt_settings, SZ_27M,
{ 7, 7, 7, 7,
7, 7, 7, 7,
7, 7, 7, 7,
@@ -225,7 +225,7 @@ static struct namespace namespace4_blk0 = {
};
static struct namespace namespace5_blk0 = {
- 0, "namespace_block", &btt_settings, SZ_27M,
+ 0, "namespace_blk", &btt_settings, SZ_27M,
{ 8, 8, 8, 8,
8, 8, 8, 8,
8, 8, 8, 8,
@@ -237,13 +237,13 @@ static struct region regions0[] = {
{ &namespace0_pmem0, NULL, }, },
{ { 2 }, 4, 1, "pmem", SZ_64M, SZ_64M, { 1 },
{ &namespace1_pmem0, NULL, }, },
- { { DIMM_HANDLE(0, 0, 0, 0, 0) }, 1, 1, "block", SZ_18M, SZ_32M, { },
+ { { DIMM_HANDLE(0, 0, 0, 0, 0) }, 1, 1, "blk", SZ_18M, SZ_32M, { },
{ &namespace2_blk0, &namespace2_blk1, NULL, }, },
- { { DIMM_HANDLE(0, 0, 0, 0, 1) }, 1, 1, "block", SZ_18M, SZ_32M, { },
+ { { DIMM_HANDLE(0, 0, 0, 0, 1) }, 1, 1, "blk", SZ_18M, SZ_32M, { },
{ &namespace3_blk0, &namespace3_blk1, NULL, }, },
- { { DIMM_HANDLE(0, 0, 1, 0, 0) }, 1, 1, "block", SZ_27M, SZ_32M, { },
+ { { DIMM_HANDLE(0, 0, 1, 0, 0) }, 1, 1, "blk", SZ_27M, SZ_32M, { },
{ &namespace4_blk0, NULL, }, },
- { { DIMM_HANDLE(0, 0, 1, 0, 1) }, 1, 1, "block", SZ_27M, SZ_32M, { },
+ { { DIMM_HANDLE(0, 0, 1, 0, 1) }, 1, 1, "blk", SZ_27M, SZ_32M, { },
{ &namespace5_blk0, NULL, }, },
};
@@ -252,7 +252,7 @@ static struct namespace namespace1 = {
};
static struct region regions1[] = {
- { { 1 }, 0, 1, "pmem", 0, SZ_32M,
+ { { 1 }, 1, 1, "pmem", 0, SZ_32M,
.namespaces = {
[0] = &namespace1,
},
@@ -267,9 +267,9 @@ static struct btt btts1[] = {
{ 0, { 0, }, 2, { 512, 4096, }, },
};
-static unsigned long commands0 = 1UL << NFIT_CMD_GET_CONFIG_SIZE
- | 1UL << NFIT_CMD_GET_CONFIG_DATA
- | 1UL << NFIT_CMD_SET_CONFIG_DATA;
+static unsigned long commands0 = 1UL << ND_CMD_GET_CONFIG_SIZE
+ | 1UL << ND_CMD_GET_CONFIG_DATA
+ | 1UL << ND_CMD_SET_CONFIG_DATA;
static struct ndctl_dimm *get_dimm_by_handle(struct ndctl_bus *bus, unsigned int handle)
{
@@ -339,7 +339,7 @@ static struct ndctl_region *get_blk_region_by_dimm_handle(struct ndctl_bus *bus,
ndctl_region_foreach(bus, region) {
struct ndctl_mapping *map;
- if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLOCK)
+ if (ndctl_region_get_type(region) != ND_DEVICE_REGION_BLK)
continue;
ndctl_mapping_foreach(region, map) {
struct ndctl_dimm *dimm = ndctl_mapping_get_dimm(map);
@@ -904,7 +904,7 @@ static int check_get_config_size(struct ndctl_dimm *dimm, struct check_cmd *chec
static int check_get_config_data(struct ndctl_dimm *dimm, struct check_cmd *check)
{
- struct ndctl_cmd *cmd_size = check_cmds[NFIT_CMD_GET_CONFIG_SIZE].cmd;
+ struct ndctl_cmd *cmd_size = check_cmds[ND_CMD_GET_CONFIG_SIZE].cmd;
struct ndctl_cmd *cmd = ndctl_dimm_cmd_new_cfg_read(cmd_size);
static char buf[SZ_128K];
ssize_t rc;
@@ -937,7 +937,7 @@ static int check_get_config_data(struct ndctl_dimm *dimm, struct check_cmd *chec
static int check_set_config_data(struct ndctl_dimm *dimm, struct check_cmd *check)
{
- struct ndctl_cmd *cmd_read = check_cmds[NFIT_CMD_GET_CONFIG_DATA].cmd;
+ struct ndctl_cmd *cmd_read = check_cmds[ND_CMD_GET_CONFIG_DATA].cmd;
struct ndctl_cmd *cmd = ndctl_dimm_cmd_new_cfg_write(cmd_read);
char buf[20], result[sizeof(buf)];
size_t rc;
@@ -1010,15 +1010,15 @@ static int check_commands(struct ndctl_bus *bus, struct ndctl_dimm *dimm,
* For now, by coincidence, these are indexed in test execution
* order such that check_get_config_data can assume that
* check_get_config_size has updated
- * check_cmd[NFIT_CMD_GET_CONFIG_SIZE].cmd and
+ * check_cmd[ND_CMD_GET_CONFIG_SIZE].cmd and
* check_set_config_data can assume that both
* check_get_config_size and check_get_config_data have run
*/
static struct check_cmd __check_cmds[] = {
- [NFIT_CMD_GET_CONFIG_SIZE] = { check_get_config_size },
- [NFIT_CMD_GET_CONFIG_DATA] = { check_get_config_data },
- [NFIT_CMD_SET_CONFIG_DATA] = { check_set_config_data },
- [NFIT_CMD_SMART_THRESHOLD] = { },
+ [ND_CMD_GET_CONFIG_SIZE] = { check_get_config_size },
+ [ND_CMD_GET_CONFIG_DATA] = { check_get_config_data },
+ [ND_CMD_SET_CONFIG_DATA] = { check_set_config_data },
+ [ND_CMD_SMART_THRESHOLD] = { },
};
unsigned int i, rc;
diff --git a/ndctl.h b/ndctl.h
index abddfdd2cfb4..baf1c506fee8 100644
--- a/ndctl.h
+++ b/ndctl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Intel Corporation.
+ * Copyright (c) 2014-2015, 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,
@@ -15,60 +15,60 @@
#include <linux/types.h>
-struct nfit_cmd_smart {
+struct nd_cmd_smart {
__u32 status;
__u8 data[128];
} __attribute__((packed));
-struct nfit_cmd_smart_threshold {
+struct nd_cmd_smart_threshold {
__u32 status;
__u8 data[8];
} __attribute__((packed));
-struct nfit_cmd_dimm_flags {
+struct nd_cmd_dimm_flags {
__u32 status;
__u32 flags;
} __attribute__((packed));
-struct nfit_cmd_get_config_size {
+struct nd_cmd_get_config_size {
__u32 status;
__u32 config_size;
__u32 max_xfer;
} __attribute__((packed));
-struct nfit_cmd_get_config_data_hdr {
+struct nd_cmd_get_config_data_hdr {
__u32 in_offset;
__u32 in_length;
__u32 status;
__u8 out_buf[0];
} __attribute__((packed));
-struct nfit_cmd_set_config_hdr {
+struct nd_cmd_set_config_hdr {
__u32 in_offset;
__u32 in_length;
__u8 in_buf[0];
} __attribute__((packed));
-struct nfit_cmd_vendor_hdr {
+struct nd_cmd_vendor_hdr {
__u32 opcode;
__u32 in_length;
__u8 in_buf[0];
} __attribute__((packed));
-struct nfit_cmd_vendor_tail {
+struct nd_cmd_vendor_tail {
__u32 status;
__u32 out_length;
__u8 out_buf[0];
} __attribute__((packed));
-struct nfit_cmd_ars_cap {
+struct nd_cmd_ars_cap {
__u64 address;
__u64 length;
__u32 status;
__u32 max_ars_out;
} __attribute__((packed));
-struct nfit_cmd_ars_start {
+struct nd_cmd_ars_start {
__u64 address;
__u64 length;
__u16 type;
@@ -76,15 +76,15 @@ struct nfit_cmd_ars_start {
__u32 status;
} __attribute__((packed));
-struct nfit_cmd_ars_query {
+struct nd_cmd_ars_query {
__u32 status;
- __u16 out_length;
+ __u32 out_length;
__u64 address;
__u64 length;
__u16 type;
__u32 num_records;
- struct nfit_ars_record {
- __u32 nfit_handle;
+ struct nd_ars_record {
+ __u32 handle;
__u32 flags;
__u64 err_address;
__u64 mask;
@@ -92,31 +92,31 @@ struct nfit_cmd_ars_query {
} __attribute__((packed));
enum {
- NFIT_CMD_IMPLEMENTED = 0,
+ ND_CMD_IMPLEMENTED = 0,
/* bus commands */
- NFIT_CMD_ARS_CAP = 1,
- NFIT_CMD_ARS_START = 2,
- NFIT_CMD_ARS_QUERY = 3,
+ ND_CMD_ARS_CAP = 1,
+ ND_CMD_ARS_START = 2,
+ ND_CMD_ARS_QUERY = 3,
/* per-dimm commands */
- NFIT_CMD_SMART = 1,
- NFIT_CMD_SMART_THRESHOLD = 2,
- NFIT_CMD_DIMM_FLAGS = 3,
- NFIT_CMD_GET_CONFIG_SIZE = 4,
- NFIT_CMD_GET_CONFIG_DATA = 5,
- NFIT_CMD_SET_CONFIG_DATA = 6,
- NFIT_CMD_VENDOR_EFFECT_LOG_SIZE = 7,
- NFIT_CMD_VENDOR_EFFECT_LOG = 8,
- NFIT_CMD_VENDOR = 9,
+ ND_CMD_SMART = 1,
+ ND_CMD_SMART_THRESHOLD = 2,
+ ND_CMD_DIMM_FLAGS = 3,
+ ND_CMD_GET_CONFIG_SIZE = 4,
+ ND_CMD_GET_CONFIG_DATA = 5,
+ ND_CMD_SET_CONFIG_DATA = 6,
+ ND_CMD_VENDOR_EFFECT_LOG_SIZE = 7,
+ ND_CMD_VENDOR_EFFECT_LOG = 8,
+ ND_CMD_VENDOR = 9,
};
-static __inline__ const char *nfit_bus_cmd_name(unsigned cmd)
+static __inline__ const char *nd_bus_cmd_name(unsigned cmd)
{
- static const char *names[] = {
- [NFIT_CMD_ARS_CAP] = "ars_cap",
- [NFIT_CMD_ARS_START] = "ars_start",
- [NFIT_CMD_ARS_QUERY] = "ars_query",
+ static const char * const names[] = {
+ [ND_CMD_ARS_CAP] = "ars_cap",
+ [ND_CMD_ARS_START] = "ars_start",
+ [ND_CMD_ARS_QUERY] = "ars_query",
};
if (cmd < ARRAY_SIZE(names) && names[cmd])
@@ -124,18 +124,18 @@ static __inline__ const char *nfit_bus_cmd_name(unsigned cmd)
return "unknown";
}
-static __inline__ const char *nfit_dimm_cmd_name(unsigned cmd)
+static __inline__ const char *nd_dimm_cmd_name(unsigned cmd)
{
- static const char *names[] = {
- [NFIT_CMD_SMART] = "smart",
- [NFIT_CMD_SMART_THRESHOLD] = "smart_thresh",
- [NFIT_CMD_DIMM_FLAGS] = "flags",
- [NFIT_CMD_GET_CONFIG_SIZE] = "get_size",
- [NFIT_CMD_GET_CONFIG_DATA] = "get_data",
- [NFIT_CMD_SET_CONFIG_DATA] = "set_data",
- [NFIT_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size",
- [NFIT_CMD_VENDOR_EFFECT_LOG] = "effect_log",
- [NFIT_CMD_VENDOR] = "vendor",
+ static const char * const names[] = {
+ [ND_CMD_SMART] = "smart",
+ [ND_CMD_SMART_THRESHOLD] = "smart_thresh",
+ [ND_CMD_DIMM_FLAGS] = "flags",
+ [ND_CMD_GET_CONFIG_SIZE] = "get_size",
+ [ND_CMD_GET_CONFIG_DATA] = "get_data",
+ [ND_CMD_SET_CONFIG_DATA] = "set_data",
+ [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size",
+ [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log",
+ [ND_CMD_VENDOR] = "vendor",
};
if (cmd < ARRAY_SIZE(names) && names[cmd])
@@ -145,51 +145,51 @@ static __inline__ const char *nfit_dimm_cmd_name(unsigned cmd)
#define ND_IOCTL 'N'
-#define NFIT_IOCTL_SMART _IOWR(ND_IOCTL, NFIT_CMD_SMART,\
- struct nfit_cmd_smart)
+#define ND_IOCTL_SMART _IOWR(ND_IOCTL, ND_CMD_SMART,\
+ struct nd_cmd_smart)
-#define NFIT_IOCTL_SMART_THRESHOLD _IOWR(ND_IOCTL, NFIT_CMD_SMART_THRESHOLD,\
- struct nfit_cmd_smart_threshold)
+#define ND_IOCTL_SMART_THRESHOLD _IOWR(ND_IOCTL, ND_CMD_SMART_THRESHOLD,\
+ struct nd_cmd_smart_threshold)
-#define NFIT_IOCTL_DIMM_FLAGS _IOWR(ND_IOCTL, NFIT_CMD_DIMM_FLAGS,\
- struct nfit_cmd_dimm_flags)
+#define ND_IOCTL_DIMM_FLAGS _IOWR(ND_IOCTL, ND_CMD_DIMM_FLAGS,\
+ struct nd_cmd_dimm_flags)
-#define NFIT_IOCTL_GET_CONFIG_SIZE _IOWR(ND_IOCTL, NFIT_CMD_GET_CONFIG_SIZE,\
- struct nfit_cmd_get_config_size)
+#define ND_IOCTL_GET_CONFIG_SIZE _IOWR(ND_IOCTL, ND_CMD_GET_CONFIG_SIZE,\
+ struct nd_cmd_get_config_size)
-#define NFIT_IOCTL_GET_CONFIG_DATA _IOWR(ND_IOCTL, NFIT_CMD_GET_CONFIG_DATA,\
- struct nfit_cmd_get_config_data_hdr)
+#define ND_IOCTL_GET_CONFIG_DATA _IOWR(ND_IOCTL, ND_CMD_GET_CONFIG_DATA,\
+ struct nd_cmd_get_config_data_hdr)
-#define NFIT_IOCTL_SET_CONFIG_DATA _IOWR(ND_IOCTL, NFIT_CMD_SET_CONFIG_DATA,\
- struct nfit_cmd_set_config_hdr)
+#define ND_IOCTL_SET_CONFIG_DATA _IOWR(ND_IOCTL, ND_CMD_SET_CONFIG_DATA,\
+ struct nd_cmd_set_config_hdr)
-#define NFIT_IOCTL_VENDOR _IOWR(ND_IOCTL, NFIT_CMD_VENDOR,\
- struct nfit_cmd_vendor_hdr)
+#define ND_IOCTL_VENDOR _IOWR(ND_IOCTL, ND_CMD_VENDOR,\
+ struct nd_cmd_vendor_hdr)
-#define NFIT_IOCTL_ARS_CAP _IOWR(ND_IOCTL, NFIT_CMD_ARS_CAP,\
- struct nfit_cmd_ars_cap)
+#define ND_IOCTL_ARS_CAP _IOWR(ND_IOCTL, ND_CMD_ARS_CAP,\
+ struct nd_cmd_ars_cap)
-#define NFIT_IOCTL_ARS_START _IOWR(ND_IOCTL, NFIT_CMD_ARS_START,\
- struct nfit_cmd_ars_start)
+#define ND_IOCTL_ARS_START _IOWR(ND_IOCTL, ND_CMD_ARS_START,\
+ struct nd_cmd_ars_start)
-#define NFIT_IOCTL_ARS_QUERY _IOWR(ND_IOCTL, NFIT_CMD_ARS_QUERY,\
- struct nfit_cmd_ars_query)
+#define ND_IOCTL_ARS_QUERY _IOWR(ND_IOCTL, ND_CMD_ARS_QUERY,\
+ struct nd_cmd_ars_query)
#define ND_DEVICE_DIMM 1 /* nd_dimm: container for "config data" */
#define ND_DEVICE_REGION_PMEM 2 /* nd_region: (parent of pmem namespaces) */
-#define ND_DEVICE_REGION_BLOCK 3 /* nd_region: (parent of block namespaces) */
+#define ND_DEVICE_REGION_BLK 3 /* nd_region: (parent of blk namespaces) */
#define ND_DEVICE_NAMESPACE_IO 4 /* legacy persistent memory */
#define ND_DEVICE_NAMESPACE_PMEM 5 /* persistent memory namespace (may alias) */
-#define ND_DEVICE_NAMESPACE_BLOCK 6 /* block-data-window namespace (may alias) */
+#define ND_DEVICE_NAMESPACE_BLK 6 /* block-data-window namespace (may alias) */
#define ND_DEVICE_BTT 7 /* block-translation table device */
enum nd_driver_flags {
ND_DRIVER_DIMM = 1 << ND_DEVICE_DIMM,
ND_DRIVER_REGION_PMEM = 1 << ND_DEVICE_REGION_PMEM,
- ND_DRIVER_REGION_BLOCK = 1 << ND_DEVICE_REGION_BLOCK,
+ ND_DRIVER_REGION_BLK = 1 << ND_DEVICE_REGION_BLK,
ND_DRIVER_NAMESPACE_IO = 1 << ND_DEVICE_NAMESPACE_IO,
ND_DRIVER_NAMESPACE_PMEM = 1 << ND_DEVICE_NAMESPACE_PMEM,
- ND_DRIVER_NAMESPACE_BLOCK = 1 << ND_DEVICE_NAMESPACE_BLOCK,
+ ND_DRIVER_NAMESPACE_BLK = 1 << ND_DEVICE_NAMESPACE_BLK,
ND_DRIVER_BTT = 1 << ND_DEVICE_BTT,
};
5 years, 8 months
[Linux-nvdimm] [PATCH 00/21] ND: NFIT-Defined / NVDIMM Subsystem
by Dan Williams
Since 2010 Intel has included non-volatile memory support on a few
storage-focused platforms with a feature named ADR (Asynchronous DRAM
Refresh). These platforms were mostly targeted at custom applications
and never enjoyed standard discovery mechanisms for platform firmware
to advertise non-volatile memory capabilities. This now changes with
the publication of version 6 of the ACPI specification [1] and its
inclusion of a new table for describing platform memory capabilities.
The NVDIMM Firmware Interface Table (NFIT), along with new EFI and E820
memory types, enumerates persistent memory ranges, memory-mapped-I/O
apertures, physical memory devices (DIMMs), and their associated
properties.
The ND-subsystem wraps a Linux device driver model around the objects
and address boundaries defined in the specification and introduces 3 new
drivers.
nd_pmem: NFIT enabled version of the existing 'pmem' driver [2]
nd_blk: mmio aperture method for accessing persistent storage
nd_btt: give persistent memory disk semantics (atomic sector update)
See the documentation in patch2 for more details, and there is
supplemental documentation on pmem.io [4]. Please review, and
patches welcome...
For kicking the tires, this release is accompanied by a userspace
management library 'ndctl' that includes unit tests (make check) for all
of the kernel ABIs. The nfit_test.ko module can be used to explore a
sample NFIT topology.
[1]: http://www.uefi.org/sites/default/files/resources/ACPI_6.0.pdf
[2]: https://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/log/?h=x86/pmem
[3]: https://github.com/pmem/ndctl
[4]: http://pmem.io/documents/
--
Dan for the NFIT driver development team Andy Rudoff, Matthew Wilcox, Ross
Zwisler, and Vishal Verma
---
Dan Williams (19):
e820, efi: add ACPI 6.0 persistent memory types
ND NFIT-Defined/NVIDIMM Subsystem
nd_acpi: initial core implementation and nfit skeleton
nd: create an 'nd_bus' from an 'nfit_desc'
nfit-test: manufactured NFITs for interface development
nd: ndctl class device, and nd bus attributes
nd: dimm devices (nfit "memory-devices")
nd: ndctl.h, the nd ioctl abi
nd_dimm: dimm driver and base nd-bus device-driver infrastructure
nd: regions (block-data-window, persistent memory, volatile memory)
nd_region: support for legacy nvdimms
nd_pmem: add NFIT support to the pmem driver
nd: add interleave-set state-tracking infrastructure
nd: namespace indices: read and validate
nd: pmem label sets and namespace instantiation.
nd: blk labels and namespace instantiation
nd: write pmem label set
nd: write blk label set
nd: infrastructure for btt devices
Ross Zwisler (1):
nd_blk: nfit blk driver
Vishal Verma (1):
nd_btt: atomic sector updates
Documentation/blockdev/btt.txt | 273 ++++++
Documentation/blockdev/nd.txt | 867 +++++++++++++++++++
MAINTAINERS | 34 +
arch/arm64/kernel/efi.c | 1
arch/ia64/kernel/efi.c | 1
arch/x86/boot/compressed/eboot.c | 4
arch/x86/include/uapi/asm/e820.h | 1
arch/x86/kernel/e820.c | 25 -
arch/x86/platform/efi/efi.c | 3
drivers/block/Kconfig | 13
drivers/block/Makefile | 2
drivers/block/nd/Kconfig | 130 +++
drivers/block/nd/Makefile | 39 +
drivers/block/nd/acpi.c | 443 ++++++++++
drivers/block/nd/blk.c | 269 ++++++
drivers/block/nd/btt.c | 1423 +++++++++++++++++++++++++++++++
drivers/block/nd/btt.h | 185 ++++
drivers/block/nd/btt_devs.c | 443 ++++++++++
drivers/block/nd/bus.c | 703 +++++++++++++++
drivers/block/nd/core.c | 963 +++++++++++++++++++++
drivers/block/nd/dimm.c | 126 +++
drivers/block/nd/dimm_devs.c | 701 +++++++++++++++
drivers/block/nd/label.c | 925 ++++++++++++++++++++
drivers/block/nd/label.h | 143 +++
drivers/block/nd/namespace_devs.c | 1697 +++++++++++++++++++++++++++++++++++++
drivers/block/nd/nd-private.h | 203 ++++
drivers/block/nd/nd.h | 310 +++++++
drivers/block/nd/nfit.h | 238 +++++
drivers/block/nd/pmem.c | 122 ++-
drivers/block/nd/region.c | 95 ++
drivers/block/nd/region_devs.c | 1196 ++++++++++++++++++++++++++
drivers/block/nd/test/Makefile | 5
drivers/block/nd/test/iomap.c | 199 ++++
drivers/block/nd/test/nfit.c | 1018 ++++++++++++++++++++++
drivers/block/nd/test/nfit_test.h | 37 +
include/linux/efi.h | 3
include/linux/nd.h | 98 ++
include/uapi/linux/Kbuild | 1
include/uapi/linux/ndctl.h | 199 ++++
39 files changed, 13102 insertions(+), 36 deletions(-)
create mode 100644 Documentation/blockdev/btt.txt
create mode 100644 Documentation/blockdev/nd.txt
create mode 100644 drivers/block/nd/Kconfig
create mode 100644 drivers/block/nd/Makefile
create mode 100644 drivers/block/nd/acpi.c
create mode 100644 drivers/block/nd/blk.c
create mode 100644 drivers/block/nd/btt.c
create mode 100644 drivers/block/nd/btt.h
create mode 100644 drivers/block/nd/btt_devs.c
create mode 100644 drivers/block/nd/bus.c
create mode 100644 drivers/block/nd/core.c
create mode 100644 drivers/block/nd/dimm.c
create mode 100644 drivers/block/nd/dimm_devs.c
create mode 100644 drivers/block/nd/label.c
create mode 100644 drivers/block/nd/label.h
create mode 100644 drivers/block/nd/namespace_devs.c
create mode 100644 drivers/block/nd/nd-private.h
create mode 100644 drivers/block/nd/nd.h
create mode 100644 drivers/block/nd/nfit.h
rename drivers/block/{pmem.c => nd/pmem.c} (68%)
create mode 100644 drivers/block/nd/region.c
create mode 100644 drivers/block/nd/region_devs.c
create mode 100644 drivers/block/nd/test/Makefile
create mode 100644 drivers/block/nd/test/iomap.c
create mode 100644 drivers/block/nd/test/nfit.c
create mode 100644 drivers/block/nd/test/nfit_test.h
create mode 100644 include/linux/nd.h
create mode 100644 include/uapi/linux/ndctl.h
5 years, 8 months