Skip to content

Commit 11294d6

Browse files
committed
nfit: fail DSMs that return non-zero status by default
For the DSMs where the kernel knows the format of the output buffer and originates those DSMs from within the kernel, return -EIO for any non-zero status. If the BIOS is indicating a status that we do not know how to handle, fail the DSM. Cc: <[email protected]> Signed-off-by: Dan Williams <[email protected]>
1 parent ecfb6d8 commit 11294d6

File tree

1 file changed

+28
-20
lines changed

1 file changed

+28
-20
lines changed

drivers/acpi/nfit/core.c

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -94,74 +94,70 @@ static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
9494
return to_acpi_device(acpi_desc->dev);
9595
}
9696

97-
static int xlat_status(void *buf, unsigned int cmd)
97+
static int xlat_status(void *buf, unsigned int cmd, u32 status)
9898
{
9999
struct nd_cmd_clear_error *clear_err;
100100
struct nd_cmd_ars_status *ars_status;
101-
struct nd_cmd_ars_start *ars_start;
102-
struct nd_cmd_ars_cap *ars_cap;
103101
u16 flags;
104102

105103
switch (cmd) {
106104
case ND_CMD_ARS_CAP:
107-
ars_cap = buf;
108-
if ((ars_cap->status & 0xffff) == NFIT_ARS_CAP_NONE)
105+
if ((status & 0xffff) == NFIT_ARS_CAP_NONE)
109106
return -ENOTTY;
110107

111108
/* Command failed */
112-
if (ars_cap->status & 0xffff)
109+
if (status & 0xffff)
113110
return -EIO;
114111

115112
/* No supported scan types for this range */
116113
flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE;
117-
if ((ars_cap->status >> 16 & flags) == 0)
114+
if ((status >> 16 & flags) == 0)
118115
return -ENOTTY;
119116
break;
120117
case ND_CMD_ARS_START:
121-
ars_start = buf;
122118
/* ARS is in progress */
123-
if ((ars_start->status & 0xffff) == NFIT_ARS_START_BUSY)
119+
if ((status & 0xffff) == NFIT_ARS_START_BUSY)
124120
return -EBUSY;
125121

126122
/* Command failed */
127-
if (ars_start->status & 0xffff)
123+
if (status & 0xffff)
128124
return -EIO;
129125
break;
130126
case ND_CMD_ARS_STATUS:
131127
ars_status = buf;
132128
/* Command failed */
133-
if (ars_status->status & 0xffff)
129+
if (status & 0xffff)
134130
return -EIO;
135131
/* Check extended status (Upper two bytes) */
136-
if (ars_status->status == NFIT_ARS_STATUS_DONE)
132+
if (status == NFIT_ARS_STATUS_DONE)
137133
return 0;
138134

139135
/* ARS is in progress */
140-
if (ars_status->status == NFIT_ARS_STATUS_BUSY)
136+
if (status == NFIT_ARS_STATUS_BUSY)
141137
return -EBUSY;
142138

143139
/* No ARS performed for the current boot */
144-
if (ars_status->status == NFIT_ARS_STATUS_NONE)
140+
if (status == NFIT_ARS_STATUS_NONE)
145141
return -EAGAIN;
146142

147143
/*
148144
* ARS interrupted, either we overflowed or some other
149145
* agent wants the scan to stop. If we didn't overflow
150146
* then just continue with the returned results.
151147
*/
152-
if (ars_status->status == NFIT_ARS_STATUS_INTR) {
148+
if (status == NFIT_ARS_STATUS_INTR) {
153149
if (ars_status->flags & NFIT_ARS_F_OVERFLOW)
154150
return -ENOSPC;
155151
return 0;
156152
}
157153

158154
/* Unknown status */
159-
if (ars_status->status >> 16)
155+
if (status >> 16)
160156
return -EIO;
161157
break;
162158
case ND_CMD_CLEAR_ERROR:
163159
clear_err = buf;
164-
if (clear_err->status & 0xffff)
160+
if (status & 0xffff)
165161
return -EIO;
166162
if (!clear_err->cleared)
167163
return -EIO;
@@ -172,6 +168,9 @@ static int xlat_status(void *buf, unsigned int cmd)
172168
break;
173169
}
174170

171+
/* all other non-zero status results in an error */
172+
if (status)
173+
return -EIO;
175174
return 0;
176175
}
177176

@@ -186,10 +185,10 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
186185
struct nd_cmd_pkg *call_pkg = NULL;
187186
const char *cmd_name, *dimm_name;
188187
unsigned long cmd_mask, dsm_mask;
188+
u32 offset, fw_status = 0;
189189
acpi_handle handle;
190190
unsigned int func;
191191
const u8 *uuid;
192-
u32 offset;
193192
int rc, i;
194193

195194
func = cmd;
@@ -317,6 +316,15 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
317316
out_obj->buffer.pointer + offset, out_size);
318317
offset += out_size;
319318
}
319+
320+
/*
321+
* Set fw_status for all the commands with a known format to be
322+
* later interpreted by xlat_status().
323+
*/
324+
if (i >= 1 && ((cmd >= ND_CMD_ARS_CAP && cmd <= ND_CMD_CLEAR_ERROR)
325+
|| (cmd >= ND_CMD_SMART && cmd <= ND_CMD_VENDOR)))
326+
fw_status = *(u32 *) out_obj->buffer.pointer;
327+
320328
if (offset + in_buf.buffer.length < buf_len) {
321329
if (i >= 1) {
322330
/*
@@ -325,7 +333,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
325333
*/
326334
rc = buf_len - offset - in_buf.buffer.length;
327335
if (cmd_rc)
328-
*cmd_rc = xlat_status(buf, cmd);
336+
*cmd_rc = xlat_status(buf, cmd, fw_status);
329337
} else {
330338
dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n",
331339
__func__, dimm_name, cmd_name, buf_len,
@@ -335,7 +343,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
335343
} else {
336344
rc = 0;
337345
if (cmd_rc)
338-
*cmd_rc = xlat_status(buf, cmd);
346+
*cmd_rc = xlat_status(buf, cmd, fw_status);
339347
}
340348

341349
out:

0 commit comments

Comments
 (0)