Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

Pull libnvdimm fixes from Dan Williams:
 "A regression fix, new unit test infrastructure and a build fix:

   - Regression fix addressing support for the new NVDIMM label storage
     area access commands (_LSI, _LSR, and _LSW).

     The Intel specific version of these commands communicated the
     "Device Locked" status on the label-storage-information command.

     However, these new commands (standardized in ACPI 6.2) communicate
     the "Device Locked" status on the label-storage-read command, and
     the driver was missing the indication.

     Reading from locked persistent memory is similar to reading
     unmapped PCI memory space, returns all 1's.

   - Unit test infrastructure is added to regression test the "Device
     Locked" detection failure.

   - A build fix is included to allow the "of_pmem" driver to be built
     as a module and translate an Open Firmware described device to its
     local numa node"

* 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
  MAINTAINERS: Add backup maintainers for libnvdimm and DAX
  device-dax: allow MAP_SYNC to succeed
  Revert "libnvdimm, of_pmem: workaround OF_NUMA=n build error"
  libnvdimm, of_pmem: use dev_to_node() instead of of_node_to_nid()
  tools/testing/nvdimm: enable labels for nfit_test.1 dimms
  tools/testing/nvdimm: fix missing newline in nfit_test_dimm 'handle' attribute
  tools/testing/nvdimm: support nfit_test_dimm attributes under nfit_test.1
  tools/testing/nvdimm: allow custom error code injection
  libnvdimm, dimm: handle EACCES failures from label reads
This commit is contained in:
Linus Torvalds
2018-04-21 21:11:05 -07:00
6 changed files with 96 additions and 32 deletions

View File

@@ -138,6 +138,7 @@ static u32 handle[] = {
};
static unsigned long dimm_fail_cmd_flags[NUM_DCR];
static int dimm_fail_cmd_code[NUM_DCR];
struct nfit_test_fw {
enum intel_fw_update_state state;
@@ -892,8 +893,11 @@ static int get_dimm(struct nfit_mem *nfit_mem, unsigned int func)
if (i >= ARRAY_SIZE(handle))
return -ENXIO;
if ((1 << func) & dimm_fail_cmd_flags[i])
if ((1 << func) & dimm_fail_cmd_flags[i]) {
if (dimm_fail_cmd_code[i])
return dimm_fail_cmd_code[i];
return -EIO;
}
return i;
}
@@ -1162,12 +1166,12 @@ static int ars_state_init(struct device *dev, struct ars_state *ars_state)
static void put_dimms(void *data)
{
struct device **dimm_dev = data;
struct nfit_test *t = data;
int i;
for (i = 0; i < NUM_DCR; i++)
if (dimm_dev[i])
device_unregister(dimm_dev[i]);
for (i = 0; i < t->num_dcr; i++)
if (t->dimm_dev[i])
device_unregister(t->dimm_dev[i]);
}
static struct class *nfit_test_dimm;
@@ -1176,13 +1180,11 @@ static int dimm_name_to_id(struct device *dev)
{
int dimm;
if (sscanf(dev_name(dev), "test_dimm%d", &dimm) != 1
|| dimm >= NUM_DCR || dimm < 0)
if (sscanf(dev_name(dev), "test_dimm%d", &dimm) != 1)
return -ENXIO;
return dimm;
}
static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -1191,7 +1193,7 @@ static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
if (dimm < 0)
return dimm;
return sprintf(buf, "%#x", handle[dimm]);
return sprintf(buf, "%#x\n", handle[dimm]);
}
DEVICE_ATTR_RO(handle);
@@ -1225,8 +1227,39 @@ static ssize_t fail_cmd_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(fail_cmd);
static ssize_t fail_cmd_code_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
int dimm = dimm_name_to_id(dev);
if (dimm < 0)
return dimm;
return sprintf(buf, "%d\n", dimm_fail_cmd_code[dimm]);
}
static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
{
int dimm = dimm_name_to_id(dev);
unsigned long val;
ssize_t rc;
if (dimm < 0)
return dimm;
rc = kstrtol(buf, 0, &val);
if (rc)
return rc;
dimm_fail_cmd_code[dimm] = val;
return size;
}
static DEVICE_ATTR_RW(fail_cmd_code);
static struct attribute *nfit_test_dimm_attributes[] = {
&dev_attr_fail_cmd.attr,
&dev_attr_fail_cmd_code.attr,
&dev_attr_handle.attr,
NULL,
};
@@ -1240,6 +1273,23 @@ static const struct attribute_group *nfit_test_dimm_attribute_groups[] = {
NULL,
};
static int nfit_test_dimm_init(struct nfit_test *t)
{
int i;
if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t))
return -ENOMEM;
for (i = 0; i < t->num_dcr; i++) {
t->dimm_dev[i] = device_create_with_groups(nfit_test_dimm,
&t->pdev.dev, 0, NULL,
nfit_test_dimm_attribute_groups,
"test_dimm%d", i + t->dcr_idx);
if (!t->dimm_dev[i])
return -ENOMEM;
}
return 0;
}
static void smart_init(struct nfit_test *t)
{
int i;
@@ -1335,17 +1385,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
if (!t->_fit)
return -ENOMEM;
if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t->dimm_dev))
if (nfit_test_dimm_init(t))
return -ENOMEM;
for (i = 0; i < NUM_DCR; i++) {
t->dimm_dev[i] = device_create_with_groups(nfit_test_dimm,
&t->pdev.dev, 0, NULL,
nfit_test_dimm_attribute_groups,
"test_dimm%d", i);
if (!t->dimm_dev[i])
return -ENOMEM;
}
smart_init(t);
return ars_state_init(&t->pdev.dev, &t->ars_state);
}
@@ -1377,6 +1418,8 @@ static int nfit_test1_alloc(struct nfit_test *t)
if (!t->spa_set[1])
return -ENOMEM;
if (nfit_test_dimm_init(t))
return -ENOMEM;
smart_init(t);
return ars_state_init(&t->pdev.dev, &t->ars_state);
}
@@ -2222,6 +2265,9 @@ static void nfit_test1_setup(struct nfit_test *t)
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
set_bit(ND_INTEL_ENABLE_LSS_STATUS, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
}
static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,