Skip to content

Commit

Permalink
Merge tag 'libnvdimm-for-4.19_misc' of gitolite.kernel.org:pub/scm/li…
Browse files Browse the repository at this point in the history
…nux/kernel/git/nvdimm/nvdimm

Pull libnvdimm updates from Dave Jiang:
 "Collection of misc libnvdimm patches for 4.19 submission:

   - Adding support to read locked nvdimm capacity.

   - Change test code to make DSM failure code injection an override.

   - Add support for calculate maximum contiguous area for namespace.

   - Add support for queueing a short ARS when there is on going ARS for
     nvdimm.

   - Allow NULL to be passed in to ->direct_access() for kaddr and pfn
     params.

   - Improve smart injection support for nvdimm emulation testing.

   - Fix test code that supports for emulating controller temperature.

   - Fix hang on error before devm_memremap_pages()

   - Fix a bug that causes user memory corruption when data returned to
     user for ars_status.

   - Maintainer updates for Ross Zwisler emails and adding Jan Kara to
     fsdax"

* tag 'libnvdimm-for-4.19_misc' of gitolite.kernel.org:pub/scm/linux/kernel/git/nvdimm/nvdimm:
  libnvdimm: fix ars_status output length calculation
  device-dax: avoid hang on error before devm_memremap_pages()
  tools/testing/nvdimm: improve emulation of smart injection
  filesystem-dax: Do not request kaddr and pfn when not required
  md/dm-writecache: Don't request pointer dummy_addr when not required
  dax/super: Do not request a pointer kaddr when not required
  tools/testing/nvdimm: kaddr and pfn can be NULL to ->direct_access()
  s390, dcssblk: kaddr and pfn can be NULL to ->direct_access()
  libnvdimm, pmem: kaddr and pfn can be NULL to ->direct_access()
  acpi/nfit: queue issuing of ars when an uc error notification comes in
  libnvdimm: Export max available extent
  libnvdimm: Use max contiguous area for namespace size
  MAINTAINERS: Add Jan Kara for filesystem DAX
  MAINTAINERS: update Ross Zwisler's email address
  tools/testing/nvdimm: Fix support for emulating controller temperature
  tools/testing/nvdimm: Make DSM failure code injection an override
  acpi, nfit: Prefer _DSM over _LSR for namespace label reads
  libnvdimm: Introduce locked DIMM capacity support
  • Loading branch information
torvalds committed Aug 26, 2018
2 parents b326272 + 286e877 commit 828bf6e
Show file tree
Hide file tree
Showing 19 changed files with 270 additions and 90 deletions.
1 change: 1 addition & 0 deletions .mailmap
Expand Up @@ -159,6 +159,7 @@ Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
Randy Dunlap <rdunlap@infradead.org> <rdunlap@xenotime.net>
Rémi Denis-Courmont <rdenis@simphalempin.com>
Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
Ross Zwisler <zwisler@kernel.org> <ross.zwisler@linux.intel.com>
Rudolf Marek <R.Marek@sh.cvut.cz>
Rui Saraiva <rmps@joel.ist.utl.pt>
Sachin P Sant <ssant@in.ibm.com>
Expand Down
13 changes: 7 additions & 6 deletions MAINTAINERS
Expand Up @@ -4364,7 +4364,8 @@ F: drivers/i2c/busses/i2c-diolan-u2c.c

FILESYSTEM DIRECT ACCESS (DAX)
M: Matthew Wilcox <mawilcox@microsoft.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Ross Zwisler <zwisler@kernel.org>
M: Jan Kara <jack@suse.cz>
L: linux-fsdevel@vger.kernel.org
S: Supported
F: fs/dax.c
Expand All @@ -4374,7 +4375,7 @@ F: include/trace/events/fs_dax.h
DEVICE DIRECT ACCESS (DAX)
M: Dan Williams <dan.j.williams@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Ross Zwisler <zwisler@kernel.org>
M: Vishal Verma <vishal.l.verma@intel.com>
L: linux-nvdimm@lists.01.org
S: Supported
Expand Down Expand Up @@ -8303,7 +8304,7 @@ S: Maintained
F: tools/lib/lockdep/

