projects/linux·commit 9f3a0941

Merge tag 'libnvdimm-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

9f3a0941 · Linus Torvalds <[email protected]> · 2018-04-10 10:25:57 -07:00

Pull libnvdimm updates from Dan Williams:
 "This cycle was was not something I ever want to repeat as there were
  several late changes that have only now just settled.

  Half of the branch up to commit d2c997c0f145 ("fs, dax: use
  page->mapping to warn...") have been in -next for several releases.
  The of_pmem driver and the address range scrub rework were late
  arrivals, and the dax work was scaled back at the last moment.

  The of_pmem driver missed a previous merge window due to an oversight.
  A sense of obligation to rectify that miss is why it is included for
  4.17. It has acks from PowerPC folks. Stephen reported a build failure
  that only occurs when merging it with your latest tree, for now I have
  fixed that up by disabling modular builds of of_pmem. A test merge
  with your tree has received a build success report from the 0day robot
  over 156 configs.

  An initial version of the ARS rework was submitted before the merge
  window. It is self contained to libnvdimm, a net code reduction, and
  passing all unit tests.

  The filesystem-dax changes are based on the wait_var_event()
  functionality from tip/sched/core. However, late review feedback
  showed that those changes regressed truncate performance to a large
  degree. The branch was rewound to drop the truncate behavior change
  and now only includes preparation patches and cleanups (with full acks
  and reviews). The finalization of this dax-dma-vs-trnucate work will
  need to wait for 4.18.

  Summary:

   - A rework of the filesytem-dax implementation provides for detection
     of unmap operations (truncate / hole punch) colliding with
     in-progress device-DMA. A fix for these collisions remains a
     work-in-progress pending resolution of truncate latency and
     starvation regressions.

   - The of_pmem driver expands the users of libnvdimm outside of x86
     and ACPI to describe an implementation of persistent memory on
     PowerPC with Open Firmware / Device tree.

   - Address Range Scrub (ARS) handling is completely rewritten to
     account for the fact that ARS may run for 100s of seconds and there
     is no platform defined way to cancel it. ARS will now no longer
     block namespace initialization.

   - The NVDIMM Namespace Label implementation is updated to handle
     label areas as small as 1K, down from 128K.

   - Miscellaneous cleanups and updates to unit test infrastructure"

* tag 'libnvdimm-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: (39 commits)
  libnvdimm, of_pmem: workaround OF_NUMA=n build error
  nfit, address-range-scrub: add module option to skip initial ars
  nfit, address-range-scrub: rework and simplify ARS state machine
  nfit, address-range-scrub: determine one platform max_ars value
  powerpc/powernv: Create platform devs for nvdimm buses
  doc/devicetree: Persistent memory region bindings
  libnvdimm: Add device-tree based driver
  libnvdimm: Add of_node to region and bus descriptors
  libnvdimm, region: quiet region probe
  libnvdimm, namespace: use a safe lookup for dimm device name
  libnvdimm, dimm: fix dpa reservation vs uninitialized label area
  libnvdimm, testing: update the default smart ctrl_temperature
  libnvdimm, testing: Add emulation for smart injection commands
  nfit, address-range-scrub: introduce nfit_spa->ars_state
  libnvdimm: add an api to cast a 'struct nd_region' to its 'struct device'
  nfit, address-range-scrub: fix scrub in-progress reporting
  dax, dm: allow device-mapper to operate without dax support
  dax: introduce CONFIG_DAX_DRIVER
  fs, dax: use page->mapping to warn if truncate collides with a busy page
  ext2, dax: introduce ext2_dax_aops
  ...
Commit
9f3a0941fb5efaa4d27911e251dc595034d58baa
Parents
fbe173e3 · e13e75b8

Merge commit. Changes below are compared with the first parent: fbe173e3.

Changes

50 files changed · +1217 −788

FileStatusAddDelContent
Documentation/devicetree/bindings/pmem/pmem-region.txtadded+65−0View file
MAINTAINERSmodified+8−0View file
arch/powerpc/platforms/powernv/opal.cmodified+3−0View file
drivers/acpi/nfit/core.cmodified+323−356View file
drivers/acpi/nfit/mce.cmodified+2−3View file
drivers/acpi/nfit/nfit.hmodified+14−8View file
drivers/dax/Kconfigmodified+4−1View file
drivers/dax/device.cmodified+17−21View file
drivers/dax/pmem.cmodified+4−14View file
drivers/dax/super.cmodified+12−3View file
drivers/md/Kconfigmodified+1−1View file
drivers/md/dm-linear.cmodified+6−0View file
drivers/md/dm-log-writes.cmodified+50−45View file
drivers/md/dm-stripe.cmodified+6−0View file
drivers/md/dm.cmodified+6−4View file
drivers/nvdimm/Kconfigmodified+12−1View file
drivers/nvdimm/Makefilemodified+1−0View file
drivers/nvdimm/btt_devs.cmodified+10−11View file
drivers/nvdimm/bus.cmodified+7−7View file
drivers/nvdimm/claim.cmodified+1−1View file
drivers/nvdimm/core.cmodified+3−3View file
drivers/nvdimm/dax_devs.cmodified+2−3View file
drivers/nvdimm/dimm.cmodified+5−3View file
drivers/nvdimm/dimm_devs.cmodified+3−4View file
drivers/nvdimm/label.cmodified+47−38View file
drivers/nvdimm/label.hmodified+1−1View file
drivers/nvdimm/namespace_devs.cmodified+18−24View file
drivers/nvdimm/nd.hmodified+0−1View file
drivers/nvdimm/of_pmem.cadded+119−0View file
drivers/nvdimm/pfn_devs.cmodified+12−13View file
drivers/nvdimm/pmem.cmodified+2−12View file
drivers/nvdimm/region.cmodified+2−2View file
drivers/nvdimm/region_devs.cmodified+9−0View file
drivers/s390/block/Kconfigmodified+1−1View file
fs/block_dev.cmodified+0−5View file
fs/dax.cmodified+94−52View file
fs/ext2/ext2.hmodified+1−0View file
fs/ext2/inode.cmodified+27−19View file
fs/ext2/namei.cmodified+2−16View file
fs/ext4/inode.cmodified+31−11View file
fs/libfs.cmodified+39−0View file
fs/xfs/xfs_aops.cmodified+18−16View file
fs/xfs/xfs_aops.hmodified+1−0View file
fs/xfs/xfs_iops.cmodified+4−1View file
include/linux/dax.hmodified+33−9View file
include/linux/fs.hmodified+4−0View file
include/linux/libnvdimm.hmodified+4−0View file
include/linux/nd.hmodified+6−0View file
tools/testing/nvdimm/test/nfit.cmodified+161−78View file
tools/testing/nvdimm/test/nfit_test.hmodified+16−0View file

Only the first 600 diff lines are shown. Download the complete patch.

Documentation/devicetree/bindings/pmem/pmem-region.txt

View file
diff --git a/Documentation/devicetree/bindings/pmem/pmem-region.txt b/Documentation/devicetree/bindings/pmem/pmem-region.txt
new file mode 100644
index 0000000..5cfa4f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pmem/pmem-region.txt
@@ -0,0 +1,65 @@
+Device-tree bindings for persistent memory regions
+-----------------------------------------------------
+
+Persistent memory refers to a class of memory devices that are:
+
+ a) Usable as main system memory (i.e. cacheable), and
+ b) Retain their contents across power failure.
+
+Given b) it is best to think of persistent memory as a kind of memory mapped
+storage device. To ensure data integrity the operating system needs to manage
+persistent regions separately to the normal memory pool. To aid with that this
+binding provides a standardised interface for discovering where persistent
+memory regions exist inside the physical address space.
+
+Bindings for the region nodes:
+-----------------------------
+
+Required properties:
+ - compatible = "pmem-region"
+
+ - reg = <base, size>;
+ The reg property should specificy an address range that is
+ translatable to a system physical address range. This address
+ range should be mappable as normal system memory would be
+ (i.e cacheable).
+
+ If the reg property contains multiple address ranges
+ each address range will be treated as though it was specified
+ in a separate device node. Having multiple address ranges in a
+ node implies no special relationship between the two ranges.
+
+Optional properties:
+ - Any relevant NUMA assocativity properties for the target platform.
+
+ - volatile; This property indicates that this region is actually
+ backed by non-persistent memory. This lets the OS know that it
+ may skip the cache flushes required to ensure data is made
+ persistent after a write.
+
+ If this property is absent then the OS must assume that the region
+ is backed by non-volatile memory.
+
+Examples:
+--------------------
+
+ /*
+ * This node specifies one 4KB region spanning from
+ * 0x5000 to 0x5fff that is backed by non-volatile memory.
+ */
+ pmem@5000 {
+ compatible = "pmem-region";
+ reg = <0x00005000 0x00001000>;
+ };
+
+ /*
+ * This node specifies two 4KB regions that are backed by
+ * volatile (normal) memory.
+ */
+ pmem@6000 {
+ compatible = "pmem-region";
+ reg = < 0x00006000 0x00001000
+ 0x00008000 0x00001000 >;
+ volatile;
+ };
+

