diff options
Diffstat (limited to 'drivers/acpi')
| -rw-r--r-- | drivers/acpi/acpi_pnp.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/acpi_tad.c | 178 | ||||
| -rw-r--r-- | drivers/acpi/cppc_acpi.c | 13 | ||||
| -rw-r--r-- | drivers/acpi/x86/cmos_rtc.c | 13 |
4 files changed, 141 insertions, 65 deletions
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 4ad88187dc7a..7eb9561b9589 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -385,7 +385,7 @@ static int is_cmos_rtc_device(struct acpi_device *adev) { "PNP0B02" }, {""}, }; - return !acpi_match_device_ids(adev, ids); + return !cmos_rtc_platform_device_present && !acpi_match_device_ids(adev, ids); } bool acpi_is_pnp_device(struct acpi_device *adev) diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c index fcebfa7d507f..0d62a75a4b92 100644 --- a/drivers/acpi/acpi_tad.c +++ b/drivers/acpi/acpi_tad.c @@ -23,6 +23,7 @@ #include <linux/acpi.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/suspend.h> @@ -49,6 +50,9 @@ MODULE_AUTHOR("Rafael J. Wysocki"); /* Special value for disabled timer or expired timer wake policy. */ #define ACPI_TAD_WAKE_DISABLED (~(u32)0) +/* ACPI TAD RTC */ +#define ACPI_TAD_TZ_UNSPEC 2047 + struct acpi_tad_driver_data { u32 capabilities; }; @@ -67,6 +71,18 @@ struct acpi_tad_rt { u8 padding[3]; /* must be 0 */ } __packed; +static bool acpi_tad_rt_is_invalid(struct acpi_tad_rt *rt) +{ + return rt->year < 1900 || rt->year > 9999 || + rt->month < 1 || rt->month > 12 || + rt->hour > 23 || rt->minute > 59 || rt->second > 59 || + rt->tz < -1440 || + (rt->tz > 1440 && rt->tz != ACPI_TAD_TZ_UNSPEC) || + rt->daylight > 3; +} + +static DEFINE_MUTEX(acpi_tad_aml_lock); + static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt) { acpi_handle handle = ACPI_HANDLE(dev); @@ -80,18 +96,16 @@ static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt) unsigned long long retval; acpi_status status; - if (rt->year < 1900 || rt->year > 9999 || - rt->month < 1 || rt->month > 12 || - rt->hour > 23 || rt->minute > 59 || rt->second > 59 || - rt->tz < -1440 || (rt->tz > 1440 && rt->tz != 2047) || - rt->daylight > 3) - return -ERANGE; + if (acpi_tad_rt_is_invalid(rt)) + return -EINVAL; args[0].buffer.pointer = (u8 *)rt; args[0].buffer.length = sizeof(*rt); pm_runtime_get_sync(dev); + guard(mutex)(&acpi_tad_aml_lock); + status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval); pm_runtime_put_sync(dev); @@ -102,43 +116,113 @@ static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt) return 0; } -static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt) +static int acpi_tad_evaluate_grt(struct device *dev, struct acpi_tad_rt *rt) { acpi_handle handle = ACPI_HANDLE(dev); struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER }; - union acpi_object *out_obj; - struct acpi_tad_rt *data; acpi_status status; int ret = -EIO; - pm_runtime_get_sync(dev); + guard(mutex)(&acpi_tad_aml_lock); status = acpi_evaluate_object(handle, "_GRT", NULL, &output); + if (ACPI_SUCCESS(status)) { + union acpi_object *out_obj; + + out_obj = output.pointer; + if (out_obj->type == ACPI_TYPE_BUFFER && + out_obj->buffer.length == sizeof(*rt)) { + struct acpi_tad_rt *data; + + data = (struct acpi_tad_rt *)(out_obj->buffer.pointer); + if (data->valid) { + memcpy(rt, data, sizeof(*rt)); + ret = 0; + } + } + } + ACPI_FREE(output.pointer); + return ret; +} - pm_runtime_put_sync(dev); +static int __acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt) +{ + int ret; - if (ACPI_FAILURE(status)) - goto out_free; + ret = acpi_tad_evaluate_grt(dev, rt); + if (ret) + return ret; - out_obj = output.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) - goto out_free; + if (acpi_tad_rt_is_invalid(rt)) + return -ENODATA; - if (out_obj->buffer.length != sizeof(*rt)) - goto out_free; + return 0; +} - data = (struct acpi_tad_rt *)(out_obj->buffer.pointer); - if (!data->valid) - goto out_free; +static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt) +{ + int ret; - memcpy(rt, data, sizeof(*rt)); - ret = 0; + pm_runtime_get_sync(dev); + + ret = __acpi_tad_get_real_time(dev, rt); + + pm_runtime_put_sync(dev); -out_free: - ACPI_FREE(output.pointer); return ret; } +static int __acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id, + u32 value) +{ + acpi_handle handle = ACPI_HANDLE(dev); + union acpi_object args[] = { + { .type = ACPI_TYPE_INTEGER, }, + { .type = ACPI_TYPE_INTEGER, }, + }; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + unsigned long long retval; + acpi_status status; + + args[0].integer.value = timer_id; + args[1].integer.value = value; + + guard(mutex)(&acpi_tad_aml_lock); + + status = acpi_evaluate_integer(handle, method, &arg_list, &retval); + if (ACPI_FAILURE(status) || retval) + return -EIO; + + return 0; +} + +static int __acpi_tad_wake_read(struct device *dev, char *method, u32 timer_id, + unsigned long long *retval) +{ + acpi_handle handle = ACPI_HANDLE(dev); + union acpi_object args[] = { + { .type = ACPI_TYPE_INTEGER, }, + }; + struct acpi_object_list arg_list = { + .pointer = args, + .count = ARRAY_SIZE(args), + }; + acpi_status status; + + args[0].integer.value = timer_id; + + guard(mutex)(&acpi_tad_aml_lock); + + status = acpi_evaluate_integer(handle, method, &arg_list, retval); + if (ACPI_FAILURE(status)) + return -EIO; + + return 0; +} + static char *acpi_tad_rt_next_field(char *s, int *val) { char *p; @@ -251,31 +335,15 @@ static const struct attribute_group acpi_tad_time_attr_group = { static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id, u32 value) { - acpi_handle handle = ACPI_HANDLE(dev); - union acpi_object args[] = { - { .type = ACPI_TYPE_INTEGER, }, - { .type = ACPI_TYPE_INTEGER, }, - }; - struct acpi_object_list arg_list = { - .pointer = args, - .count = ARRAY_SIZE(args), - }; - unsigned long long retval; - acpi_status status; - - args[0].integer.value = timer_id; - args[1].integer.value = value; + int ret; pm_runtime_get_sync(dev); - status = acpi_evaluate_integer(handle, method, &arg_list, &retval); + ret = __acpi_tad_wake_set(dev, method, timer_id, value); pm_runtime_put_sync(dev); - if (ACPI_FAILURE(status) || retval) - return -EIO; - - return 0; + return ret; } static int acpi_tad_wake_write(struct device *dev, const char *buf, char *method, @@ -301,27 +369,17 @@ static int acpi_tad_wake_write(struct device *dev, const char *buf, char *method static ssize_t acpi_tad_wake_read(struct device *dev, char *buf, char *method, u32 timer_id, const char *specval) { - acpi_handle handle = ACPI_HANDLE(dev); - union acpi_object args[] = { - { .type = ACPI_TYPE_INTEGER, }, - }; - struct acpi_object_list arg_list = { - .pointer = args, - .count = ARRAY_SIZE(args), - }; unsigned long long retval; - acpi_status status; - - args[0].integer.value = timer_id; + int ret; pm_runtime_get_sync(dev); - status = acpi_evaluate_integer(handle, method, &arg_list, &retval); + ret = __acpi_tad_wake_read(dev, method, timer_id, &retval); pm_runtime_put_sync(dev); - if (ACPI_FAILURE(status)) - return -EIO; + if (ret) + return ret; if ((u32)retval == ACPI_TAD_WAKE_DISABLED) return sprintf(buf, "%s\n", specval); @@ -372,6 +430,8 @@ static int acpi_tad_clear_status(struct device *dev, u32 timer_id) pm_runtime_get_sync(dev); + guard(mutex)(&acpi_tad_aml_lock); + status = acpi_evaluate_integer(handle, "_CWS", &arg_list, &retval); pm_runtime_put_sync(dev); @@ -413,6 +473,8 @@ static ssize_t acpi_tad_status_read(struct device *dev, char *buf, u32 timer_id) pm_runtime_get_sync(dev); + guard(mutex)(&acpi_tad_aml_lock); + status = acpi_evaluate_integer(handle, "_GWS", &arg_list, &retval); pm_runtime_put_sync(dev); diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 60d2548f0eea..531777557b47 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -768,7 +768,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) } if (cpc_rev > CPPC_V3_REV) { num_ent = CPPC_V3_NUM_ENT; - cpc_rev = CPPC_V3_REV; } cpc_ptr->num_entries = num_ent; @@ -1289,10 +1288,20 @@ static int cppc_set_reg_val(int cpu, enum cppc_regs reg_idx, u64 val) * @cpunum: CPU from which to get desired performance. * @desired_perf: Return address. * - * Return: 0 for success, -EIO otherwise. + * Return: 0 for success, -EOPNOTSUPP for _CPC revision 4 or later, and a + * negative errno otherwise. */ int cppc_get_desired_perf(int cpunum, u64 *desired_perf) { + struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum); + + if (!cpc_desc) + return -ENODEV; + + /* _CPC revision 4 no longer specifies Desired Performance as readable. */ + if (cpc_desc->version > CPPC_V3_REV) + return -EOPNOTSUPP; + return cppc_get_reg_val(cpunum, DESIRED_PERF, desired_perf); } EXPORT_SYMBOL_GPL(cppc_get_desired_perf); diff --git a/drivers/acpi/x86/cmos_rtc.c b/drivers/acpi/x86/cmos_rtc.c index 45db7e51cbe6..a6df5b991c96 100644 --- a/drivers/acpi/x86/cmos_rtc.c +++ b/drivers/acpi/x86/cmos_rtc.c @@ -18,12 +18,11 @@ #include "../internal.h" static const struct acpi_device_id acpi_cmos_rtc_ids[] = { - { "PNP0B00" }, - { "PNP0B01" }, - { "PNP0B02" }, - {} + ACPI_CMOS_RTC_IDS }; +bool cmos_rtc_platform_device_present; + static bool cmos_rtc_space_handler_present __read_mostly; static acpi_status acpi_cmos_rtc_space_handler(u32 function, @@ -103,6 +102,12 @@ static int acpi_cmos_rtc_attach(struct acpi_device *adev, if (ret < 0) return ret; + if (IS_ERR_OR_NULL(acpi_create_platform_device(adev, NULL))) { + pr_err("Failed to create CMOS-RTC platform device\n"); + return 0; + } else { + cmos_rtc_platform_device_present = true; + } return 1; } |