LIBNVDIMM BLK: MMIO-APERTURE DRIVER
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Ross Zwisler <zwisler@kernel.org>
M: Dan Williams <dan.j.williams@intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
Expand All @@ -8316,15 +8317,15 @@ F: drivers/nvdimm/region_devs.c
LIBNVDIMM BTT: BLOCK TRANSLATION TABLE
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dan Williams <dan.j.williams@intel.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Ross Zwisler <zwisler@kernel.org>
M: Dave Jiang <dave.jiang@intel.com>
L: linux-nvdimm@lists.01.org
Q: https://patchwork.kernel.org/project/linux-nvdimm/list/
S: Supported
F: drivers/nvdimm/btt*

LIBNVDIMM PMEM: PERSISTENT MEMORY DRIVER
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Ross Zwisler <zwisler@kernel.org>
M: Dan Williams <dan.j.williams@intel.com>
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
Expand All @@ -8343,7 +8344,7 @@ F: Documentation/devicetree/bindings/pmem/pmem-region.txt

LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
M: Dan Williams <dan.j.williams@intel.com>
M: Ross Zwisler <ross.zwisler@linux.intel.com>
M: Ross Zwisler <zwisler@kernel.org>
M: Vishal Verma <vishal.l.verma@intel.com>
M: Dave Jiang <dave.jiang@intel.com>
L: linux-nvdimm@lists.01.org
Expand Down
24 changes: 20 additions & 4 deletions drivers/acpi/nfit/core.c
Expand Up @@ -1699,7 +1699,7 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
{
struct acpi_device *adev, *adev_dimm;
struct device *dev = acpi_desc->dev;
unsigned long dsm_mask;
unsigned long dsm_mask, label_mask;
const guid_t *guid;
int i;
int family = -1;
Expand Down Expand Up @@ -1771,6 +1771,16 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
1ULL << i))
set_bit(i, &nfit_mem->dsm_mask);

/*
* Prefer the NVDIMM_FAMILY_INTEL label read commands if present
* due to their better semantics handling locked capacity.
*/
label_mask = 1 << ND_CMD_GET_CONFIG_SIZE | 1 << ND_CMD_GET_CONFIG_DATA
| 1 << ND_CMD_SET_CONFIG_DATA;
if (family == NVDIMM_FAMILY_INTEL
&& (dsm_mask & label_mask) == label_mask)
return 0;

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));
Expand Down Expand Up @@ -2559,7 +2569,12 @@ static void ars_complete(struct acpi_nfit_desc *acpi_desc,
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);
if (test_and_clear_bit(ARS_REQ_REDO, &nfit_spa->ars_state)) {
set_bit(ARS_SHORT, &nfit_spa->ars_state);
set_bit(ARS_REQ, &nfit_spa->ars_state);
dev_dbg(dev, "ARS: processing scrub request received while in progress\n");
} else
set_bit(ARS_DONE, &nfit_spa->ars_state);
}

static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc)
Expand Down Expand Up @@ -3256,9 +3271,10 @@ int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, unsigned long flags)
if (test_bit(ARS_FAILED, &nfit_spa->ars_state))
continue;