MAINTAINERS

View file
diff --git a/MAINTAINERS b/MAINTAINERS
index dd7ce91..00855ff 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8048,6 +8048,14 @@ Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
S: Supported
F: drivers/nvdimm/pmem*
+LIBNVDIMM: DEVICETREE BINDINGS
+M: Oliver O'Halloran <[email protected]>
+Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
+S: Supported
+F: drivers/nvdimm/of_pmem.c
+F: Documentation/devicetree/bindings/pmem/pmem-region.txt
+
LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
M: Dan Williams <[email protected]>

arch/powerpc/platforms/powernv/opal.c

View file
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 516e23d..48fbb41 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -824,6 +824,9 @@ static int __init opal_init(void)
/* Create i2c platform devices */
opal_pdev_init("ibm,opal-i2c");
+ /* Handle non-volatile memory devices */
+ opal_pdev_init("pmem-region");
+
/* Setup a heatbeat thread if requested by OPAL */
opal_init_heartbeat();

drivers/acpi/nfit/core.c

View file
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 22a112b..e2235ed 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -36,16 +36,6 @@ static bool force_enable_dimms;
module_param(force_enable_dimms, bool, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(force_enable_dimms, "Ignore _STA (ACPI DIMM device) status");
-static unsigned int scrub_timeout = NFIT_ARS_TIMEOUT;
-module_param(scrub_timeout, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scrub_timeout, "Initial scrub timeout in seconds");
-
-/* after three payloads of overflow, it's dead jim */
-static unsigned int scrub_overflow_abort = 3;
-module_param(scrub_overflow_abort, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(scrub_overflow_abort,
- "Number of times we overflow ARS results before abort");
-
static bool disable_vendor_specific;
module_param(disable_vendor_specific, bool, S_IRUGO);
MODULE_PARM_DESC(disable_vendor_specific,
@@ -60,6 +50,10 @@ module_param(default_dsm_family, int, S_IRUGO);
MODULE_PARM_DESC(default_dsm_family,
"Try this DSM type first when identifying NVDIMM family");
+static bool no_init_ars;
+module_param(no_init_ars, bool, 0644);
+MODULE_PARM_DESC(no_init_ars, "Skip ARS run at nfit init time");
+
LIST_HEAD(acpi_descs);
DEFINE_MUTEX(acpi_desc_lock);
@@ -197,7 +191,7 @@ static int xlat_nvdimm_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd
* In the _LSI, _LSR, _LSW case the locked status is
* communicated via the read/write commands
*/
- if (nfit_mem->has_lsi)
+ if (nfit_mem->has_lsr)
break;
if (status >> 16 & ND_CONFIG_LOCKED)
@@ -477,14 +471,14 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
in_buf.buffer.length = call_pkg->nd_size_in;
}
- dev_dbg(dev, "%s:%s cmd: %d: func: %d input length: %d\n",
- __func__, dimm_name, cmd, func, in_buf.buffer.length);
+ dev_dbg(dev, "%s cmd: %d: func: %d input length: %d\n",
+ dimm_name, cmd, func, in_buf.buffer.length);
print_hex_dump_debug("nvdimm in ", DUMP_PREFIX_OFFSET, 4, 4,
in_buf.buffer.pointer,
min_t(u32, 256, in_buf.buffer.length), true);
/* call the BIOS, prefer the named methods over _DSM if available */
- if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsi)
+ if (nvdimm && cmd == ND_CMD_GET_CONFIG_SIZE && nfit_mem->has_lsr)
out_obj = acpi_label_info(handle);
else if (nvdimm && cmd == ND_CMD_GET_CONFIG_DATA && nfit_mem->has_lsr) {
struct nd_cmd_get_config_data_hdr *p = buf;
@@ -507,8 +501,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
}
if (!out_obj) {
- dev_dbg(dev, "%s:%s _DSM failed cmd: %s\n", __func__, dimm_name,
- cmd_name);
+ dev_dbg(dev, "%s _DSM failed cmd: %s\n", dimm_name, cmd_name);
return -EINVAL;
}
@@ -529,13 +522,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
}
if (out_obj->package.type != ACPI_TYPE_BUFFER) {
- dev_dbg(dev, "%s:%s unexpected output object type cmd: %s type: %d\n",
- __func__, dimm_name, cmd_name, out_obj->type);
+ dev_dbg(dev, "%s unexpected output object type cmd: %s type: %d\n",
+ dimm_name, cmd_name, out_obj->type);
rc = -EINVAL;
goto out;
}
- dev_dbg(dev, "%s:%s cmd: %s output length: %d\n", __func__, dimm_name,
+ dev_dbg(dev, "%s cmd: %s output length: %d\n", dimm_name,
cmd_name, out_obj->buffer.length);
print_hex_dump_debug(cmd_name, DUMP_PREFIX_OFFSET, 4, 4,
out_obj->buffer.pointer,
@@ -547,14 +540,14 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
out_obj->buffer.length - offset);
if (offset + out_size > out_obj->buffer.length) {
- dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
+ dev_dbg(dev, "%s output object underflow cmd: %s field: %d\n",
+ dimm_name, cmd_name, i);
break;
}
if (in_buf.buffer.length + offset + out_size > buf_len) {
- dev_dbg(dev, "%s:%s output overrun cmd: %s field: %d\n",
- __func__, dimm_name, cmd_name, i);
+ dev_dbg(dev, "%s output overrun cmd: %s field: %d\n",
+ dimm_name, cmd_name, i);
rc = -ENXIO;
goto out;
}
@@ -656,7 +649,7 @@ static bool add_spa(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_spa->list);
memcpy(nfit_spa->spa, spa, sizeof(*spa));
list_add_tail(&nfit_spa->list, &acpi_desc->spas);
- dev_dbg(dev, "%s: spa index: %d type: %s\n", __func__,
+ dev_dbg(dev, "spa index: %d type: %s\n",
spa->range_index,
spa_type_name(nfit_spa_type(spa)));
return true;
@@ -685,8 +678,8 @@ static bool add_memdev(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_memdev->list);
memcpy(nfit_memdev->memdev, memdev, sizeof(*memdev));
list_add_tail(&nfit_memdev->list, &acpi_desc->memdevs);
- dev_dbg(dev, "%s: memdev handle: %#x spa: %d dcr: %d flags: %#x\n",
- __func__, memdev->device_handle, memdev->range_index,
+ dev_dbg(dev, "memdev handle: %#x spa: %d dcr: %d flags: %#x\n",
+ memdev->device_handle, memdev->range_index,
memdev->region_index, memdev->flags);
return true;
}
@@ -754,7 +747,7 @@ static bool add_dcr(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_dcr->list);
memcpy(nfit_dcr->dcr, dcr, sizeof_dcr(dcr));
list_add_tail(&nfit_dcr->list, &acpi_desc->dcrs);
- dev_dbg(dev, "%s: dcr index: %d windows: %d\n", __func__,
+ dev_dbg(dev, "dcr index: %d windows: %d\n",
dcr->region_index, dcr->windows);
return true;
}
@@ -781,7 +774,7 @@ static bool add_bdw(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_bdw->list);
memcpy(nfit_bdw->bdw, bdw, sizeof(*bdw));
list_add_tail(&nfit_bdw->list, &acpi_desc->bdws);
- dev_dbg(dev, "%s: bdw dcr: %d windows: %d\n", __func__,
+ dev_dbg(dev, "bdw dcr: %d windows: %d\n",
bdw->region_index, bdw->windows);
return true;
}
@@ -820,7 +813,7 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_idt->list);
memcpy(nfit_idt->idt, idt, sizeof_idt(idt));
list_add_tail(&nfit_idt->list, &acpi_desc->idts);
- dev_dbg(dev, "%s: idt index: %d num_lines: %d\n", __func__,
+ dev_dbg(dev, "idt index: %d num_lines: %d\n",
idt->interleave_index, idt->line_count);
return true;
}
@@ -860,7 +853,7 @@ static bool add_flush(struct acpi_nfit_desc *acpi_desc,
INIT_LIST_HEAD(&nfit_flush->list);
memcpy(nfit_flush->flush, flush, sizeof_flush(flush));
list_add_tail(&nfit_flush->list, &acpi_desc->flushes);
- dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__,
+ dev_dbg(dev, "nfit_flush handle: %d hint_count: %d\n",
flush->device_handle, flush->hint_count);
return true;
}
@@ -873,7 +866,7 @@ static bool add_platform_cap(struct acpi_nfit_desc *acpi_desc,
mask = (1 << (pcap->highest_capability + 1)) - 1;
acpi_desc->platform_cap = pcap->capabilities & mask;
- dev_dbg(dev, "%s: cap: %#x\n", __func__, acpi_desc->platform_cap);
+ dev_dbg(dev, "cap: %#x\n", acpi_desc->platform_cap);
return true;
}
@@ -920,7 +913,7 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc,
return err;
break;
case ACPI_NFIT_TYPE_SMBIOS:
- dev_dbg(dev, "%s: smbios\n", __func__);
+ dev_dbg(dev, "smbios\n");
break;
case ACPI_NFIT_TYPE_CAPABILITIES:
if (!add_platform_cap(acpi_desc, table))
@@ -1277,8 +1270,11 @@ static ssize_t scrub_show(struct device *dev,
if (nd_desc) {
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
+ mutex_lock(&acpi_desc->init_mutex);
rc = sprintf(buf, "%d%s", acpi_desc->scrub_count,
- (work_busy(&acpi_desc->work)) ? "+\n" : "\n");
+ work_busy(&acpi_desc->dwork.work)
+ && !acpi_desc->cancel ? "+\n" : "\n");
+ mutex_unlock(&acpi_desc->init_mutex);
}
device_unlock(dev);
return rc;
@@ -1648,7 +1644,7 @@ void __acpi_nvdimm_notify(struct device *dev, u32 event)
struct nfit_mem *nfit_mem;
struct acpi_nfit_desc *acpi_desc;
- dev_dbg(dev->parent, "%s: %s: event: %d\n", dev_name(dev), __func__,
+ dev_dbg(dev->parent, "%s: event: %d\n", dev_name(dev),
event);
if (event != NFIT_NOTIFY_DIMM_HEALTH) {
@@ -1681,12 +1677,23 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
device_unlock(dev->parent);
}
+static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ status = acpi_get_handle(adev->handle, method, &handle);
+
+ if (ACPI_SUCCESS(status))
+ return true;
+ return false;
+}
+
static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
struct nfit_mem *nfit_mem, u32 device_handle)
{
struct acpi_device *adev, *adev_dimm;
struct device *dev = acpi_desc->dev;
- union acpi_object *obj;
unsigned long dsm_mask;
const guid_t *guid;
int i;
@@ -1759,25 +1766,15 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1ULL << i))
set_bit(i, &nfit_mem->dsm_mask);
- obj = acpi_label_info(adev_dimm->handle);
- if (obj) {
- ACPI_FREE(obj);
- nfit_mem->has_lsi = 1;
- dev_dbg(dev, "%s: has _LSI\n", dev_name(&adev_dimm->dev));
- }
-
- obj = acpi_label_read(adev_dimm->handle, 0, 0);
- if (obj) {
- ACPI_FREE(obj);
- nfit_mem->has_lsr = 1;
+ if (acpi_nvdimm_has_method(adev_dimm, "_LSI")
+ && acpi_nvdimm_has_method(adev_dimm, "_LSR")) {
dev_dbg(dev, "%s: has _LSR\n", dev_name(&adev_dimm->dev));
+ nfit_mem->has_lsr = true;
}
- obj = acpi_label_write(adev_dimm->handle, 0, 0, NULL);
- if (obj) {
- ACPI_FREE(obj);
- nfit_mem->has_lsw = 1;
+ if (nfit_mem->has_lsr && acpi_nvdimm_has_method(adev_dimm, "_LSW")) {
dev_dbg(dev, "%s: has _LSW\n", dev_name(&adev_dimm->dev));
+ nfit_mem->has_lsw = true;
}
return 0;
@@ -1866,10 +1863,10 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
cmd_mask |= nfit_mem->dsm_mask & NVDIMM_STANDARD_CMDMASK;
}
- if (nfit_mem->has_lsi)
+ if (nfit_mem->has_lsr) {
set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
- if (nfit_mem->has_lsr)
set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
+ }
if (nfit_mem->has_lsw)
set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask);
@@ -2365,7 +2362,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
nvdimm = nd_blk_region_to_dimm(ndbr);
nfit_mem = nvdimm_provider_data(nvdimm);
if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) {
- dev_dbg(dev, "%s: missing%s%s%s\n", __func__,
+ dev_dbg(dev, "missing%s%s%s\n",
nfit_mem ? "" : " nfit_mem",
(nfit_mem && nfit_mem->dcr) ? "" : " dcr",
(nfit_mem && nfit_mem->bdw) ? "" : " bdw");
@@ -2384,7 +2381,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
mmio->addr.base = devm_nvdimm_memremap(dev, nfit_mem->spa_bdw->address,
nfit_mem->spa_bdw->length, nd_blk_memremap_flags(ndbr));
if (!mmio->addr.base) {
- dev_dbg(dev, "%s: %s failed to map bdw\n", __func__,
+ dev_dbg(dev, "%s failed to map bdw\n",
nvdimm_name(nvdimm));
return -ENOMEM;
}
@@ -2395,8 +2392,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
rc = nfit_blk_init_interleave(mmio, nfit_mem->idt_bdw,
nfit_mem->memdev_bdw->interleave_ways);
if (rc) {
- dev_dbg(dev, "%s: %s failed to init bdw interleave\n",
- __func__, nvdimm_name(nvdimm));
+ dev_dbg(dev, "%s failed to init bdw interleave\n",
+ nvdimm_name(nvdimm));
return rc;
}
@@ -2407,7 +2404,7 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
mmio->addr.base = devm_nvdimm_ioremap(dev, nfit_mem->spa_dcr->address,
nfit_mem->spa_dcr->length);
if (!mmio->addr.base) {
- dev_dbg(dev, "%s: %s failed to map dcr\n", __func__,
+ dev_dbg(dev, "%s failed to map dcr\n",
nvdimm_name(nvdimm));
return -ENOMEM;
}
@@ -2418,15 +2415,15 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus,
rc = nfit_blk_init_interleave(mmio, nfit_mem->idt_dcr,
nfit_mem->memdev_dcr->interleave_ways);
if (rc) {
- dev_dbg(dev, "%s: %s failed to init dcr interleave\n",
- __func__, nvdimm_name(nvdimm));
+ dev_dbg(dev, "%s failed to init dcr interleave\n",
+ nvdimm_name(nvdimm));
return rc;
}
rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk);
if (rc < 0) {
- dev_dbg(dev, "%s: %s failed get DIMM flags\n",
- __func__, nvdimm_name(nvdimm));
+ dev_dbg(dev, "%s failed get DIMM flags\n",
+ nvdimm_name(nvdimm));
return rc;
}
@@ -2476,7 +2473,8 @@ static int ars_start(struct acpi_nfit_desc *acpi_desc, struct nfit_spa *nfit_spa
memset(&ars_start, 0, sizeof(ars_start));
ars_start.address = spa->address;
ars_start.length = spa->length;
- ars_start.flags = acpi_desc->ars_start_flags;
+ if (test_bit(ARS_SHORT, &nfit_spa->ars_state))
+ ars_start.flags = ND_ARS_RETURN_PREV_DATA;
if (nfit_spa_type(spa) == NFIT_SPA_PM)
ars_start.type = ND_ARS_PERSISTENT;
else if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE)
@@ -2518,16 +2516,62 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc)
int rc, cmd_rc;
rc = nd_desc->ndctl(nd_desc, NULL, ND_CMD_ARS_STATUS, ars_status,
- acpi_desc->ars_status_size, &cmd_rc);
+ acpi_desc->max_ars, &cmd_rc);
if (rc < 0)
return rc;
return cmd_rc;
}
-static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc,
- struct nd_cmd_ars_status *ars_status)
+static void ars_complete(struct acpi_nfit_desc *acpi_desc,
+ struct nfit_spa *nfit_spa)
+{
+ struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
+ struct acpi_nfit_system_address *spa = nfit_spa->spa;
+ struct nd_region *nd_region = nfit_spa->nd_region;
+ struct device *dev;
+
+ if ((ars_status->address >= spa->address && ars_status->address
+ < spa->address + spa->length)
+ || (ars_status->address < spa->address)) {
+ /*
+ * Assume that if a scrub starts at an offset from the
+ * start of nfit_spa that we are in the continuation
+ * case.
+ *
+ * Otherwise, if the scrub covers the spa range, mark
+ * any pending request complete.
+ */
+ if (ars_status->address + ars_status->length
+ >= spa->address + spa->length)
+ /* complete */;
+ else
+ return;
+ } else
+ return;
+
+ if (test_bit(ARS_DONE, &nfit_spa->ars_state))
+ return;
+
+ if (!test_and_clear_bit(ARS_REQ, &nfit_spa->ars_state))
+ return;
+
+ if (nd_region) {
+ dev = nd_region_dev(nd_region);
+ nvdimm_region_notify(nd_region, NVDIMM_REVALIDATE_POISON);
+ } else
+ dev = acpi_desc->dev;
+
+ dev_dbg(dev, "ARS: range %d %s complete\n", spa->range_index,
+ test_bit(ARS_SHORT, &nfit_spa->ars_state)
+ ? "short" : "long");
+ clear_bit(ARS_SHORT, &nfit_spa->ars_state);
+ set_bit(ARS_DONE, &nfit_spa->ars_state);
+}
+
+static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc)
{
struct nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus;
+ struct nd_cmd_ars_status *ars_status = acpi_desc->ars_status;
int rc;
u32 i;
@@ -2606,7 +2650,7 @@ static int acpi_nfit_init_mapping(struct acpi_nfit_desc *acpi_desc,
struct acpi_nfit_system_address *spa = nfit_spa->spa;
struct nd_blk_region_desc *ndbr_desc;
struct nfit_mem *nfit_mem;
- int blk_valid = 0, rc;
+ int rc;
if (!nvdimm) {
dev_err(acpi_desc->dev, "spa%d dimm: %#x not found\n",
@@ -2626,15 +2670,14 @@ static int acpi_nfit_init_mapping(struct acpi_nfit_desc *acpi_desc,
if (!nfit_mem || !nfit_mem->bdw) {
dev_dbg(acpi_desc->dev, "spa%d %s missing bdw\n",
spa->range_index, nvdimm_name(nvdimm));
- } else {
- mapping->size = nfit_mem->bdw->capacity;
- mapping->start = nfit_mem->bdw->start_address;
- ndr_desc->num_lanes = nfit_mem->bdw->windows;
- blk_valid = 1;
+ break;
}
+ mapping->size = nfit_mem->bdw->capacity;
+ mapping->start = nfit_mem->bdw->start_address;
+ ndr_desc->num_lanes = nfit_mem->bdw->windows;
ndr_desc->mapping = mapping;
- ndr_desc->num_mappings = blk_valid;
+ ndr_desc->num_mappings = 1;
ndbr_desc = to_blk_region_desc(ndr_desc);
ndbr_desc->enable = acpi_nfit_blk_region_enable;
ndbr_desc->do_io = acpi_desc->blk_do_io;
@@ -2682,8 +2725,7 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
return 0;
if (spa->range_index == 0 && !nfit_spa_is_virtual(spa)) {
- dev_dbg(acpi_desc->dev, "%s: detected invalid spa index\n",
- __func__);
+ dev_dbg(acpi_desc->dev, "detected invalid spa index\n");
return 0;
}
@@ -2769,301 +2811,243 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
return rc;
}
-static int ars_status_alloc(struct acpi_nfit_desc *acpi_desc,
- u32 max_ars)
+static int ars_status_alloc(struct acpi_nfit_desc *acpi_desc)
{
struct device *dev = acpi_desc->dev;
struct nd_cmd_ars_status *ars_status;
- if (acpi_desc->ars_status && acpi_desc->ars_status_size >= max_ars) {
- memset(acpi_desc->ars_status, 0, acpi_desc->ars_status_size);
+ if (acpi_desc->ars_status) {
+ memset(acpi_desc->ars_status, 0, acpi_desc->max_ars);
return 0;
}
- if (acpi_desc->ars_status)
- devm_kfree(dev, acpi_desc->ars_status);
- acpi_desc->ars_status = NULL;
- ars_status = devm_kzalloc(dev, max_ars, GFP_KERNEL);
+ ars_status = devm_kzalloc(dev, acpi_desc->max_ars, GFP_KERNEL);
if (!ars_status)
return -ENOMEM;
acpi_desc->ars_status = ars_status;
- acpi_desc->ars_status_size = max_ars;
return 0;
}
-static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc,
- struct nfit_spa *nfit_spa)
+static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc)
{
- struct acpi_nfit_system_address *spa = nfit_spa->spa;
int rc;
- if (!nfit_spa->max_ars) {
- struct nd_cmd_ars_cap ars_cap;
-
- memset(&ars_cap, 0, sizeof(ars_cap));
- rc = ars_get_cap(acpi_desc, &ars_cap, nfit_spa);
- if (rc < 0)
- return rc;
- nfit_spa->max_ars = ars_cap.max_ars_out;
- nfit_spa->clear_err_unit = ars_cap.clear_err_unit;
- /* check that the supported scrub types match the spa type */
- if (nfit_spa_type(spa) == NFIT_SPA_VOLATILE &&
- ((ars_cap.status >> 16) & ND_ARS_VOLATILE) == 0)
- return -ENOTTY;
- else if (nfit_spa_type(spa) == NFIT_SPA_PM &&
- ((ars_cap.status >> 16) & ND_ARS_PERSISTENT) == 0)

This diff is incomplete. Download the complete patch.

drivers/acpi/nfit/mce.c

View file

This diff is incomplete. Download the complete patch.

drivers/acpi/nfit/nfit.h

View file

This diff is incomplete. Download the complete patch.

drivers/dax/Kconfig

View file

This diff is incomplete. Download the complete patch.

drivers/dax/device.c

View file

This diff is incomplete. Download the complete patch.

drivers/dax/pmem.c

View file

This diff is incomplete. Download the complete patch.

drivers/dax/super.c

View file

This diff is incomplete. Download the complete patch.

drivers/md/Kconfig

View file

This diff is incomplete. Download the complete patch.

drivers/md/dm-linear.c

View file

This diff is incomplete. Download the complete patch.

drivers/md/dm-log-writes.c

View file

This diff is incomplete. Download the complete patch.

drivers/md/dm-stripe.c

View file

This diff is incomplete. Download the complete patch.

drivers/md/dm.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/Kconfig

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/Makefile

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/btt_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/bus.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/claim.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/core.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/dax_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/dimm.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/dimm_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/label.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/label.h

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/namespace_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/nd.h

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/of_pmem.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/pfn_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/pmem.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/region.c

View file

This diff is incomplete. Download the complete patch.

drivers/nvdimm/region_devs.c

View file

This diff is incomplete. Download the complete patch.

drivers/s390/block/Kconfig

View file

This diff is incomplete. Download the complete patch.

fs/block_dev.c

View file

This diff is incomplete. Download the complete patch.

fs/dax.c

View file

This diff is incomplete. Download the complete patch.

fs/ext2/ext2.h

View file

This diff is incomplete. Download the complete patch.

fs/ext2/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/ext2/namei.c

View file

This diff is incomplete. Download the complete patch.

fs/ext4/inode.c

View file

This diff is incomplete. Download the complete patch.

fs/libfs.c

View file

This diff is incomplete. Download the complete patch.

fs/xfs/xfs_aops.c

View file

This diff is incomplete. Download the complete patch.

fs/xfs/xfs_aops.h

View file

This diff is incomplete. Download the complete patch.

fs/xfs/xfs_iops.c

View file

This diff is incomplete. Download the complete patch.

include/linux/dax.h

View file

This diff is incomplete. Download the complete patch.

include/linux/fs.h

View file

This diff is incomplete. Download the complete patch.

include/linux/libnvdimm.h

View file

This diff is incomplete. Download the complete patch.

include/linux/nd.h

View file

This diff is incomplete. Download the complete patch.

tools/testing/nvdimm/test/nfit.c

View file

This diff is incomplete. Download the complete patch.

tools/testing/nvdimm/test/nfit_test.h

View file

This diff is incomplete. Download the complete patch.