* [PATCH 1/5] libnvdimm, dimm: handle EACCES failures from label reads
2018-04-10 22:39 [PATCH 0/5] libnvdimm: fix locked status detection Dan Williams
@ 2018-04-10 22:39 ` Dan Williams
2018-04-10 22:39 ` [PATCH 2/5] tools/testing/nvdimm: allow custom error code injection Dan Williams
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-10 22:39 UTC (permalink / raw)
To: linux-nvdimm; +Cc: stable, linux-acpi, linux-kernel
The new support for the standard _LSR and _LSW methods neglected to also
update the nvdimm_init_config_data() and nvdimm_set_config_data() to
return the translated error code from failed commands. This precision is
necessary because the locked status that was previously returned on
ND_CMD_GET_CONFIG_SIZE commands is now returned on
ND_CMD_{GET,SET}_CONFIG_DATA commands.
If the kernel misses this indication it can inadvertently fall back to
label-less mode when it should otherwise avoid all access to locked
regions.
Cc: <stable@vger.kernel.org>
Fixes: 4b27db7e26cd ("acpi, nfit: add support for the _LSI, _LSR, and...")
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/nvdimm/dimm_devs.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index e00d45522b80..8d348b22ba45 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -88,9 +88,9 @@ int nvdimm_init_nsarea(struct nvdimm_drvdata *ndd)
int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
{
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
+ int rc = validate_dimm(ndd), cmd_rc = 0;
struct nd_cmd_get_config_data_hdr *cmd;
struct nvdimm_bus_descriptor *nd_desc;
- int rc = validate_dimm(ndd);
u32 max_cmd_size, config_size;
size_t offset;
@@ -124,9 +124,11 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
cmd->in_offset = offset;
rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
ND_CMD_GET_CONFIG_DATA, cmd,
- cmd->in_length + sizeof(*cmd), NULL);
- if (rc || cmd->status) {
- rc = -ENXIO;
+ cmd->in_length + sizeof(*cmd), &cmd_rc);
+ if (rc < 0)
+ break;
+ if (cmd_rc < 0) {
+ rc = cmd_rc;
break;
}
memcpy(ndd->data + offset, cmd->out_buf, cmd->in_length);
@@ -140,9 +142,9 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
void *buf, size_t len)
{
- int rc = validate_dimm(ndd);
size_t max_cmd_size, buf_offset;
struct nd_cmd_set_config_hdr *cmd;
+ int rc = validate_dimm(ndd), cmd_rc = 0;
struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(ndd->dev);
struct nvdimm_bus_descriptor *nd_desc = nvdimm_bus->nd_desc;
@@ -164,7 +166,6 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
for (buf_offset = 0; len; len -= cmd->in_length,
buf_offset += cmd->in_length) {
size_t cmd_size;
- u32 *status;
cmd->in_offset = offset + buf_offset;
cmd->in_length = min(max_cmd_size, len);
@@ -172,12 +173,13 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset,
/* status is output in the last 4-bytes of the command buffer */
cmd_size = sizeof(*cmd) + cmd->in_length + sizeof(u32);
- status = ((void *) cmd) + cmd_size - sizeof(u32);
rc = nd_desc->ndctl(nd_desc, to_nvdimm(ndd->dev),
- ND_CMD_SET_CONFIG_DATA, cmd, cmd_size, NULL);
- if (rc || *status) {
- rc = rc ? rc : -ENXIO;
+ ND_CMD_SET_CONFIG_DATA, cmd, cmd_size, &cmd_rc);
+ if (rc < 0)
+ break;
+ if (cmd_rc < 0) {
+ rc = cmd_rc;
break;
}
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/5] tools/testing/nvdimm: allow custom error code injection
2018-04-10 22:39 [PATCH 0/5] libnvdimm: fix locked status detection Dan Williams
2018-04-10 22:39 ` [PATCH 1/5] libnvdimm, dimm: handle EACCES failures from label reads Dan Williams
@ 2018-04-10 22:39 ` Dan Williams
2018-04-10 22:39 ` [PATCH 3/5] tools/testing/nvdimm: support nfit_test_dimm attributes under nfit_test.1 Dan Williams
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-10 22:39 UTC (permalink / raw)
To: linux-nvdimm; +Cc: linux-acpi, linux-kernel
Given that libnvdimm driver stack takes specific actions on DIMM command
error codes like -EACCES, provide a facility to inject custom failures.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/nvdimm/test/nfit.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index cb166be4918d..dc6cf5630280 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -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;
}
@@ -1225,8 +1229,40 @@ 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,
};
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/5] tools/testing/nvdimm: support nfit_test_dimm attributes under nfit_test.1
2018-04-10 22:39 [PATCH 0/5] libnvdimm: fix locked status detection Dan Williams
2018-04-10 22:39 ` [PATCH 1/5] libnvdimm, dimm: handle EACCES failures from label reads Dan Williams
2018-04-10 22:39 ` [PATCH 2/5] tools/testing/nvdimm: allow custom error code injection Dan Williams
@ 2018-04-10 22:39 ` Dan Williams
2018-04-10 22:39 ` [PATCH 4/5] tools/testing/nvdimm: fix missing newline in nfit_test_dimm 'handle' attribute Dan Williams
2018-04-10 22:39 ` [PATCH 5/5] tools/testing/nvdimm: enable labels for nfit_test.1 dimms Dan Williams
4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-10 22:39 UTC (permalink / raw)
To: linux-nvdimm; +Cc: linux-acpi, linux-kernel
The nfit_test.1 bus provides a pmem topology without blk-aperture
enabling, so it presents different failure modes for label space
handling. Allow custom DSM command error injection.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/nvdimm/test/nfit.c | 43 ++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 18 deletions(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index dc6cf5630280..c8c88363311b 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1166,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;
@@ -1180,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)
{
@@ -1259,7 +1257,6 @@ static ssize_t fail_cmd_code_store(struct device *dev, struct device_attribute *
}
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,
@@ -1276,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;
@@ -1371,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);
}
@@ -1413,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);
}
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/5] tools/testing/nvdimm: fix missing newline in nfit_test_dimm 'handle' attribute
2018-04-10 22:39 [PATCH 0/5] libnvdimm: fix locked status detection Dan Williams
` (2 preceding siblings ...)
2018-04-10 22:39 ` [PATCH 3/5] tools/testing/nvdimm: support nfit_test_dimm attributes under nfit_test.1 Dan Williams
@ 2018-04-10 22:39 ` Dan Williams
2018-04-10 22:39 ` [PATCH 5/5] tools/testing/nvdimm: enable labels for nfit_test.1 dimms Dan Williams
4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-10 22:39 UTC (permalink / raw)
To: linux-nvdimm; +Cc: linux-acpi, linux-kernel
Sysfs userspace tooling generally expects the kernel to emit a newlines
when reading sysfs attributes.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/nvdimm/test/nfit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index c8c88363311b..51fc41c24a77 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -1193,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);
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5/5] tools/testing/nvdimm: enable labels for nfit_test.1 dimms
2018-04-10 22:39 [PATCH 0/5] libnvdimm: fix locked status detection Dan Williams
` (3 preceding siblings ...)
2018-04-10 22:39 ` [PATCH 4/5] tools/testing/nvdimm: fix missing newline in nfit_test_dimm 'handle' attribute Dan Williams
@ 2018-04-10 22:39 ` Dan Williams
4 siblings, 0 replies; 6+ messages in thread
From: Dan Williams @ 2018-04-10 22:39 UTC (permalink / raw)
To: linux-nvdimm; +Cc: linux-acpi, linux-kernel
Enable test cases for the kernel's fallback to label-less mode.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/nvdimm/test/nfit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 51fc41c24a77..4ea385be528f 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -2265,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,
^ permalink raw reply related [flat|nested] 6+ messages in thread