if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state))
if (test_and_set_bit(ARS_REQ, &nfit_spa->ars_state)) {
busy++;
else {
set_bit(ARS_REQ_REDO, &nfit_spa->ars_state);
} else {
if (test_bit(ARS_SHORT, &flags))
set_bit(ARS_SHORT, &nfit_spa->ars_state);
scheduled++;
Expand Down
1 change: 1 addition & 0 deletions drivers/acpi/nfit/nfit.h
Expand Up @@ -119,6 +119,7 @@ enum nfit_dimm_notifiers {

enum nfit_ars_state {
ARS_REQ,
ARS_REQ_REDO,
ARS_DONE,
ARS_SHORT,
ARS_FAILED,
Expand Down
12 changes: 8 additions & 4 deletions drivers/dax/pmem.c
Expand Up @@ -105,15 +105,19 @@ static int dax_pmem_probe(struct device *dev)
if (rc)
return rc;

rc = devm_add_action_or_reset(dev, dax_pmem_percpu_exit,
&dax_pmem->ref);
if (rc)
rc = devm_add_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
if (rc) {
percpu_ref_exit(&dax_pmem->ref);
return rc;
}

dax_pmem->pgmap.ref = &dax_pmem->ref;
addr = devm_memremap_pages(dev, &dax_pmem->pgmap);
if (IS_ERR(addr))
if (IS_ERR(addr)) {
devm_remove_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
percpu_ref_exit(&dax_pmem->ref);
return PTR_ERR(addr);
}

rc = devm_add_action_or_reset(dev, dax_pmem_percpu_kill,
&dax_pmem->ref);
Expand Down
3 changes: 1 addition & 2 deletions drivers/dax/super.c
Expand Up @@ -89,7 +89,6 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
struct request_queue *q;
pgoff_t pgoff;
int err, id;
void *kaddr;
pfn_t pfn;
long len;
char buf[BDEVNAME_SIZE];
Expand Down Expand Up @@ -122,7 +121,7 @@ bool __bdev_dax_supported(struct block_device *bdev, int blocksize)
}

id = dax_read_lock();
len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
len = dax_direct_access(dax_dev, pgoff, 1, NULL, &pfn);
dax_read_unlock(id);

put_dax(dax_dev);
Expand Down
3 changes: 1 addition & 2 deletions drivers/md/dm-writecache.c
Expand Up @@ -268,9 +268,8 @@ static int persistent_memory_claim(struct dm_writecache *wc)
i = 0;
do {
long daa;
void *dummy_addr;
daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i,
&dummy_addr, &pfn);
NULL, &pfn);
if (daa <= 0) {
r = daa ? daa : -EINVAL;
goto err3;
Expand Down
4 changes: 2 additions & 2 deletions drivers/nvdimm/bus.c
Expand Up @@ -812,9 +812,9 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
* overshoots the remainder by 4 bytes, assume it was
* including 'status'.
*/
if (out_field[1] - 8 == remainder)
if (out_field[1] - 4 == remainder)
return remainder;
return out_field[1] - 4;
return out_field[1] - 8;
} else if (cmd == ND_CMD_CALL) {
struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field;

Expand Down
24 changes: 22 additions & 2 deletions drivers/nvdimm/dimm.c
Expand Up @@ -34,6 +34,9 @@ static int nvdimm_probe(struct device *dev)
return rc;
}

/* reset locked, to be validated below... */
nvdimm_clear_locked(dev);

ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
if (!ndd)
return -ENOMEM;
Expand All @@ -48,12 +51,30 @@ static int nvdimm_probe(struct device *dev)
get_device(dev);
kref_init(&ndd->kref);

/*
* EACCES failures reading the namespace label-area-properties
* are interpreted as the DIMM capacity being locked but the
* namespace labels themselves being accessible.
*/
rc = nvdimm_init_nsarea(ndd);
if (rc == -EACCES)
if (rc == -EACCES) {
/*
* See nvdimm_namespace_common_probe() where we fail to
* allow namespaces to probe while the DIMM is locked,
* but we do allow for namespace enumeration.
*/
nvdimm_set_locked(dev);
rc = 0;
}
if (rc)
goto err;

/*
* EACCES failures reading the namespace label-data are
* interpreted as the label area being locked in addition to the
* DIMM capacity. We fail the dimm probe to prevent regions from
* attempting to parse the label area.
*/
rc = nvdimm_init_config_data(ndd);
if (rc == -EACCES)
nvdimm_set_locked(dev);
Expand All @@ -72,7 +93,6 @@ static int nvdimm_probe(struct device *dev)
if (rc == 0)
nvdimm_set_aliasing(dev);
}
nvdimm_clear_locked(dev);
nvdimm_bus_unlock(dev);

if (rc)
Expand Down
31 changes: 31 additions & 0 deletions drivers/nvdimm/dimm_devs.c
Expand Up @@ -536,6 +536,37 @@ resource_size_t nd_blk_available_dpa(struct nd_region *nd_region)
return info.available;
}

/**
* nd_pmem_max_contiguous_dpa - For the given dimm+region, return the max
* contiguous unallocated dpa range.
* @nd_region: constrain available space check to this reference region
* @nd_mapping: container of dpa-resource-root + labels
*/
resource_size_t nd_pmem_max_contiguous_dpa(struct nd_region *nd_region,
struct nd_mapping *nd_mapping)
{
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
struct nvdimm_bus *nvdimm_bus;
resource_size_t max = 0;
struct resource *res;

/* if a dimm is disabled the available capacity is zero */
if (!ndd)
return 0;

nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
if (__reserve_free_pmem(&nd_region->dev, nd_mapping->nvdimm))
return 0;
for_each_dpa_resource(ndd, res) {
if (strcmp(res->name, "pmem-reserve") != 0)
continue;
if (resource_size(res) > max)
max = resource_size(res);
}
release_free_pmem(nvdimm_bus, nd_mapping);
return max;
}

