Commit d6eb270c authored by Dan Williams's avatar Dan Williams

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: aef25338 ("libnvdimm, nfit: centralize command status translation")
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent 82aa37cf
...@@ -94,7 +94,7 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc) ...@@ -94,7 +94,7 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
return to_acpi_device(acpi_desc->dev); 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_clear_error *clear_err;
struct nd_cmd_ars_status *ars_status; struct nd_cmd_ars_status *ars_status;
...@@ -175,6 +175,16 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) ...@@ -175,6 +175,16 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
return 0; 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, static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
struct nvdimm *nvdimm, unsigned int cmd, void *buf, struct nvdimm *nvdimm, unsigned int cmd, void *buf,
unsigned int buf_len, int *cmd_rc) unsigned int buf_len, int *cmd_rc)
...@@ -335,7 +345,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, ...@@ -335,7 +345,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
*/ */
rc = buf_len - offset - in_buf.buffer.length; rc = buf_len - offset - in_buf.buffer.length;
if (cmd_rc) if (cmd_rc)
*cmd_rc = xlat_status(buf, cmd, fw_status); *cmd_rc = xlat_status(nvdimm, buf, cmd,
fw_status);
} else { } else {
dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n", dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n",
__func__, dimm_name, cmd_name, buf_len, __func__, dimm_name, cmd_name, buf_len,
...@@ -345,7 +356,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, ...@@ -345,7 +356,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
} else { } else {
rc = 0; rc = 0;
if (cmd_rc) if (cmd_rc)
*cmd_rc = xlat_status(buf, cmd, fw_status); *cmd_rc = xlat_status(nvdimm, buf, cmd, fw_status);
} }
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment