You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'libnvdimm-for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm
Pull libnvdimm subsystem from Dan Williams:
"The libnvdimm sub-system introduces, in addition to the
libnvdimm-core, 4 drivers / enabling modules:
NFIT:
Instantiates an "nvdimm bus" with the core and registers memory
devices (NVDIMMs) enumerated by the ACPI 6.0 NFIT (NVDIMM Firmware
Interface table).
After registering NVDIMMs the NFIT driver then registers "region"
devices. A libnvdimm-region defines an access mode and the
boundaries of persistent memory media. A region may span multiple
NVDIMMs that are interleaved by the hardware memory controller. In
turn, a libnvdimm-region can be carved into a "namespace" device and
bound to the PMEM or BLK driver which will attach a Linux block
device (disk) interface to the memory.
PMEM:
Initially merged in v4.1 this driver for contiguous spans of
persistent memory address ranges is re-worked to drive
PMEM-namespaces emitted by the libnvdimm-core.
In this update the PMEM driver, on x86, gains the ability to assert
that writes to persistent memory have been flushed all the way
through the caches and buffers in the platform to persistent media.
See memcpy_to_pmem() and wmb_pmem().
BLK:
This new driver enables access to persistent memory media through
"Block Data Windows" as defined by the NFIT. The primary difference
of this driver to PMEM is that only a small window of persistent
memory is mapped into system address space at any given point in
time.
Per-NVDIMM windows are reprogrammed at run time, per-I/O, to access
different portions of the media. BLK-mode, by definition, does not
support DAX.
BTT:
This is a library, optionally consumed by either PMEM or BLK, that
converts a byte-accessible namespace into a disk with atomic sector
update semantics (prevents sector tearing on crash or power loss).
The sinister aspect of sector tearing is that most applications do
not know they have a atomic sector dependency. At least today's
disk's rarely ever tear sectors and if they do one almost certainly
gets a CRC error on access. NVDIMMs will always tear and always
silently. Until an application is audited to be robust in the
presence of sector-tearing the usage of BTT is recommended.
Thanks to: Ross Zwisler, Jeff Moyer, Vishal Verma, Christoph Hellwig,
Ingo Molnar, Neil Brown, Boaz Harrosh, Robert Elliott, Matthew Wilcox,
Andy Rudoff, Linda Knippers, Toshi Kani, Nicholas Moulin, Rafael
Wysocki, and Bob Moore"
* tag 'libnvdimm-for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm: (33 commits)
arch, x86: pmem api for ensuring durability of persistent memory updates
libnvdimm: Add sysfs numa_node to NVDIMM devices
libnvdimm: Set numa_node to NVDIMM devices
acpi: Add acpi_map_pxm_to_online_node()
libnvdimm, nfit: handle unarmed dimms, mark namespaces read-only
pmem: flag pmem block devices as non-rotational
libnvdimm: enable iostat
pmem: make_request cleanups
libnvdimm, pmem: fix up max_hw_sectors
libnvdimm, blk: add support for blk integrity
libnvdimm, btt: add support for blk integrity
fs/block_dev.c: skip rw_page if bdev has integrity
libnvdimm: Non-Volatile Devices
tools/testing/nvdimm: libnvdimm unit test infrastructure
libnvdimm, nfit, nd_blk: driver for BLK-mode access persistent memory
nd_btt: atomic sector updates
libnvdimm: infrastructure for btt devices
libnvdimm: write blk label set
libnvdimm: write pmem label set
libnvdimm: blk labels and namespace instantiation
...
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
ldflags-y += --wrap=ioremap_cache
|
||||
ldflags-y += --wrap=ioremap_nocache
|
||||
ldflags-y += --wrap=iounmap
|
||||
ldflags-y += --wrap=__request_region
|
||||
ldflags-y += --wrap=__release_region
|
||||
|
||||
DRIVERS := ../../../drivers
|
||||
NVDIMM_SRC := $(DRIVERS)/nvdimm
|
||||
ACPI_SRC := $(DRIVERS)/acpi
|
||||
|
||||
obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
|
||||
obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
|
||||
obj-$(CONFIG_ND_BTT) += nd_btt.o
|
||||
obj-$(CONFIG_ND_BLK) += nd_blk.o
|
||||
obj-$(CONFIG_ACPI_NFIT) += nfit.o
|
||||
|
||||
nfit-y := $(ACPI_SRC)/nfit.o
|
||||
nfit-y += config_check.o
|
||||
|
||||
nd_pmem-y := $(NVDIMM_SRC)/pmem.o
|
||||
nd_pmem-y += config_check.o
|
||||
|
||||
nd_btt-y := $(NVDIMM_SRC)/btt.o
|
||||
nd_btt-y += config_check.o
|
||||
|
||||
nd_blk-y := $(NVDIMM_SRC)/blk.o
|
||||
nd_blk-y += config_check.o
|
||||
|
||||
libnvdimm-y := $(NVDIMM_SRC)/core.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/bus.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/dimm_devs.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/dimm.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/region_devs.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/region.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/namespace_devs.o
|
||||
libnvdimm-y += $(NVDIMM_SRC)/label.o
|
||||
libnvdimm-$(CONFIG_BTT) += $(NVDIMM_SRC)/btt_devs.o
|
||||
libnvdimm-y += config_check.o
|
||||
|
||||
obj-m += test/
|
||||
@@ -0,0 +1,7 @@
|
||||
KDIR ?= ../../../
|
||||
|
||||
default:
|
||||
$(MAKE) -C $(KDIR) M=$$PWD
|
||||
|
||||
install: default
|
||||
$(MAKE) -C $(KDIR) M=$$PWD modules_install
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <linux/kconfig.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
void check(void)
|
||||
{
|
||||
/*
|
||||
* These kconfig symbols must be set to "m" for nfit_test to
|
||||
* load and operate.
|
||||
*/
|
||||
BUILD_BUG_ON(!IS_MODULE(CONFIG_LIBNVDIMM));
|
||||
BUILD_BUG_ON(!IS_MODULE(CONFIG_BLK_DEV_PMEM));
|
||||
BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT));
|
||||
BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK));
|
||||
BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT));
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
ccflags-y := -I$(src)/../../../../drivers/nvdimm/
|
||||
ccflags-y += -I$(src)/../../../../drivers/acpi/
|
||||
|
||||
obj-m += nfit_test.o
|
||||
obj-m += nfit_test_iomap.o
|
||||
|
||||
nfit_test-y := nfit.o
|
||||
nfit_test_iomap-y := iomap.o
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that 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 <linux/rculist.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
#include "nfit_test.h"
|
||||
|
||||
static LIST_HEAD(iomap_head);
|
||||
|
||||
static struct iomap_ops {
|
||||
nfit_test_lookup_fn nfit_test_lookup;
|
||||
struct list_head list;
|
||||
} iomap_ops = {
|
||||
.list = LIST_HEAD_INIT(iomap_ops.list),
|
||||
};
|
||||
|
||||
void nfit_test_setup(nfit_test_lookup_fn lookup)
|
||||
{
|
||||
iomap_ops.nfit_test_lookup = lookup;
|
||||
list_add_rcu(&iomap_ops.list, &iomap_head);
|
||||
}
|
||||
EXPORT_SYMBOL(nfit_test_setup);
|
||||
|
||||
void nfit_test_teardown(void)
|
||||
{
|
||||
list_del_rcu(&iomap_ops.list);
|
||||
synchronize_rcu();
|
||||
}
|
||||
EXPORT_SYMBOL(nfit_test_teardown);
|
||||
|
||||
static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
|
||||
{
|
||||
struct iomap_ops *ops;
|
||||
|
||||
ops = list_first_or_null_rcu(&iomap_head, typeof(*ops), list);
|
||||
if (ops)
|
||||
return ops->nfit_test_lookup(resource);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
|
||||
void __iomem *(*fallback_fn)(resource_size_t, unsigned long))
|
||||
{
|
||||
struct nfit_test_resource *nfit_res;
|
||||
|
||||
rcu_read_lock();
|
||||
nfit_res = get_nfit_res(offset);
|
||||
rcu_read_unlock();
|
||||
if (nfit_res)
|
||||
return (void __iomem *) nfit_res->buf + offset
|
||||
- nfit_res->res->start;
|
||||
return fallback_fn(offset, size);
|
||||
}
|
||||
|
||||
void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size)
|
||||
{
|
||||
return __nfit_test_ioremap(offset, size, ioremap_cache);
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap_ioremap_cache);
|
||||
|
||||
void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
|
||||
{
|
||||
return __nfit_test_ioremap(offset, size, ioremap_nocache);
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap_ioremap_nocache);
|
||||
|
||||
void __wrap_iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
struct nfit_test_resource *nfit_res;
|
||||
|
||||
rcu_read_lock();
|
||||
nfit_res = get_nfit_res((unsigned long) addr);
|
||||
rcu_read_unlock();
|
||||
if (nfit_res)
|
||||
return;
|
||||
return iounmap(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap_iounmap);
|
||||
|
||||
struct resource *__wrap___request_region(struct resource *parent,
|
||||
resource_size_t start, resource_size_t n, const char *name,
|
||||
int flags)
|
||||
{
|
||||
struct nfit_test_resource *nfit_res;
|
||||
|
||||
if (parent == &iomem_resource) {
|
||||
rcu_read_lock();
|
||||
nfit_res = get_nfit_res(start);
|
||||
rcu_read_unlock();
|
||||
if (nfit_res) {
|
||||
struct resource *res = nfit_res->res + 1;
|
||||
|
||||
if (start + n > nfit_res->res->start
|
||||
+ resource_size(nfit_res->res)) {
|
||||
pr_debug("%s: start: %llx n: %llx overflow: %pr\n",
|
||||
__func__, start, n,
|
||||
nfit_res->res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res->start = start;
|
||||
res->end = start + n - 1;
|
||||
res->name = name;
|
||||
res->flags = resource_type(parent);
|
||||
res->flags |= IORESOURCE_BUSY | flags;
|
||||
pr_debug("%s: %pr\n", __func__, res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return __request_region(parent, start, n, name, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap___request_region);
|
||||
|
||||
void __wrap___release_region(struct resource *parent, resource_size_t start,
|
||||
resource_size_t n)
|
||||
{
|
||||
struct nfit_test_resource *nfit_res;
|
||||
|
||||
if (parent == &iomem_resource) {
|
||||
rcu_read_lock();
|
||||
nfit_res = get_nfit_res(start);
|
||||
rcu_read_unlock();
|
||||
if (nfit_res) {
|
||||
struct resource *res = nfit_res->res + 1;
|
||||
|
||||
if (start != res->start || resource_size(res) != n)
|
||||
pr_info("%s: start: %llx n: %llx mismatch: %pr\n",
|
||||
__func__, start, n, res);
|
||||
else
|
||||
memset(res, 0, sizeof(*res));
|
||||
return;
|
||||
}
|
||||
}
|
||||
__release_region(parent, start, n);
|
||||
}
|
||||
EXPORT_SYMBOL(__wrap___release_region);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that 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.
|
||||
*/
|
||||
#ifndef __NFIT_TEST_H__
|
||||
#define __NFIT_TEST_H__
|
||||
|
||||
struct nfit_test_resource {
|
||||
struct list_head list;
|
||||
struct resource *res;
|
||||
struct device *dev;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
typedef struct nfit_test_resource *(*nfit_test_lookup_fn)(resource_size_t);
|
||||
void __iomem *__wrap_ioremap_nocache(resource_size_t offset,
|
||||
unsigned long size);
|
||||
void __wrap_iounmap(volatile void __iomem *addr);
|
||||
void nfit_test_setup(nfit_test_lookup_fn lookup);
|
||||
void nfit_test_teardown(void);
|
||||
#endif
|
||||
Reference in New Issue
Block a user