/**
* nd_pmem_available_dpa - for the given dimm+region account unallocated dpa
* @nd_mapping: container of dpa-resource-root + labels
Expand Down
29 changes: 26 additions & 3 deletions drivers/nvdimm/namespace_devs.c
Expand Up @@ -799,7 +799,7 @@ static int merge_dpa(struct nd_region *nd_region,
return 0;
}

static int __reserve_free_pmem(struct device *dev, void *data)
int __reserve_free_pmem(struct device *dev, void *data)
{
struct nvdimm *nvdimm = data;
struct nd_region *nd_region;
Expand Down Expand Up @@ -836,7 +836,7 @@ static int __reserve_free_pmem(struct device *dev, void *data)
return 0;
}

static void release_free_pmem(struct nvdimm_bus *nvdimm_bus,
void release_free_pmem(struct nvdimm_bus *nvdimm_bus,
struct nd_mapping *nd_mapping)
{
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
Expand Down Expand Up @@ -1032,7 +1032,7 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)

allocated += nvdimm_allocated_dpa(ndd, &label_id);
}
available = nd_region_available_dpa(nd_region);
available = nd_region_allocatable_dpa(nd_region);

if (val > available + allocated)
return -ENOSPC;
Expand Down Expand Up @@ -1144,6 +1144,26 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns)
}
EXPORT_SYMBOL(nvdimm_namespace_capacity);

bool nvdimm_namespace_locked(struct nd_namespace_common *ndns)
{
int i;
bool locked = false;
struct device *dev = &ndns->dev;
struct nd_region *nd_region = to_nd_region(dev->parent);

for (i = 0; i < nd_region->ndr_mappings; i++) {
struct nd_mapping *nd_mapping = &nd_region->mapping[i];
struct nvdimm *nvdimm = nd_mapping->nvdimm;

if (test_bit(NDD_LOCKED, &nvdimm->flags)) {
dev_dbg(dev, "%s locked\n", nvdimm_name(nvdimm));
locked = true;
}
}
return locked;
}
EXPORT_SYMBOL(nvdimm_namespace_locked);

static ssize_t size_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
Expand Down Expand Up @@ -1695,6 +1715,9 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
}
}

if (nvdimm_namespace_locked(ndns))
return ERR_PTR(-EACCES);

size = nvdimm_namespace_capacity(ndns);
if (size < ND_MIN_NAMESPACE_SIZE) {
dev_dbg(&ndns->dev, "%pa, too small must be at least %#x\n",
Expand Down
8 changes: 8 additions & 0 deletions drivers/nvdimm/nd-core.h
Expand Up @@ -100,6 +100,14 @@ struct nd_region;
struct nvdimm_drvdata;
struct nd_mapping;
void nd_mapping_free_labels(struct nd_mapping *nd_mapping);

int __reserve_free_pmem(struct device *dev, void *data);
void release_free_pmem(struct nvdimm_bus *nvdimm_bus,
struct nd_mapping *nd_mapping);

resource_size_t nd_pmem_max_contiguous_dpa(struct nd_region *nd_region,
struct nd_mapping *nd_mapping);
resource_size_t nd_region_allocatable_dpa(struct nd_region *nd_region);
resource_size_t nd_pmem_available_dpa(struct nd_region *nd_region,
struct nd_mapping *nd_mapping, resource_size_t *overlap);
resource_size_t nd_blk_available_dpa(struct nd_region *nd_region);
Expand Down
1 change: 1 addition & 0 deletions drivers/nvdimm/nd.h
Expand Up @@ -357,6 +357,7 @@ struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd,
struct nd_label_id *label_id, resource_size_t start,
resource_size_t n);
resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns);
bool nvdimm_namespace_locked(struct nd_namespace_common *ndns);
struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev);
int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns);
int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt);
Expand Down
7 changes: 5 additions & 2 deletions drivers/nvdimm/pmem.c
Expand Up @@ -226,8 +226,11 @@ __weak long __pmem_direct_access(struct pmem_device *pmem, pgoff_t pgoff,
if (unlikely(is_bad_pmem(&pmem->bb, PFN_PHYS(pgoff) / 512,
PFN_PHYS(nr_pages))))
return -EIO;
*kaddr = pmem->virt_addr + offset;
*pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);

if (kaddr)
*kaddr = pmem->virt_addr + offset;
if (pfn)
*pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);

/*
* If badblocks are present, limit known good range to the
Expand Down

0 comments on commit 828bf6e

Please sign in to comment.