aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-12-06 15:06:55 -0800
committerDan Williams <dan.j.williams@intel.com>2016-12-06 16:30:37 -0800
commitd6eb270c57fef35798525004ddf2ac5dcdadd43b (patch)
tree5ffbbc6b4585a5df44dc7d5b9017188469252684
parentacpi, nfit: validate ars_status output buffer size (diff)
downloadlinux-dev-d6eb270c57fef35798525004ddf2ac5dcdadd43b.tar.xz
linux-dev-d6eb270c57fef35798525004ddf2ac5dcdadd43b.zip
acpi, nfit: fix bus vs dimm confusion in xlat_status
Given dimms and bus commands share the same command number space we need to be careful that we are translating status in the correct context. Otherwise we can, for example, fail an ND_CMD_GET_CONFIG_SIZE command because max_xfer is zero. It fails because that condition erroneously correlates with the 'cleared == 0' failure of ND_CMD_CLEAR_ERROR. Cc: <stable@vger.kernel.org> Fixes: aef253382266 ("libnvdimm, nfit: centralize command status translation") Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r--drivers/acpi/nfit/core.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 4b8b4f520d76..09d3db322ee8 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -94,7 +94,7 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
return to_acpi_device(acpi_desc->dev);
}
-static int xlat_status(void *buf, unsigned int cmd, u32 status)
+static int xlat_bus_status(void *buf, unsigned int cmd, u32 status)
{
struct nd_cmd_clear_error *clear_err;
struct nd_cmd_ars_status *ars_status;
@@ -175,6 +175,16 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
return 0;
}
+static int xlat_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd,
+ u32 status)
+{
+ if (!nvdimm)
+ return xlat_bus_status(buf, cmd, status);
+ if (status)
+ return -EIO;
+ return 0;
+}
+
static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc)
@@ -335,7 +345,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
*/
rc = buf_len - offset - in_buf.buffer.length;
if (cmd_rc)
- *cmd_rc = xlat_status(buf, cmd, fw_status);
+ *cmd_rc = xlat_status(nvdimm, buf, cmd,
+ fw_status);
} else {
dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n",
__func__, dimm_name, cmd_name, buf_len,
@@ -345,7 +356,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
} else {
rc = 0;
if (cmd_rc)
- *cmd_rc = xlat_status(buf, cmd, fw_status);
+ *cmd_rc = xlat_status(nvdimm, buf, cmd, fw_status);
}
out: