summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/tbfadt.c10
-rw-r--r--drivers/acpi/nfit/core.c55
-rw-r--r--drivers/acpi/nfit/nfit.h2
-rw-r--r--drivers/acpi/sleep.c29
4 files changed, 52 insertions, 44 deletions
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 046c4d0394ee..5fb838e592dc 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -480,19 +480,17 @@ static void acpi_tb_convert_fadt(void)
u32 i;
/*
- * For ACPI 1.0 FADTs (revision 1), ensure that reserved fields which
+ * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
* should be zero are indeed zero. This will workaround BIOSs that
* inadvertently place values in these fields.
*
* The ACPI 1.0 reserved fields that will be zeroed are the bytes located
* at offset 45, 55, 95, and the word located at offset 109, 110.
*
- * Note: The FADT revision value is unreliable because of BIOS errors.
- * The table length is instead used as the final word on the version.
- *
- * Note: FADT revision 3 is the ACPI 2.0 version of the FADT.
+ * Note: The FADT revision value is unreliable. Only the length can be
+ * trusted.
*/
- if (acpi_gbl_FADT.header.length <= ACPI_FADT_V3_SIZE) {
+ if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) {
acpi_gbl_FADT.preferred_profile = 0;
acpi_gbl_FADT.pstate_control = 0;
acpi_gbl_FADT.cst_control = 0;
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 71a7d07c28c9..312c4b4dc363 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;
@@ -113,7 +113,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE;
if ((status >> 16 & flags) == 0)
return -ENOTTY;
- break;
+ return 0;
case ND_CMD_ARS_START:
/* ARS is in progress */
if ((status & 0xffff) == NFIT_ARS_START_BUSY)
@@ -122,7 +122,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
/* Command failed */
if (status & 0xffff)
return -EIO;
- break;
+ return 0;
case ND_CMD_ARS_STATUS:
ars_status = buf;
/* Command failed */
@@ -146,7 +146,8 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
* then just continue with the returned results.
*/
if (status == NFIT_ARS_STATUS_INTR) {
- if (ars_status->flags & NFIT_ARS_F_OVERFLOW)
+ if (ars_status->out_length >= 40 && (ars_status->flags
+ & NFIT_ARS_F_OVERFLOW))
return -ENOSPC;
return 0;
}
@@ -154,7 +155,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
/* Unknown status */
if (status >> 16)
return -EIO;
- break;
+ return 0;
case ND_CMD_CLEAR_ERROR:
clear_err = buf;
if (status & 0xffff)
@@ -163,7 +164,7 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
return -EIO;
if (clear_err->length > clear_err->cleared)
return clear_err->cleared;
- break;
+ return 0;
default:
break;
}
@@ -174,9 +175,18 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
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)
+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;
+}
+
+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)
{
struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
union acpi_object in_obj, in_buf, *out_obj;
@@ -298,7 +308,8 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
for (i = 0, offset = 0; i < desc->out_num; i++) {
u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf,
- (u32 *) out_obj->buffer.pointer);
+ (u32 *) out_obj->buffer.pointer,
+ out_obj->buffer.length - offset);
if (offset + out_size > out_obj->buffer.length) {
dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n",
@@ -333,7 +344,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,
@@ -343,7 +355,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:
@@ -351,6 +363,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
return rc;
}
+EXPORT_SYMBOL_GPL(acpi_nfit_ctl);
static const char *spa_type_name(u16 type)
{
@@ -2001,19 +2014,32 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc)
return cmd_rc;
}
-static int ars_status_process_records(struct nvdimm_bus *nvdimm_bus,
+static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc,
struct nd_cmd_ars_status *ars_status)
{
+ struct nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus;
int rc;
u32 i;
+ /*
+ * First record starts at 44 byte offset from the start of the
+ * payload.
+ */
+ if (ars_status->out_length < 44)
+ return 0;
for (i = 0; i < ars_status->num_records; i++) {
+ /* only process full records */
+ if (ars_status->out_length
+ < 44 + sizeof(struct nd_ars_record) * (i + 1))
+ break;
rc = nvdimm_bus_add_poison(nvdimm_bus,
ars_status->records[i].err_address,
ars_status->records[i].length);
if (rc)
return rc;
}
+ if (i < ars_status->num_records)
+ dev_warn(acpi_desc->dev, "detected truncated ars results\n");
return 0;
}
@@ -2266,8 +2292,7 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc,
if (rc < 0 && rc != -ENOSPC)
return rc;
- if (ars_status_process_records(acpi_desc->nvdimm_bus,
- acpi_desc->ars_status))
+ if (ars_status_process_records(acpi_desc, acpi_desc->ars_status))
return -ENOMEM;
return 0;
diff --git a/drivers/acpi/nfit/nfit.h b/drivers/acpi/nfit/nfit.h
index 14296f5267c8..fc29c2e9832e 100644
--- a/drivers/acpi/nfit/nfit.h
+++ b/drivers/acpi/nfit/nfit.h
@@ -240,5 +240,7 @@ const u8 *to_nfit_uuid(enum nfit_uuids id);
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *nfit, acpi_size sz);
void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event);
void __acpi_nvdimm_notify(struct device *dev, u32 event);
+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);
void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev);
#endif /* __NFIT_H__ */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index deb0ff78eba8..54abb26b7366 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -47,32 +47,15 @@ static void acpi_sleep_tts_switch(u32 acpi_state)
}
}
-static void acpi_sleep_pts_switch(u32 acpi_state)
-{
- acpi_status status;
-
- status = acpi_execute_simple_method(NULL, "\\_PTS", acpi_state);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- /*
- * OS can't evaluate the _PTS object correctly. Some warning
- * message will be printed. But it won't break anything.
- */
- printk(KERN_NOTICE "Failure in evaluating _PTS object\n");
- }
-}
-
-static int sleep_notify_reboot(struct notifier_block *this,
+static int tts_notify_reboot(struct notifier_block *this,
unsigned long code, void *x)
{
acpi_sleep_tts_switch(ACPI_STATE_S5);
-
- acpi_sleep_pts_switch(ACPI_STATE_S5);
-
return NOTIFY_DONE;
}
-static struct notifier_block sleep_notifier = {
- .notifier_call = sleep_notify_reboot,
+static struct notifier_block tts_notifier = {
+ .notifier_call = tts_notify_reboot,
.next = NULL,
.priority = 0,
};
@@ -916,9 +899,9 @@ int __init acpi_sleep_init(void)
pr_info(PREFIX "(supports%s)\n", supported);
/*
- * Register the sleep_notifier to reboot notifier list so that the _TTS
- * and _PTS object can also be evaluated when the system enters S5.
+ * Register the tts_notifier to reboot notifier list so that the _TTS
+ * object can also be evaluated when the system enters S5.
*/
- register_reboot_notifier(&sleep_notifier);
+ register_reboot_notifier(&tts_notifier);
return 0;
}