From 6503e5df08008b9a47022b5e9ebba658c8fa69af Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 27 Nov 2008 17:48:13 +0000 Subject: [PATCH 001/140] thermal: use integers rather than strings for thermal values The thermal API currently uses strings to pass values to userspace. This makes it difficult to use from within the kernel. Change the interface to use integers and fix up the consumers. Signed-off-by: Matthew Garrett Acked-by: Zhang Rui Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/fan.c | 20 ++++--- drivers/acpi/processor_thermal.c | 20 ++++--- drivers/acpi/thermal.c | 80 +++++++++++++++---------- drivers/acpi/video.c | 22 ++++--- drivers/platform/x86/intel_menlow.c | 29 ++++----- drivers/thermal/thermal_sys.c | 91 ++++++++++++++++++++++++----- include/linux/thermal.h | 32 +++++++--- 7 files changed, 198 insertions(+), 96 deletions(-) diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index eaaee1660bdf..ae41cf3cf4e5 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -68,31 +68,35 @@ static struct acpi_driver acpi_fan_driver = { }; /* thermal cooling device callbacks */ -static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf) +static int fan_get_max_state(struct thermal_cooling_device *cdev, unsigned long + *state) { /* ACPI fan device only support two states: ON/OFF */ - return sprintf(buf, "1\n"); + *state = 1; + return 0; } -static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf) +static int fan_get_cur_state(struct thermal_cooling_device *cdev, unsigned long + *state) { struct acpi_device *device = cdev->devdata; - int state; int result; + int acpi_state; if (!device) return -EINVAL; - result = acpi_bus_get_power(device->handle, &state); + result = acpi_bus_get_power(device->handle, &acpi_state); if (result) return result; - return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" : - (state == ACPI_STATE_D0 ? "1" : "unknown")); + *state = (acpi_state == ACPI_STATE_D3 ? 0 : + (acpi_state == ACPI_STATE_D0 ? 1 : -1)); + return 0; } static int -fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) +fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct acpi_device *device = cdev->devdata; int result; diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index b1eb376fae45..0e47e299a9ac 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -373,7 +373,8 @@ static int acpi_processor_max_state(struct acpi_processor *pr) return max_state; } static int -processor_get_max_state(struct thermal_cooling_device *cdev, char *buf) +processor_get_max_state(struct thermal_cooling_device *cdev, + unsigned long *state) { struct acpi_device *device = cdev->devdata; struct acpi_processor *pr = acpi_driver_data(device); @@ -381,28 +382,29 @@ processor_get_max_state(struct thermal_cooling_device *cdev, char *buf) if (!device || !pr) return -EINVAL; - return sprintf(buf, "%d\n", acpi_processor_max_state(pr)); + *state = acpi_processor_max_state(pr); + return 0; } static int -processor_get_cur_state(struct thermal_cooling_device *cdev, char *buf) +processor_get_cur_state(struct thermal_cooling_device *cdev, + unsigned long *cur_state) { struct acpi_device *device = cdev->devdata; struct acpi_processor *pr = acpi_driver_data(device); - int cur_state; if (!device || !pr) return -EINVAL; - cur_state = cpufreq_get_cur_state(pr->id); + *cur_state = cpufreq_get_cur_state(pr->id); if (pr->flags.throttling) - cur_state += pr->throttling.state; - - return sprintf(buf, "%d\n", cur_state); + *cur_state += pr->throttling.state; + return 0; } static int -processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) +processor_set_cur_state(struct thermal_cooling_device *cdev, + unsigned long state) { struct acpi_device *device = cdev->devdata; struct acpi_processor *pr = acpi_driver_data(device); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 99e6f1f8ea45..1c410ef859c6 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -954,7 +954,8 @@ static void acpi_thermal_check(void *data) /* sys I/F for generic thermal sysfs support */ #define KELVIN_TO_MILLICELSIUS(t) (t * 100 - 273200) -static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) +static int thermal_get_temp(struct thermal_zone_device *thermal, + unsigned long *temp) { struct acpi_thermal *tz = thermal->devdata; int result; @@ -966,25 +967,28 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) if (result) return result; - return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature)); + *temp = KELVIN_TO_MILLICELSIUS(tz->temperature); + return 0; } static const char enabled[] = "kernel"; static const char disabled[] = "user"; static int thermal_get_mode(struct thermal_zone_device *thermal, - char *buf) + enum thermal_device_mode *mode) { struct acpi_thermal *tz = thermal->devdata; if (!tz) return -EINVAL; - return sprintf(buf, "%s\n", tz->tz_enabled ? - enabled : disabled); + *mode = tz->tz_enabled ? THERMAL_DEVICE_ENABLED : + THERMAL_DEVICE_DISABLED; + + return 0; } static int thermal_set_mode(struct thermal_zone_device *thermal, - const char *buf) + enum thermal_device_mode mode) { struct acpi_thermal *tz = thermal->devdata; int enable; @@ -995,9 +999,9 @@ static int thermal_set_mode(struct thermal_zone_device *thermal, /* * enable/disable thermal management from ACPI thermal driver */ - if (!strncmp(buf, enabled, sizeof enabled - 1)) + if (mode == THERMAL_DEVICE_ENABLED) enable = 1; - else if (!strncmp(buf, disabled, sizeof disabled - 1)) + else if (mode == THERMAL_DEVICE_DISABLED) enable = 0; else return -EINVAL; @@ -1013,7 +1017,7 @@ static int thermal_set_mode(struct thermal_zone_device *thermal, } static int thermal_get_trip_type(struct thermal_zone_device *thermal, - int trip, char *buf) + int trip, enum thermal_trip_type *type) { struct acpi_thermal *tz = thermal->devdata; int i; @@ -1022,27 +1026,35 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, return -EINVAL; if (tz->trips.critical.flags.valid) { - if (!trip) - return sprintf(buf, "critical\n"); + if (!trip) { + *type = THERMAL_TRIP_CRITICAL; + return 0; + } trip--; } if (tz->trips.hot.flags.valid) { - if (!trip) - return sprintf(buf, "hot\n"); + if (!trip) { + *type = THERMAL_TRIP_HOT; + return 0; + } trip--; } if (tz->trips.passive.flags.valid) { - if (!trip) - return sprintf(buf, "passive\n"); + if (!trip) { + *type = THERMAL_TRIP_PASSIVE; + return 0; + } trip--; } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++) { - if (!trip) - return sprintf(buf, "active%d\n", i); + if (!trip) { + *type = THERMAL_TRIP_ACTIVE; + return 0; + } trip--; } @@ -1050,7 +1062,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal, } static int thermal_get_trip_temp(struct thermal_zone_device *thermal, - int trip, char *buf) + int trip, unsigned long *temp) { struct acpi_thermal *tz = thermal->devdata; int i; @@ -1059,31 +1071,39 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, return -EINVAL; if (tz->trips.critical.flags.valid) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( - tz->trips.critical.temperature)); + if (!trip) { + *temp = KELVIN_TO_MILLICELSIUS( + tz->trips.critical.temperature); + return 0; + } trip--; } if (tz->trips.hot.flags.valid) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( - tz->trips.hot.temperature)); + if (!trip) { + *temp = KELVIN_TO_MILLICELSIUS( + tz->trips.hot.temperature); + return 0; + } trip--; } if (tz->trips.passive.flags.valid) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( - tz->trips.passive.temperature)); + if (!trip) { + *temp = KELVIN_TO_MILLICELSIUS( + tz->trips.passive.temperature); + return 0; + } trip--; } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS( - tz->trips.active[i].temperature)); + if (!trip) { + *temp = KELVIN_TO_MILLICELSIUS( + tz->trips.active[i].temperature); + return 0; + } trip--; } diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bb5ed059114a..5259d502add6 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -358,32 +358,36 @@ static struct output_properties acpi_output_properties = { /* thermal cooling device callbacks */ -static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf) +static int video_get_max_state(struct thermal_cooling_device *cdev, unsigned + long *state) { struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); - return sprintf(buf, "%d\n", video->brightness->count - 3); + *state = video->brightness->count - 3; + return 0; } -static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) +static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned + long *state) { struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); unsigned long long level; - int state; + int offset; acpi_video_device_lcd_get_level_current(video, &level); - for (state = 2; state < video->brightness->count; state++) - if (level == video->brightness->levels[state]) - return sprintf(buf, "%d\n", - video->brightness->count - state - 1); + for (offset = 2; offset < video->brightness->count; offset++) + if (level == video->brightness->levels[offset]) { + *state = video->brightness->count - offset - 1; + return 0; + } return -EINVAL; } static int -video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) +video_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c index 27b7662955bb..29432a50be45 100644 --- a/drivers/platform/x86/intel_menlow.c +++ b/drivers/platform/x86/intel_menlow.c @@ -57,8 +57,8 @@ MODULE_LICENSE("GPL"); * In that case max_cstate would be n-1 * GTHS returning '0' would mean that no bandwidth control states are supported */ -static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, - unsigned long *max_state) +static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev, + unsigned long *max_state) { struct acpi_device *device = cdev->devdata; acpi_handle handle = device->handle; @@ -83,22 +83,12 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, return 0; } -static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev, - char *buf) -{ - unsigned long value; - if (memory_get_int_max_bandwidth(cdev, &value)) - return -EINVAL; - - return sprintf(buf, "%ld\n", value); -} - static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev, - char *buf) + unsigned long *value) { struct acpi_device *device = cdev->devdata; acpi_handle handle = device->handle; - unsigned long long value; + unsigned long long result; struct acpi_object_list arg_list; union acpi_object arg; acpi_status status = AE_OK; @@ -108,15 +98,16 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev, arg.type = ACPI_TYPE_INTEGER; arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH; status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH, - &arg_list, &value); + &arg_list, &result); if (ACPI_FAILURE(status)) return -EFAULT; - return sprintf(buf, "%llu\n", value); + *value = result; + return 0; } static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, - unsigned int state) + unsigned long state) { struct acpi_device *device = cdev->devdata; acpi_handle handle = device->handle; @@ -126,7 +117,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, unsigned long long temp; unsigned long max_state; - if (memory_get_int_max_bandwidth(cdev, &max_state)) + if (memory_get_max_bandwidth(cdev, &max_state)) return -EFAULT; if (state > max_state) @@ -142,7 +133,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, &temp); printk(KERN_INFO - "Bandwidth value was %d: status is %d\n", state, status); + "Bandwidth value was %ld: status is %d\n", state, status); if (ACPI_FAILURE(status)) return -EFAULT; diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 8171ca17b936..bd139adc6d32 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -104,22 +104,36 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); + long temperature; + int ret; if (!tz->ops->get_temp) return -EPERM; - return tz->ops->get_temp(tz, buf); + ret = tz->ops->get_temp(tz, &temperature); + + if (ret) + return ret; + + return sprintf(buf, "%ld\n", temperature); } static ssize_t mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); + enum thermal_device_mode mode; + int result; if (!tz->ops->get_mode) return -EPERM; - return tz->ops->get_mode(tz, buf); + result = tz->ops->get_mode(tz, &mode); + if (result) + return result; + + return sprintf(buf, "%s\n", mode == THERMAL_DEVICE_ENABLED ? "enabled" + : "disabled"); } static ssize_t @@ -132,7 +146,13 @@ mode_store(struct device *dev, struct device_attribute *attr, if (!tz->ops->set_mode) return -EPERM; - result = tz->ops->set_mode(tz, buf); + if (!strncmp(buf, "enabled", sizeof("enabled"))) + result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); + else if (!strncmp(buf, "disabled", sizeof("disabled"))) + result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); + else + result = -EINVAL; + if (result) return result; @@ -144,7 +164,8 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); - int trip; + enum thermal_trip_type type; + int trip, result; if (!tz->ops->get_trip_type) return -EPERM; @@ -152,7 +173,22 @@ trip_point_type_show(struct device *dev, struct device_attribute *attr, if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) return -EINVAL; - return tz->ops->get_trip_type(tz, trip, buf); + result = tz->ops->get_trip_type(tz, trip, &type); + if (result) + return result; + + switch (type) { + case THERMAL_TRIP_CRITICAL: + return sprintf(buf, "critical"); + case THERMAL_TRIP_HOT: + return sprintf(buf, "hot"); + case THERMAL_TRIP_PASSIVE: + return sprintf(buf, "passive"); + case THERMAL_TRIP_ACTIVE: + return sprintf(buf, "active"); + default: + return sprintf(buf, "unknown"); + } } static ssize_t @@ -160,7 +196,8 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_zone_device *tz = to_thermal_zone(dev); - int trip; + int trip, ret; + long temperature; if (!tz->ops->get_trip_temp) return -EPERM; @@ -168,7 +205,12 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) return -EINVAL; - return tz->ops->get_trip_temp(tz, trip, buf); + ret = tz->ops->get_trip_temp(tz, trip, &temperature); + + if (ret) + return ret; + + return sprintf(buf, "%ld\n", temperature); } static DEVICE_ATTR(type, 0444, type_show, NULL); @@ -236,8 +278,13 @@ thermal_cooling_device_max_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_cooling_device *cdev = to_cooling_device(dev); + unsigned long state; + int ret; - return cdev->ops->get_max_state(cdev, buf); + ret = cdev->ops->get_max_state(cdev, &state); + if (ret) + return ret; + return sprintf(buf, "%ld\n", state); } static ssize_t @@ -245,8 +292,13 @@ thermal_cooling_device_cur_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct thermal_cooling_device *cdev = to_cooling_device(dev); + unsigned long state; + int ret; - return cdev->ops->get_cur_state(cdev, buf); + ret = cdev->ops->get_cur_state(cdev, &state); + if (ret) + return ret; + return sprintf(buf, "%ld\n", state); } static ssize_t @@ -255,10 +307,10 @@ thermal_cooling_device_cur_state_store(struct device *dev, const char *buf, size_t count) { struct thermal_cooling_device *cdev = to_cooling_device(dev); - int state; + unsigned long state; int result; - if (!sscanf(buf, "%d\n", &state)) + if (!sscanf(buf, "%ld\n", &state)) return -EINVAL; if (state < 0) @@ -312,13 +364,20 @@ static DEVICE_ATTR(name, 0444, name_show, NULL); static ssize_t temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) { + long temperature; + int ret; struct thermal_hwmon_attr *hwmon_attr = container_of(attr, struct thermal_hwmon_attr, attr); struct thermal_zone_device *tz = container_of(hwmon_attr, struct thermal_zone_device, temp_input); - return tz->ops->get_temp(tz, buf); + ret = tz->ops->get_temp(tz, &temperature); + + if (ret) + return ret; + + return sprintf(buf, "%ld\n", temperature); } static ssize_t @@ -330,8 +389,14 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, struct thermal_zone_device *tz = container_of(hwmon_attr, struct thermal_zone_device, temp_crit); + long temperature; + int ret; - return tz->ops->get_trip_temp(tz, 0, buf); + ret = tz->ops->get_trip_temp(tz, 0, &temperature); + if (ret) + return ret; + + return sprintf(buf, "%ld\n", temperature); } diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 917707e6151d..4cb3292fb6e4 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -31,23 +31,39 @@ struct thermal_zone_device; struct thermal_cooling_device; +enum thermal_device_mode { + THERMAL_DEVICE_DISABLED = 0, + THERMAL_DEVICE_ENABLED, +}; + +enum thermal_trip_type { + THERMAL_TRIP_ACTIVE = 0, + THERMAL_TRIP_PASSIVE, + THERMAL_TRIP_HOT, + THERMAL_TRIP_CRITICAL, +}; + struct thermal_zone_device_ops { int (*bind) (struct thermal_zone_device *, struct thermal_cooling_device *); int (*unbind) (struct thermal_zone_device *, struct thermal_cooling_device *); - int (*get_temp) (struct thermal_zone_device *, char *); - int (*get_mode) (struct thermal_zone_device *, char *); - int (*set_mode) (struct thermal_zone_device *, const char *); - int (*get_trip_type) (struct thermal_zone_device *, int, char *); - int (*get_trip_temp) (struct thermal_zone_device *, int, char *); + int (*get_temp) (struct thermal_zone_device *, unsigned long *); + int (*get_mode) (struct thermal_zone_device *, + enum thermal_device_mode *); + int (*set_mode) (struct thermal_zone_device *, + enum thermal_device_mode); + int (*get_trip_type) (struct thermal_zone_device *, int, + enum thermal_trip_type *); + int (*get_trip_temp) (struct thermal_zone_device *, int, + unsigned long *); int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); }; struct thermal_cooling_device_ops { - int (*get_max_state) (struct thermal_cooling_device *, char *); - int (*get_cur_state) (struct thermal_cooling_device *, char *); - int (*set_cur_state) (struct thermal_cooling_device *, unsigned int); + int (*get_max_state) (struct thermal_cooling_device *, unsigned long *); + int (*get_cur_state) (struct thermal_cooling_device *, unsigned long *); + int (*set_cur_state) (struct thermal_cooling_device *, unsigned long); }; #define THERMAL_TRIPS_NONE -1 From b1569e99c795bf83b4ddf41c4f1c42761ab7f75e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 3 Dec 2008 17:55:32 +0000 Subject: [PATCH 002/140] ACPI: move thermal trip handling to generic thermal layer The ACPI code currently carries its own thermal trip handling, meaning that any other thermal implementation will need to reimplement it. Move the code to the generic thermal layer. Signed-off-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 458 ++++------------------------------ drivers/thermal/thermal_sys.c | 188 +++++++++++++- include/linux/thermal.h | 15 +- 3 files changed, 248 insertions(+), 413 deletions(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 1c410ef859c6..0ec48d2f85c5 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -190,7 +189,6 @@ struct acpi_thermal { struct acpi_thermal_state state; struct acpi_thermal_trips trips; struct acpi_handle_list devices; - struct timer_list timer; struct thermal_zone_device *thermal_zone; int tz_enabled; struct mutex lock; @@ -290,6 +288,11 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds) tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ + tz->thermal_zone->polling_delay = seconds * 1000; + + if (tz->tz_enabled) + thermal_zone_device_update(tz->thermal_zone); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Polling frequency set to %lu seconds\n", tz->polling_frequency/10)); @@ -569,386 +572,11 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); } -static int acpi_thermal_critical(struct acpi_thermal *tz) -{ - if (!tz || !tz->trips.critical.flags.valid) - return -EINVAL; - - if (tz->temperature >= tz->trips.critical.temperature) { - printk(KERN_WARNING PREFIX "Critical trip point\n"); - tz->trips.critical.flags.enabled = 1; - } else if (tz->trips.critical.flags.enabled) - tz->trips.critical.flags.enabled = 0; - - acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, - tz->trips.critical.flags.enabled); - acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - dev_name(&tz->device->dev), - ACPI_THERMAL_NOTIFY_CRITICAL, - tz->trips.critical.flags.enabled); - - /* take no action if nocrt is set */ - if(!nocrt) { - printk(KERN_EMERG - "Critical temperature reached (%ld C), shutting down.\n", - KELVIN_TO_CELSIUS(tz->temperature)); - orderly_poweroff(true); - } - - return 0; -} - -static int acpi_thermal_hot(struct acpi_thermal *tz) -{ - if (!tz || !tz->trips.hot.flags.valid) - return -EINVAL; - - if (tz->temperature >= tz->trips.hot.temperature) { - printk(KERN_WARNING PREFIX "Hot trip point\n"); - tz->trips.hot.flags.enabled = 1; - } else if (tz->trips.hot.flags.enabled) - tz->trips.hot.flags.enabled = 0; - - acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT, - tz->trips.hot.flags.enabled); - acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - dev_name(&tz->device->dev), - ACPI_THERMAL_NOTIFY_HOT, - tz->trips.hot.flags.enabled); - - /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */ - - return 0; -} - -static void acpi_thermal_passive(struct acpi_thermal *tz) -{ - int result = 1; - struct acpi_thermal_passive *passive = NULL; - int trend = 0; - int i = 0; - - - if (!tz || !tz->trips.passive.flags.valid) - return; - - passive = &(tz->trips.passive); - - /* - * Above Trip? - * ----------- - * Calculate the thermal trend (using the passive cooling equation) - * and modify the performance limit for all passive cooling devices - * accordingly. Note that we assume symmetry. - */ - if (tz->temperature >= passive->temperature) { - trend = - (passive->tc1 * (tz->temperature - tz->last_temperature)) + - (passive->tc2 * (tz->temperature - passive->temperature)); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n", - trend, passive->tc1, tz->temperature, - tz->last_temperature, passive->tc2, - tz->temperature, passive->temperature)); - passive->flags.enabled = 1; - /* Heating up? */ - if (trend > 0) - for (i = 0; i < passive->devices.count; i++) - acpi_processor_set_thermal_limit(passive-> - devices. - handles[i], - ACPI_PROCESSOR_LIMIT_INCREMENT); - /* Cooling off? */ - else if (trend < 0) { - for (i = 0; i < passive->devices.count; i++) - /* - * assume that we are on highest - * freq/lowest thrott and can leave - * passive mode, even in error case - */ - if (!acpi_processor_set_thermal_limit - (passive->devices.handles[i], - ACPI_PROCESSOR_LIMIT_DECREMENT)) - result = 0; - /* - * Leave cooling mode, even if the temp might - * higher than trip point This is because some - * machines might have long thermal polling - * frequencies (tsp) defined. We will fall back - * into passive mode in next cycle (probably quicker) - */ - if (result) { - passive->flags.enabled = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Disabling passive cooling, still above threshold," - " but we are cooling down\n")); - } - } - return; - } - - /* - * Below Trip? - * ----------- - * Implement passive cooling hysteresis to slowly increase performance - * and avoid thrashing around the passive trip point. Note that we - * assume symmetry. - */ - if (!passive->flags.enabled) - return; - for (i = 0; i < passive->devices.count; i++) - if (!acpi_processor_set_thermal_limit - (passive->devices.handles[i], - ACPI_PROCESSOR_LIMIT_DECREMENT)) - result = 0; - if (result) { - passive->flags.enabled = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Disabling passive cooling (zone is cool)\n")); - } -} - -static void acpi_thermal_active(struct acpi_thermal *tz) -{ - int result = 0; - struct acpi_thermal_active *active = NULL; - int i = 0; - int j = 0; - unsigned long maxtemp = 0; - - - if (!tz) - return; - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - active = &(tz->trips.active[i]); - if (!active || !active->flags.valid) - break; - if (tz->temperature >= active->temperature) { - /* - * Above Threshold? - * ---------------- - * If not already enabled, turn ON all cooling devices - * associated with this active threshold. - */ - if (active->temperature > maxtemp) - tz->state.active_index = i; - maxtemp = active->temperature; - if (active->flags.enabled) - continue; - for (j = 0; j < active->devices.count; j++) { - result = - acpi_bus_set_power(active->devices. - handles[j], - ACPI_STATE_D0); - if (result) { - printk(KERN_WARNING PREFIX - "Unable to turn cooling device [%p] 'on'\n", - active->devices. - handles[j]); - continue; - } - active->flags.enabled = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Cooling device [%p] now 'on'\n", - active->devices.handles[j])); - } - continue; - } - if (!active->flags.enabled) - continue; - /* - * Below Threshold? - * ---------------- - * Turn OFF all cooling devices associated with this - * threshold. - */ - for (j = 0; j < active->devices.count; j++) { - result = acpi_bus_set_power(active->devices.handles[j], - ACPI_STATE_D3); - if (result) { - printk(KERN_WARNING PREFIX - "Unable to turn cooling device [%p] 'off'\n", - active->devices.handles[j]); - continue; - } - active->flags.enabled = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Cooling device [%p] now 'off'\n", - active->devices.handles[j])); - } - } -} - -static void acpi_thermal_check(void *context); - -static void acpi_thermal_run(unsigned long data) -{ - struct acpi_thermal *tz = (struct acpi_thermal *)data; - if (!tz->zombie) - acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data); -} - -static void acpi_thermal_active_off(void *data) -{ - int result = 0; - struct acpi_thermal *tz = data; - int i = 0; - int j = 0; - struct acpi_thermal_active *active = NULL; - - if (!tz) { - printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); - return; - } - - result = acpi_thermal_get_temperature(tz); - if (result) - return; - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - active = &(tz->trips.active[i]); - if (!active || !active->flags.valid) - break; - if (tz->temperature >= active->temperature) { - /* - * If the thermal temperature is greater than the - * active threshod, unnecessary to turn off the - * the active cooling device. - */ - continue; - } - /* - * Below Threshold? - * ---------------- - * Turn OFF all cooling devices associated with this - * threshold. - */ - for (j = 0; j < active->devices.count; j++) - result = acpi_bus_set_power(active->devices.handles[j], - ACPI_STATE_D3); - } -} - static void acpi_thermal_check(void *data) { - int result = 0; struct acpi_thermal *tz = data; - unsigned long sleep_time = 0; - unsigned long timeout_jiffies = 0; - int i = 0; - struct acpi_thermal_state state; - - if (!tz) { - printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); - return; - } - - /* Check if someone else is already running */ - if (!mutex_trylock(&tz->lock)) - return; - - state = tz->state; - - result = acpi_thermal_get_temperature(tz); - if (result) - goto unlock; - - if (!tz->tz_enabled) - goto unlock; - - memset(&tz->state, 0, sizeof(tz->state)); - - /* - * Check Trip Points - * ----------------- - * Compare the current temperature to the trip point values to see - * if we've entered one of the thermal policy states. Note that - * this function determines when a state is entered, but the - * individual policy decides when it is exited (e.g. hysteresis). - */ - if (tz->trips.critical.flags.valid) - state.critical |= - (tz->temperature >= tz->trips.critical.temperature); - if (tz->trips.hot.flags.valid) - state.hot |= (tz->temperature >= tz->trips.hot.temperature); - if (tz->trips.passive.flags.valid) - state.passive |= - (tz->temperature >= tz->trips.passive.temperature); - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - if (tz->trips.active[i].flags.valid) - state.active |= - (tz->temperature >= - tz->trips.active[i].temperature); - - /* - * Invoke Policy - * ------------- - * Separated from the above check to allow individual policy to - * determine when to exit a given state. - */ - if (state.critical) - acpi_thermal_critical(tz); - if (state.hot) - acpi_thermal_hot(tz); - if (state.passive) - acpi_thermal_passive(tz); - if (state.active) - acpi_thermal_active(tz); - - /* - * Calculate State - * --------------- - * Again, separated from the above two to allow independent policy - * decisions. - */ - tz->state.critical = tz->trips.critical.flags.enabled; - tz->state.hot = tz->trips.hot.flags.enabled; - tz->state.passive = tz->trips.passive.flags.enabled; - tz->state.active = 0; - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - tz->state.active |= tz->trips.active[i].flags.enabled; - - /* - * Calculate Sleep Time - * -------------------- - * If we're in the passive state, use _TSP's value. Otherwise - * use the default polling frequency (e.g. _TZP). If no polling - * frequency is specified then we'll wait forever (at least until - * a thermal event occurs). Note that _TSP and _TZD values are - * given in 1/10th seconds (we must covert to milliseconds). - */ - if (tz->state.passive) { - sleep_time = tz->trips.passive.tsp * 100; - timeout_jiffies = jiffies + (HZ * sleep_time) / 1000; - } else if (tz->polling_frequency > 0) { - sleep_time = tz->polling_frequency * 100; - timeout_jiffies = round_jiffies(jiffies + (HZ * sleep_time) / 1000); - } - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n", - tz->name, tz->temperature, sleep_time)); - - /* - * Schedule Next Poll - * ------------------ - */ - if (!sleep_time) { - if (timer_pending(&(tz->timer))) - del_timer(&(tz->timer)); - } else { - if (timer_pending(&(tz->timer))) - mod_timer(&(tz->timer), timeout_jiffies); - else { - tz->timer.data = (unsigned long)tz; - tz->timer.function = acpi_thermal_run; - tz->timer.expires = timeout_jiffies; - add_timer(&(tz->timer)); - } - } - unlock: - mutex_unlock(&tz->lock); + thermal_zone_device_update(tz->thermal_zone); } /* sys I/F for generic thermal sysfs support */ @@ -1122,6 +750,29 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal, return -EINVAL; } +static int thermal_notify(struct thermal_zone_device *thermal, int trip, + enum thermal_trip_type trip_type) +{ + u8 type = 0; + struct acpi_thermal *tz = thermal->devdata; + + if (trip_type == THERMAL_TRIP_CRITICAL) + type = ACPI_THERMAL_NOTIFY_CRITICAL; + else if (trip_type == THERMAL_TRIP_HOT) + type = ACPI_THERMAL_NOTIFY_HOT; + else + return 0; + + acpi_bus_generate_proc_event(tz->device, type, 1); + acpi_bus_generate_netlink_event(tz->device->pnp.device_class, + tz->device->dev.bus_id, type, 1); + + if (trip_type == THERMAL_TRIP_CRITICAL && nocrt) + return 1; + + return 0; +} + typedef int (*cb)(struct thermal_zone_device *, int, struct thermal_cooling_device *); static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, @@ -1214,6 +865,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .get_trip_type = thermal_get_trip_type, .get_trip_temp = thermal_get_trip_temp, .get_crit_temp = thermal_get_crit_temp, + .notify = thermal_notify, }; static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) @@ -1234,8 +886,21 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++, trips++); - tz->thermal_zone = thermal_zone_device_register("acpitz", - trips, tz, &acpi_thermal_zone_ops); + + if (tz->trips.passive.flags.valid) + tz->thermal_zone = + thermal_zone_device_register("acpitz", trips, tz, + &acpi_thermal_zone_ops, + tz->trips.passive.tc1, + tz->trips.passive.tc2, + tz->trips.passive.tsp*100, + tz->polling_frequency*100); + else + tz->thermal_zone = + thermal_zone_device_register("acpitz", trips, tz, + &acpi_thermal_zone_ops, + 0, 0, 0, + tz->polling_frequency); if (IS_ERR(tz->thermal_zone)) return -ENODEV; @@ -1467,13 +1132,13 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset) if (!tz) goto end; - if (!tz->polling_frequency) { + if (!tz->thermal_zone->polling_delay) { seq_puts(seq, "\n"); goto end; } - seq_printf(seq, "polling frequency: %lu seconds\n", - (tz->polling_frequency / 10)); + seq_printf(seq, "polling frequency: %d seconds\n", + (tz->thermal_zone->polling_delay / 1000)); end: return 0; @@ -1703,12 +1368,6 @@ static int acpi_thermal_add(struct acpi_device *device) if (result) goto unregister_thermal_zone; - init_timer(&tz->timer); - - acpi_thermal_active_off(tz); - - acpi_thermal_check(tz); - status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_thermal_notify, tz); @@ -1737,36 +1396,15 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) acpi_status status = AE_OK; struct acpi_thermal *tz = NULL; - if (!device || !acpi_driver_data(device)) return -EINVAL; tz = acpi_driver_data(device); - /* avoid timer adding new defer task */ - tz->zombie = 1; - /* wait for running timer (on other CPUs) finish */ - del_timer_sync(&(tz->timer)); - /* synchronize deferred task */ - acpi_os_wait_events_complete(NULL); - /* deferred task may reinsert timer */ - del_timer_sync(&(tz->timer)); - status = acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, acpi_thermal_notify); - /* Terminate policy */ - if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) { - tz->trips.passive.flags.enabled = 0; - acpi_thermal_passive(tz); - } - if (tz->trips.active[0].flags.valid - && tz->trips.active[0].flags.enabled) { - tz->trips.active[0].flags.enabled = 0; - acpi_thermal_active(tz); - } - acpi_thermal_remove_fs(device); acpi_thermal_unregister_thermal_zone(tz); mutex_destroy(&tz->lock); diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index bd139adc6d32..6378741882f3 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -30,6 +30,7 @@ #include #include #include +#include MODULE_AUTHOR("Zhang Rui"); MODULE_DESCRIPTION("Generic thermal management sysfs support"); @@ -517,6 +518,97 @@ thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) } #endif +static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, + int delay) +{ + cancel_delayed_work(&(tz->poll_queue)); + + if (!delay) + return; + + if (delay > 1000) + schedule_delayed_work(&(tz->poll_queue), + round_jiffies(msecs_to_jiffies(delay))); + else + schedule_delayed_work(&(tz->poll_queue), + msecs_to_jiffies(delay)); +} + +static void thermal_zone_device_passive(struct thermal_zone_device *tz, + int temp, int trip_temp, int trip) +{ + int trend = 0; + struct thermal_cooling_device_instance *instance; + struct thermal_cooling_device *cdev; + long state, max_state; + + /* + * Above Trip? + * ----------- + * Calculate the thermal trend (using the passive cooling equation) + * and modify the performance limit for all passive cooling devices + * accordingly. Note that we assume symmetry. + */ + if (temp >= trip_temp) { + tz->passive = true; + + trend = (tz->tc1 * (temp - tz->last_temperature)) + + (tz->tc2 * (temp - trip_temp)); + + /* Heating up? */ + if (trend > 0) { + list_for_each_entry(instance, &tz->cooling_devices, + node) { + if (instance->trip != trip) + continue; + cdev = instance->cdev; + cdev->ops->get_cur_state(cdev, &state); + cdev->ops->get_max_state(cdev, &max_state); + if (state++ < max_state) + cdev->ops->set_cur_state(cdev, state); + } + } else if (trend < 0) { /* Cooling off? */ + list_for_each_entry(instance, &tz->cooling_devices, + node) { + if (instance->trip != trip) + continue; + cdev = instance->cdev; + cdev->ops->get_cur_state(cdev, &state); + cdev->ops->get_max_state(cdev, &max_state); + if (state > 0) + cdev->ops->set_cur_state(cdev, --state); + } + } + return; + } + + /* + * Below Trip? + * ----------- + * Implement passive cooling hysteresis to slowly increase performance + * and avoid thrashing around the passive trip point. Note that we + * assume symmetry. + */ + list_for_each_entry(instance, &tz->cooling_devices, node) { + if (instance->trip != trip) + continue; + cdev = instance->cdev; + cdev->ops->get_cur_state(cdev, &state); + cdev->ops->get_max_state(cdev, &max_state); + if (state > 0) + cdev->ops->set_cur_state(cdev, --state); + if (state == 0) + tz->passive = false; + } +} + +static void thermal_zone_device_check(struct work_struct *work) +{ + struct thermal_zone_device *tz = container_of(work, struct + thermal_zone_device, + poll_queue.work); + thermal_zone_device_update(tz); +} /** * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone @@ -786,21 +878,102 @@ void thermal_cooling_device_unregister(struct EXPORT_SYMBOL(thermal_cooling_device_unregister); +/** + * thermal_zone_device_update - force an update of a thermal zone's state + * @ttz: the thermal zone to update + */ + +void thermal_zone_device_update(struct thermal_zone_device *tz) +{ + int count, ret = 0; + long temp, trip_temp; + enum thermal_trip_type trip_type; + struct thermal_cooling_device_instance *instance; + struct thermal_cooling_device *cdev; + + mutex_lock(&tz->lock); + + tz->ops->get_temp(tz, &temp); + + for (count = 0; count < tz->trips; count++) { + tz->ops->get_trip_type(tz, count, &trip_type); + tz->ops->get_trip_temp(tz, count, &trip_temp); + + switch (trip_type) { + case THERMAL_TRIP_CRITICAL: + if (temp > trip_temp) { + if (tz->ops->notify) + ret = tz->ops->notify(tz, count, + trip_type); + if (!ret) { + printk(KERN_EMERG + "Critical temperature reached (%ld C), shutting down.\n", + temp/1000); + orderly_poweroff(true); + } + } + break; + case THERMAL_TRIP_HOT: + if (temp > trip_temp) + if (tz->ops->notify) + tz->ops->notify(tz, count, trip_type); + break; + case THERMAL_TRIP_ACTIVE: + list_for_each_entry(instance, &tz->cooling_devices, + node) { + if (instance->trip != count) + continue; + + cdev = instance->cdev; + + if (temp > trip_temp) + cdev->ops->set_cur_state(cdev, 1); + else + cdev->ops->set_cur_state(cdev, 0); + } + break; + case THERMAL_TRIP_PASSIVE: + if (temp > trip_temp || tz->passive) + thermal_zone_device_passive(tz, temp, + trip_temp, count); + break; + } + } + tz->last_temperature = temp; + if (tz->passive) + thermal_zone_device_set_polling(tz, tz->passive_delay); + else if (tz->polling_delay) + thermal_zone_device_set_polling(tz, tz->polling_delay); + mutex_unlock(&tz->lock); +} +EXPORT_SYMBOL(thermal_zone_device_update); + /** * thermal_zone_device_register - register a new thermal zone device * @type: the thermal zone device type * @trips: the number of trip points the thermal zone support * @devdata: private device data * @ops: standard thermal zone device callbacks + * @tc1: thermal coefficient 1 for passive calculations + * @tc2: thermal coefficient 2 for passive calculations + * @passive_delay: number of milliseconds to wait between polls when + * performing passive cooling + * @polling_delay: number of milliseconds to wait between polls when checking + * whether trip points have been crossed (0 for interrupt + * driven systems) * * thermal_zone_device_unregister() must be called when the device is no - * longer needed. + * longer needed. The passive cooling formula uses tc1 and tc2 as described in + * section 11.1.5.1 of the ACPI specification 3.0. */ struct thermal_zone_device *thermal_zone_device_register(char *type, int trips, void *devdata, struct thermal_zone_device_ops - *ops) + *ops, int tc1, int + tc2, + int passive_delay, + int polling_delay) { struct thermal_zone_device *tz; struct thermal_cooling_device *pos; @@ -834,6 +1007,11 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, tz->device.class = &thermal_class; tz->devdata = devdata; tz->trips = trips; + tz->tc1 = tc1; + tz->tc2 = tc2; + tz->passive_delay = passive_delay; + tz->polling_delay = polling_delay; + dev_set_name(&tz->device, "thermal_zone%d", tz->id); result = device_register(&tz->device); if (result) { @@ -879,6 +1057,10 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, } mutex_unlock(&thermal_list_lock); + INIT_DELAYED_WORK(&(tz->poll_queue), thermal_zone_device_check); + + thermal_zone_device_update(tz); + if (!result) return tz; @@ -918,6 +1100,8 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) tz->ops->unbind(tz, cdev); mutex_unlock(&thermal_list_lock); + thermal_zone_device_set_polling(tz, 0); + if (tz->type[0]) device_remove_file(&tz->device, &dev_attr_type); device_remove_file(&tz->device, &dev_attr_temp); diff --git a/include/linux/thermal.h b/include/linux/thermal.h index 4cb3292fb6e4..a81c61521ba4 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -27,6 +27,7 @@ #include #include +#include struct thermal_zone_device; struct thermal_cooling_device; @@ -58,6 +59,8 @@ struct thermal_zone_device_ops { int (*get_trip_temp) (struct thermal_zone_device *, int, unsigned long *); int (*get_crit_temp) (struct thermal_zone_device *, unsigned long *); + int (*notify) (struct thermal_zone_device *, int, + enum thermal_trip_type); }; struct thermal_cooling_device_ops { @@ -104,11 +107,18 @@ struct thermal_zone_device { struct device device; void *devdata; int trips; + int tc1; + int tc2; + int passive_delay; + int polling_delay; + int last_temperature; + bool passive; struct thermal_zone_device_ops *ops; struct list_head cooling_devices; struct idr idr; struct mutex lock; /* protect cooling devices list */ struct list_head node; + struct delayed_work poll_queue; #if defined(CONFIG_THERMAL_HWMON) struct list_head hwmon_node; struct thermal_hwmon_device *hwmon; @@ -120,13 +130,16 @@ struct thermal_zone_device { struct thermal_zone_device *thermal_zone_device_register(char *, int, void *, struct thermal_zone_device_ops - *); + *, int tc1, int tc2, + int passive_freq, + int polling_freq); void thermal_zone_device_unregister(struct thermal_zone_device *); int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, struct thermal_cooling_device *); +void thermal_zone_device_update(struct thermal_zone_device *); struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, struct thermal_cooling_device_ops From 4658e4ef9d252c26630268b20ceab78b3952db41 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 26 Feb 2009 11:27:23 +0800 Subject: [PATCH 003/140] ACPI: introduce sysfs I/F for dynamic tables SSDT tables may be loaded at runtime. create sysfs I/F for these dynamic tables in /sys/firmware/acpi/tables/dynamic/. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/system.c | 49 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 391d0358a592..c8859047acfe 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -62,6 +62,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); -------------------------------------------------------------------------- */ static LIST_HEAD(acpi_table_attr_list); static struct kobject *tables_kobj; +static struct kobject *dynamic_tables_kobj; struct acpi_table_attr { struct bin_attribute attr; @@ -128,6 +129,40 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr, return; } +static acpi_status +acpi_sysfs_table_handler(u32 event, void *table, void *context) +{ + struct acpi_table_attr *table_attr; + + switch (event) { + case ACPI_TABLE_EVENT_LOAD: + table_attr = + kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); + if (!table_attr) + return AE_NO_MEMORY; + + acpi_table_attr_init(table_attr, table); + if (sysfs_create_bin_file(dynamic_tables_kobj, + &table_attr->attr)) { + kfree(table_attr); + return AE_ERROR; + } else + list_add_tail(&table_attr->node, + &acpi_table_attr_list); + break; + case ACPI_TABLE_EVENT_UNLOAD: + /* + * we do not need to do anything right now + * because the table is not deleted from the + * global table list when unloading it. + */ + break; + default: + return AE_BAD_PARAMETER; + } + return AE_OK; +} + static int acpi_system_sysfs_init(void) { struct acpi_table_attr *table_attr; @@ -137,7 +172,11 @@ static int acpi_system_sysfs_init(void) tables_kobj = kobject_create_and_add("tables", acpi_kobj); if (!tables_kobj) - return -ENOMEM; + goto err; + + dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj); + if (!dynamic_tables_kobj) + goto err_dynamic_tables; do { result = acpi_get_table_by_index(table_index, &table_header); @@ -162,8 +201,14 @@ static int acpi_system_sysfs_init(void) } } while (!result); kobject_uevent(tables_kobj, KOBJ_ADD); + kobject_uevent(dynamic_tables_kobj, KOBJ_ADD); + result = acpi_install_table_handler(acpi_sysfs_table_handler, NULL); - return 0; + return result == AE_OK ? 0 : -EINVAL; +err_dynamic_tables: + kobject_put(tables_kobj); +err: + return -ENOMEM; } /* From 4c395bdd3f2ca8f7e8efad881e16071182c3b8ca Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Wed, 4 Mar 2009 11:55:28 -0800 Subject: [PATCH 004/140] hp-wmi: notify of a potential docking state change on resume It is possible that the system gets docked or undocked while it's suspended. Generate an input event on resume to notify user space if there was a state change. As it is a switch, we can generate the event unconditionally; the input layer will only pass it on if there is an actual change. Signed-off-by: Frans Pop Cc: Matthew Garrett Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/hp-wmi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index f41135f2fb29..50d9019de2be 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -53,6 +53,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); static int __init hp_wmi_bios_setup(struct platform_device *device); static int __exit hp_wmi_bios_remove(struct platform_device *device); +static int hp_wmi_resume_handler(struct platform_device *device); struct bios_args { u32 signature; @@ -101,6 +102,7 @@ static struct platform_driver hp_wmi_driver = { }, .probe = hp_wmi_bios_setup, .remove = hp_wmi_bios_remove, + .resume = hp_wmi_resume_handler, }; static int hp_wmi_perform_query(int query, int write, int value) @@ -487,6 +489,29 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) return 0; } +static int hp_wmi_resume_handler(struct platform_device *device) +{ + struct key_entry *key; + + /* + * Docking state may have changed while suspended, so trigger + * an input event for the current state. As this is a switch, + * the input layer will only actually pass it on if the state + * changed. + */ + for (key = hp_wmi_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_SW: + input_report_switch(hp_wmi_input_dev, key->keycode, + hp_wmi_dock_state()); + input_sync(hp_wmi_input_dev); + break; + } + } + + return 0; +} + static int __init hp_wmi_init(void) { int err; From ff69f2bba67bd45514923aaedbf40fe351787c59 Mon Sep 17 00:00:00 2001 From: "alex.shi" Date: Wed, 4 Mar 2009 11:55:26 -0800 Subject: [PATCH 005/140] acpi: fix of pmtimer overflow that make Cx states time incorrect We found Cx states time abnormal in our some of machines which have 16 LCPUs, the C0 take too many time while system is really idle when kernel enabled tickless and highres. powertop output is below: PowerTOP version 1.9 (C) 2007 Intel Corporation Cn Avg residency P-states (frequencies) C0 (cpu running) (40.5%) 2.53 Ghz 0.0% C1 0.0ms ( 0.0%) 2.53 Ghz 0.0% C2 128.8ms (59.5%) 2.40 Ghz 0.0% 1.60 Ghz 100.0% Wakeups-from-idle per second : 4.7 interval: 20.0s no ACPI power usage estimate available Top causes for wakeups: 41.4% ( 24.9) : extra timer interrupt 20.2% ( 12.2) : usb_hcd_poll_rh_status (rh_timer_func) After tacking detailed for this issue, Yakui and I find it is due to 24 bit PM timer overflows when some of cpu sleep more than 4 seconds. With tickless kernel, the CPU want to sleep as much as possible when system idle. But the Cx sleep time are recorded by pmtimer which length is determined by BIOS. The current Cx time was gotten in the following function from driver/acpi/processor_idle.c: static inline u32 ticks_elapsed(u32 t1, u32 t2) { if (t2 >= t1) return (t2 - t1); else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER)) return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); else return ((0xFFFFFFFF - t1) + t2); } If pmtimer is 24 bits and it take 5 seconds from t1 to t2, in above function, just about 1 seconds ticks was recorded. So the Cx time will be reduced about 4 seconds. and this is why we see above powertop output. To resolve this problem, Yakui and I use ktime_get() to record the Cx states time instead of PM timer as the following patch. the patch was tested with i386/x86_64 modes on several platforms. Acked-by: Venkatesh Pallipadi Tested-by: Alex Shi Signed-off-by: Alex Shi Signed-off-by: Yakui.zhao Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 63 +++++++++++++++-------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7bc22a471fe3..879af875c213 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -64,7 +64,6 @@ #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_idle"); #define ACPI_PROCESSOR_FILE_POWER "power" -#define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) #define PM_TIMER_TICK_NS (1000000000ULL/PM_TIMER_FREQUENCY) #define C2_OVERHEAD 1 /* 1us */ #define C3_OVERHEAD 1 /* 1us */ @@ -78,6 +77,10 @@ module_param(nocst, uint, 0000); static unsigned int latency_factor __read_mostly = 2; module_param(latency_factor, uint, 0644); +static s64 us_to_pm_timer_ticks(s64 t) +{ + return div64_u64(t * PM_TIMER_FREQUENCY, 1000000); +} /* * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. * For now disable this. Probably a bug somewhere else. @@ -159,25 +162,6 @@ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { {}, }; -static inline u32 ticks_elapsed(u32 t1, u32 t2) -{ - if (t2 >= t1) - return (t2 - t1); - else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER)) - return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); - else - return ((0xFFFFFFFF - t1) + t2); -} - -static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) -{ - if (t2 >= t1) - return PM_TIMER_TICKS_TO_US(t2 - t1); - else if (!(acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER)) - return PM_TIMER_TICKS_TO_US(((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); - else - return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); -} /* * Callers should disable interrupts before the call and enable @@ -853,7 +837,8 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_state *state) { - u32 t1, t2; + ktime_t kt1, kt2; + s64 idle_time; struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); @@ -871,14 +856,15 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, return 0; } - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + kt1 = ktime_get_real(); acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + kt2 = ktime_get_real(); + idle_time = ktime_to_us(ktime_sub(kt2, kt1)); local_irq_enable(); cx->usage++; - return ticks_elapsed_in_us(t1, t2); + return idle_time; } /** @@ -891,8 +877,9 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, { struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); - u32 t1, t2; - int sleep_ticks = 0; + ktime_t kt1, kt2; + s64 idle_time; + s64 sleep_ticks = 0; pr = __get_cpu_var(processors); @@ -925,18 +912,19 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, if (cx->type == ACPI_STATE_C3) ACPI_FLUSH_CPU_CACHE(); - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + kt1 = ktime_get_real(); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + kt2 = ktime_get_real(); + idle_time = ktime_to_us(ktime_sub(kt2, kt1)); #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86) /* TSC could halt in idle, so notify users */ if (tsc_halts_in_c(cx->type)) mark_tsc_unstable("TSC halts in idle");; #endif - sleep_ticks = ticks_elapsed(t1, t2); + sleep_ticks = us_to_pm_timer_ticks(idle_time); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); @@ -948,7 +936,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, acpi_state_timer_broadcast(pr, cx, 0); cx->time += sleep_ticks; - return ticks_elapsed_in_us(t1, t2); + return idle_time; } static int c3_cpu_count; @@ -966,8 +954,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, { struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); - u32 t1, t2; - int sleep_ticks = 0; + ktime_t kt1, kt2; + s64 idle_time; + s64 sleep_ticks = 0; + pr = __get_cpu_var(processors); @@ -1034,9 +1024,10 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, ACPI_FLUSH_CPU_CACHE(); } - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); + kt1 = ktime_get_real(); acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + kt2 = ktime_get_real(); + idle_time = ktime_to_us(ktime_sub(kt2, kt1)); /* Re-enable bus master arbitration */ if (pr->flags.bm_check && pr->flags.bm_control) { @@ -1051,7 +1042,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (tsc_halts_in_c(ACPI_STATE_C3)) mark_tsc_unstable("TSC halts in idle"); #endif - sleep_ticks = ticks_elapsed(t1, t2); + sleep_ticks = us_to_pm_timer_ticks(idle_time); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); @@ -1062,7 +1053,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, acpi_state_timer_broadcast(pr, cx, 0); cx->time += sleep_ticks; - return ticks_elapsed_in_us(t1, t2); + return idle_time; } struct cpuidle_driver acpi_idle_driver = { From 1c9ca3a7d41b5db884033900b539b9aeb61a399e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 17 Feb 2009 14:00:40 -0700 Subject: [PATCH 006/140] ACPI: pci_link: clean up whitespace This patch makes whitespace and indentation more consistent. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 73 +++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 46 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 6c772ca76bd1..19bc3bcda602 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -43,13 +43,14 @@ #include #include -#define _COMPONENT ACPI_PCI_COMPONENT +#define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" #define ACPI_PCI_LINK_FILE_INFO "info" #define ACPI_PCI_LINK_FILE_STATUS "state" -#define ACPI_PCI_LINK_MAX_POSSIBLE 16 +#define ACPI_PCI_LINK_MAX_POSSIBLE 16 + static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); @@ -66,7 +67,7 @@ static struct acpi_driver acpi_pci_link_driver = { .ops = { .add = acpi_pci_link_add, .remove = acpi_pci_link_remove, - }, + }, }; /* @@ -76,7 +77,7 @@ static struct acpi_driver acpi_pci_link_driver = { struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 triggering; /* All IRQs */ - u8 polarity; /* All IRQs */ + u8 polarity; /* All IRQs */ u8 resource_type; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; @@ -85,15 +86,15 @@ struct acpi_pci_link_irq { }; struct acpi_pci_link { - struct list_head node; - struct acpi_device *device; - struct acpi_pci_link_irq irq; - int refcnt; + struct list_head node; + struct acpi_device *device; + struct acpi_pci_link_irq irq; + int refcnt; }; static struct { - int count; - struct list_head entries; + int count; + struct list_head entries; } acpi_link; static DEFINE_MUTEX(acpi_link_lock); @@ -104,13 +105,12 @@ static DEFINE_MUTEX(acpi_link_lock); /* * set context (link) possible list from resource list */ -static acpi_status -acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) +static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource, + void *context) { struct acpi_pci_link *link = context; u32 i = 0; - switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_END_TAG: @@ -179,7 +179,6 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) { acpi_status status; - if (!link) return -EINVAL; @@ -197,12 +196,11 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) return 0; } -static acpi_status -acpi_pci_link_check_current(struct acpi_resource *resource, void *context) +static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource, + void *context) { int *irq = (int *)context; - switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_END_TAG: @@ -316,7 +314,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) } *resource; struct acpi_buffer buffer = { 0, NULL }; - if (!link || !irq) return -EINVAL; @@ -479,10 +476,10 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ - PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ - PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ - PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ - PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ + PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ + PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ + PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ + PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ /* >IRQ15 */ }; @@ -492,12 +489,10 @@ int __init acpi_irq_penalty_init(void) struct acpi_pci_link *link = NULL; int i = 0; - /* * Update penalties to facilitate IRQ balancing. */ list_for_each(node, &acpi_link.entries) { - link = list_entry(node, struct acpi_pci_link, node); if (!link) { printk(KERN_ERR PREFIX "Invalid link context\n"); @@ -527,7 +522,6 @@ int __init acpi_irq_penalty_init(void) } /* Add a penalty for the SCI */ acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING; - return 0; } @@ -538,7 +532,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) int irq; int i; - if (link->irq.initialized) { if (link->refcnt == 0) /* This means the link is disabled but initialized */ @@ -566,11 +559,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) /* * if active found, use it; else pick entry from end of possible list. */ - if (link->irq.active) { + if (link->irq.active) irq = link->irq.active; - } else { + else irq = link->irq.possible[link->irq.possible_count - 1]; - } if (acpi_irq_balance || !link->irq.active) { /* @@ -599,7 +591,6 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) } link->irq.initialized = 1; - return 0; } @@ -608,17 +599,13 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * success: return IRQ >= 0 * failure: return -1 */ - -int -acpi_pci_link_allocate_irq(acpi_handle handle, - int index, - int *triggering, int *polarity, char **name) +int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, + int *polarity, char **name) { int result = 0; struct acpi_device *device = NULL; struct acpi_pci_link *link = NULL; - result = acpi_bus_get_device(handle, &device); if (result) { printk(KERN_ERR PREFIX "Invalid link device\n"); @@ -673,7 +660,6 @@ int acpi_pci_link_free_irq(acpi_handle handle) struct acpi_pci_link *link = NULL; acpi_status result; - result = acpi_bus_get_device(handle, &device); if (result) { printk(KERN_ERR PREFIX "Invalid link device\n"); @@ -708,9 +694,9 @@ int acpi_pci_link_free_irq(acpi_handle handle) "Link %s is dereferenced\n", acpi_device_bid(link->device))); - if (link->refcnt == 0) { + if (link->refcnt == 0) acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); - } + mutex_unlock(&acpi_link_lock); return (link->irq.active); } @@ -726,7 +712,6 @@ static int acpi_pci_link_add(struct acpi_device *device) int i = 0; int found = 0; - if (!device) return -EINVAL; @@ -784,11 +769,10 @@ static int acpi_pci_link_add(struct acpi_device *device) static int acpi_pci_link_resume(struct acpi_pci_link *link) { - if (link->refcnt && link->irq.active && link->irq.initialized) return (acpi_pci_link_set(link, link->irq.active)); - else - return 0; + + return 0; } static int irqrouter_resume(struct sys_device *dev) @@ -811,7 +795,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) { struct acpi_pci_link *link = NULL; - if (!device || !acpi_driver_data(device)) return -EINVAL; @@ -822,7 +805,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) mutex_unlock(&acpi_link_lock); kfree(link); - return 0; } @@ -931,7 +913,6 @@ static int __init irqrouter_init_sysfs(void) { int error; - if (acpi_disabled || acpi_noirq) return 0; From c9d6244329c8149312dba27e78dc4a83b35a6ae5 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 17 Feb 2009 14:00:45 -0700 Subject: [PATCH 007/140] ACPI: pci_link: remove unnecessary casts and initializations Remove unnecessary casts and initializations. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 19bc3bcda602..b59f59efb72f 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -109,7 +109,7 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) { struct acpi_pci_link *link = context; - u32 i = 0; + u32 i; switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -199,7 +199,7 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource, void *context) { - int *irq = (int *)context; + int *irq = context; switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: @@ -256,7 +256,7 @@ static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource, static int acpi_pci_link_get_current(struct acpi_pci_link *link) { int result = 0; - acpi_status status = AE_OK; + acpi_status status; int irq = 0; if (!link) @@ -306,8 +306,8 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link) static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) { - int result = 0; - acpi_status status = AE_OK; + int result; + acpi_status status; struct { struct acpi_resource res; struct acpi_resource end; @@ -485,9 +485,9 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { int __init acpi_irq_penalty_init(void) { - struct list_head *node = NULL; - struct acpi_pci_link *link = NULL; - int i = 0; + struct list_head *node; + struct acpi_pci_link *link; + int i; /* * Update penalties to facilitate IRQ balancing. @@ -602,9 +602,9 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, int *polarity, char **name) { - int result = 0; - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; + int result; + struct acpi_device *device; + struct acpi_pci_link *link; result = acpi_bus_get_device(handle, &device); if (result) { @@ -656,8 +656,8 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, */ int acpi_pci_link_free_irq(acpi_handle handle) { - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; + struct acpi_device *device; + struct acpi_pci_link *link; acpi_status result; result = acpi_bus_get_device(handle, &device); @@ -707,9 +707,9 @@ int acpi_pci_link_free_irq(acpi_handle handle) static int acpi_pci_link_add(struct acpi_device *device) { - int result = 0; - struct acpi_pci_link *link = NULL; - int i = 0; + int result; + struct acpi_pci_link *link; + int i; int found = 0; if (!device) @@ -777,8 +777,8 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link) static int irqrouter_resume(struct sys_device *dev) { - struct list_head *node = NULL; - struct acpi_pci_link *link = NULL; + struct list_head *node; + struct acpi_pci_link *link; list_for_each(node, &acpi_link.entries) { link = list_entry(node, struct acpi_pci_link, node); @@ -793,7 +793,7 @@ static int irqrouter_resume(struct sys_device *dev) static int acpi_pci_link_remove(struct acpi_device *device, int type) { - struct acpi_pci_link *link = NULL; + struct acpi_pci_link *link; if (!device || !acpi_driver_data(device)) return -EINVAL; From 6eca4b4ca168981d7648be371945c2a21f463a45 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 17 Feb 2009 14:00:50 -0700 Subject: [PATCH 008/140] ACPI: pci_link: remove unnecessary null pointer checks Better to oops and learn about a bug than to silently cover it up. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index b59f59efb72f..dd9ebb9fda42 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -179,9 +179,6 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) { acpi_status status; - if (!link) - return -EINVAL; - status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS, acpi_pci_link_check_possible, link); if (ACPI_FAILURE(status)) { @@ -259,9 +256,6 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link) acpi_status status; int irq = 0; - if (!link) - return -EINVAL; - link->irq.active = 0; /* in practice, status disabled is meaningless, ignore it */ @@ -314,7 +308,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) } *resource; struct acpi_buffer buffer = { 0, NULL }; - if (!link || !irq) + if (!irq) return -EINVAL; resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); @@ -712,9 +706,6 @@ static int acpi_pci_link_add(struct acpi_device *device) int i; int found = 0; - if (!device) - return -EINVAL; - link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); if (!link) return -ENOMEM; @@ -795,9 +786,6 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) { struct acpi_pci_link *link; - if (!device || !acpi_driver_data(device)) - return -EINVAL; - link = acpi_driver_data(device); mutex_lock(&acpi_link_lock); From 5f0dccaa81e239477413d0def1133850530f1bbe Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 17 Feb 2009 14:00:55 -0700 Subject: [PATCH 009/140] ACPI: pci_link: simplify list of link devices We don't need a struct containing a count and a list_head; a simple list_head is sufficient. The list iterators handle empty lists fine. Furthermore, we don't need to check for null list entries because we only add non-null entries. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_link.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index dd9ebb9fda42..16e0f9d3d17c 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -86,16 +86,13 @@ struct acpi_pci_link_irq { }; struct acpi_pci_link { - struct list_head node; + struct list_head list; struct acpi_device *device; struct acpi_pci_link_irq irq; int refcnt; }; -static struct { - int count; - struct list_head entries; -} acpi_link; +static LIST_HEAD(acpi_link_list); static DEFINE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- @@ -479,19 +476,13 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { int __init acpi_irq_penalty_init(void) { - struct list_head *node; struct acpi_pci_link *link; int i; /* * Update penalties to facilitate IRQ balancing. */ - list_for_each(node, &acpi_link.entries) { - link = list_entry(node, struct acpi_pci_link, node); - if (!link) { - printk(KERN_ERR PREFIX "Invalid link context\n"); - continue; - } + list_for_each_entry(link, &acpi_link_list, list) { /* * reflect the possible and active irqs in the penalty table -- @@ -743,9 +734,7 @@ static int acpi_pci_link_add(struct acpi_device *device) printk("\n"); - /* TBD: Acquire/release lock */ - list_add_tail(&link->node, &acpi_link.entries); - acpi_link.count++; + list_add_tail(&link->list, &acpi_link_list); end: /* disable all links -- to be activated on use */ @@ -768,15 +757,9 @@ static int acpi_pci_link_resume(struct acpi_pci_link *link) static int irqrouter_resume(struct sys_device *dev) { - struct list_head *node; struct acpi_pci_link *link; - list_for_each(node, &acpi_link.entries) { - link = list_entry(node, struct acpi_pci_link, node); - if (!link) { - printk(KERN_ERR PREFIX "Invalid link context\n"); - continue; - } + list_for_each_entry(link, &acpi_link_list, list) { acpi_pci_link_resume(link); } return 0; @@ -789,7 +772,7 @@ static int acpi_pci_link_remove(struct acpi_device *device, int type) link = acpi_driver_data(device); mutex_lock(&acpi_link_lock); - list_del(&link->node); + list_del(&link->list); mutex_unlock(&acpi_link_lock); kfree(link); @@ -926,9 +909,6 @@ static int __init acpi_pci_link_init(void) acpi_irq_balance = 0; } - acpi_link.count = 0; - INIT_LIST_HEAD(&acpi_link.entries); - if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) return -ENODEV; From c686d141c7c668ac186015841a1ccd285a1f3362 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 17 Feb 2009 13:49:10 -0700 Subject: [PATCH 010/140] ACPI: PCI: use generic pci_swizzle_interrupt_pin() Use the generic pci_swizzle_interrupt_pin() instead of ACPI-specific code. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 891bdf6679f3..be6b9093f8df 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -319,7 +319,7 @@ static struct acpi_prt_entry *acpi_pci_irq_lookup(struct pci_dev *dev, int pin) */ bridge = dev->bus->self; while (bridge) { - pin = (((pin - 1) + PCI_SLOT(dev->devfn)) % 4) + 1; + pin = pci_swizzle_interrupt_pin(dev, pin); if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_CARDBUS) { /* PC card has the same IRQ as its cardbridge */ From 1c48aa36ef301d7b07674313bae65ef2496801a7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 19 Feb 2009 14:45:47 -0700 Subject: [PATCH 011/140] ACPI: update Kconfig help texts (no functional changes) Use "help" (not "---help---") consistently throughout. ACPI can't be a module, so if both ACPI & APM are configured, we use ACPI. Update pointers to ACPI CA and Linux ACPI projects. Replace "Compaq" with "Hewlett-Packard" in the spec developer list. Fix typo in /sys/module path. The user-space daemon is "acpid", not "acpi". Add standard "To compile this driver as a module ..." help text. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 150 +++++++++++++++++++++++++------------------ 1 file changed, 86 insertions(+), 64 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8a851d0f4384..431f8b439553 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -11,9 +11,9 @@ menuconfig ACPI select PNP select CPU_IDLE default y - ---help--- + help Advanced Configuration and Power Interface (ACPI) support for - Linux requires an ACPI compliant platform (hardware/firmware), + Linux requires an ACPI-compliant platform (hardware/firmware), and assumes the presence of OS-directed configuration and power management (OSPM) software. This option will enlarge your kernel by about 70K. @@ -23,20 +23,19 @@ menuconfig ACPI the Plug-and-Play BIOS specification (PnP BIOS), the MultiProcessor Specification (MPS), and the Advanced Power Management (APM) specification. If both ACPI and APM support - are configured, whichever is loaded first shall be used. + are configured, ACPI is used. - The ACPI SourceForge project contains the latest source code, - documentation, tools, mailing list subscription, and other - information. This project is available at: - + The project home page for the Linux ACPI subsystem is here: + Linux support for ACPI is based on Intel Corporation's ACPI - Component Architecture (ACPI CA). For more information see: - + Component Architecture (ACPI CA). For more information on the + ACPI CA, see: + - ACPI is an open industry specification co-developed by Compaq, - Intel, Microsoft, Phoenix, and Toshiba. The specification is - available at: + ACPI is an open industry specification co-developed by + Hewlett-Packard, Intel, Microsoft, Phoenix, and Toshiba. + The specification is available at: if ACPI @@ -49,14 +48,14 @@ config ACPI_SLEEP config ACPI_PROCFS bool "Deprecated /proc/acpi files" depends on PROC_FS - ---help--- + help For backwards compatibility, this option allows deprecated /proc/acpi/ files to exist, even when they have been replaced by functions in /sys. The deprecated files (and their replacements) include: /proc/acpi/sleep (/sys/power/state) - /proc/acpi/info (/sys/modules/acpi/parameters/acpica_version) + /proc/acpi/info (/sys/module/acpi/parameters/acpica_version) /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) @@ -66,11 +65,12 @@ config ACPI_PROCFS and functions which do not yet exist in /sys. Say N to delete /proc/acpi/ files that have moved to /sys/ + config ACPI_PROCFS_POWER bool "Deprecated power /proc/acpi directories" depends on PROC_FS default y - ---help--- + help For backwards compatibility, this option allows deprecated power /proc/acpi/ directories to exist, even when they have been replaced by functions in /sys. @@ -86,19 +86,19 @@ config ACPI_SYSFS_POWER bool "Future power /sys interface" select POWER_SUPPLY default y - ---help--- + help Say N to disable power /sys interface config ACPI_PROC_EVENT bool "Deprecated /proc/acpi/event support" depends on PROC_FS default y - ---help--- - A user-space daemon, acpi, typically read /proc/acpi/event - and handled all ACPI sub-system generated events. + help + A user-space daemon, acpid, typically reads /proc/acpi/event + and handles all ACPI-generated events. - These events are now delivered to user-space via - either the input layer, or as netlink events. + These events are now delivered to user-space either + via the input layer or as netlink events. This build option enables the old code for legacy user-space implementation. After some time, this will @@ -112,10 +112,13 @@ config ACPI_AC depends on X86 default y help - This driver adds support for the AC Adapter object, which indicates - whether a system is on AC, or not. If you have a system that can + This driver supports the AC Adapter object, which indicates + whether a system is on AC or not. If you have a system that can switch between A/C and battery, say Y. + To compile this driver as a module, choose M here: + the module will be called ac. + config ACPI_BATTERY tristate "Battery" depends on X86 @@ -125,15 +128,21 @@ config ACPI_BATTERY /proc/acpi/battery. If you have a mobile system with a battery, say Y. + To compile this driver as a module, choose M here: + the module will be called battery. + config ACPI_BUTTON tristate "Button" depends on INPUT default y help - This driver handles events on the power, sleep and lid buttons. + This driver handles events on the power, sleep, and lid buttons. A daemon reads /proc/acpi/event and perform user-defined actions such as shutting down the system. This is necessary for - software controlled poweroff. + software-controlled poweroff. + + To compile this driver as a module, choose M here: + the module will be called button. config ACPI_VIDEO tristate "Video" @@ -141,38 +150,45 @@ config ACPI_VIDEO depends on INPUT select THERMAL help - This driver implement the ACPI Extensions For Display Adapters + This driver implements the ACPI Extensions For Display Adapters for integrated graphics devices on motherboard, as specified in - ACPI 2.0 Specification, Appendix B, allowing to perform some basic - control like defining the video POST device, retrieving EDID information - or to setup a video output, etc. - Note that this is an ref. implementation only. It may or may not work - for your integrated video device. + ACPI 2.0 Specification, Appendix B. This supports basic operations + such as defining the video POST device, retrieving EDID information, + and setting up a video output. + + To compile this driver as a module, choose M here: + the module will be called video. config ACPI_FAN tristate "Fan" select THERMAL default y help - This driver adds support for ACPI fan devices, allowing user-mode + This driver supports ACPI fan devices, allowing user-mode applications to perform basic fan control (on, off, status). + To compile this driver as a module, choose M here: + the module will be called fan. + config ACPI_DOCK bool "Dock" depends on EXPERIMENTAL help - This driver adds support for ACPI controlled docking stations and removable - drive bays such as the IBM ultrabay or the Dell Module Bay. + This driver supports ACPI-controlled docking stations and removable + drive bays such as the IBM Ultrabay and the Dell Module Bay. config ACPI_PROCESSOR tristate "Processor" select THERMAL default y help - This driver installs ACPI as the idle handler for Linux, and uses - ACPI C2 and C3 processor states to save power, on systems that + This driver installs ACPI as the idle handler for Linux and uses + ACPI C2 and C3 processor states to save power on systems that support it. It is required by several flavors of cpufreq - Performance-state drivers. + performance-state drivers. + + To compile this driver as a module, choose M here: + the module will be called processor. config ACPI_HOTPLUG_CPU bool @@ -186,11 +202,14 @@ config ACPI_THERMAL select THERMAL default y help - This driver adds support for ACPI thermal zones. Most mobile and + This driver supports ACPI thermal zones. Most mobile and some desktop systems support ACPI thermal zones. It is HIGHLY recommended that this option be enabled, as your processor(s) may be damaged without it. + To compile this driver as a module, choose M here: + the module will be called thermal. + config ACPI_NUMA bool "NUMA support" depends on NUMA @@ -218,7 +237,7 @@ config ACPI_BLACKLIST_YEAR int "Disable ACPI for systems before Jan 1st this year" if X86_32 default 0 help - enter a 4-digit year, eg. 2001 to disable ACPI by default + Enter a 4-digit year, e.g., 2001, to disable ACPI by default on platforms with DMI BIOS date before January 1st that year. "acpi=force" can be used to override this mechanism. @@ -249,10 +268,13 @@ config ACPI_PCI_SLOT tristate "PCI slot detection driver" default n help - This driver will attempt to discover all PCI slots in your system, - and creates entries in /sys/bus/pci/slots/. This feature can - help you correlate PCI bus addresses with the physical geography - of your slots. If you are unsure, say N. + This driver creates entries in /sys/bus/pci/slots/ for all PCI + slots in the system. This can help correlate PCI bus addresses, + i.e., segment/bus/device/function tuples, with physical slots in + the system. If you are unsure, say N. + + To compile this driver as a module, choose M here: + the module will be called pci_slot. config X86_PM_TIMER bool "Power Management Timer Support" if EMBEDDED @@ -271,43 +293,43 @@ config X86_PM_TIMER systems require this timer. config ACPI_CONTAINER - tristate "ACPI0004,PNP0A05 and PNP0A06 Container Driver (EXPERIMENTAL)" + tristate "Container and Module Devices (EXPERIMENTAL)" depends on EXPERIMENTAL default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO) - ---help--- - This allows _physical_ insertion and removal of CPUs and memory. - This can be useful, for example, on NUMA machines that support - ACPI based physical hotplug of nodes, or non-NUMA machines that - support physical cpu/memory hot-plug. + help + This driver supports ACPI Container and Module devices (IDs + ACPI0004, PNP0A05, and PNP0A06). - If one selects "m", this driver can be loaded with - "modprobe container". + This helps support hotplug of nodes, CPUs, and memory. + + To compile this driver as a module, choose M here: + the module will be called container. config ACPI_HOTPLUG_MEMORY tristate "Memory Hotplug" depends on MEMORY_HOTPLUG default n help - This driver adds supports for ACPI Memory Hotplug. This driver - provides support for fielding notifications on ACPI memory - devices (PNP0C80) which represent memory ranges that may be - onlined or offlined during runtime. + This driver supports ACPI memory hotplug. The driver + fields notifications on ACPI memory devices (PNP0C80), + which represent memory ranges that may be onlined or + offlined during runtime. - Enabling this driver assumes that your platform hardware - and firmware have support for hot-plugging physical memory. If - your system does not support physically adding or ripping out - memory DIMMs at some platform defined granularity (individually - or as a bank) at runtime, then you need not enable this driver. + If your hardware and firmware do not support adding or + removing memory devices at runtime, you need not enable + this driver. - If one selects "m," this driver can be loaded using the following - command: - $>modprobe acpi_memhotplug + To compile this driver as a module, choose M here: + the module will be called acpi_memhotplug. config ACPI_SBS tristate "Smart Battery System" depends on X86 help - This driver adds support for the Smart Battery System, another + This driver supports the Smart Battery System, another type of access to battery information, found on some laptops. + To compile this driver as a module, choose M here: + the modules will be called sbs and sbshc. + endif # ACPI From e60cc7a6f02598fc23c68a656fe9c263d6531ca0 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 13 Mar 2009 12:08:26 -0600 Subject: [PATCH 012/140] ACPI: move private declarations to internal.h A number of things that shouldn't be exposed outside the ACPI core were declared in include/acpi/acpi_drivers.h, where anybody can see them. This patch moves those declarations to a new "internal.h" inside drivers/acpi. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 2 ++ drivers/acpi/internal.h | 24 ++++++++++++++++++++++++ drivers/acpi/scan.c | 2 ++ drivers/acpi/sleep.c | 2 ++ drivers/acpi/wakeup.c | 2 ++ include/acpi/acpi_drivers.h | 23 ----------------------- 6 files changed, 32 insertions(+), 23 deletions(-) create mode 100644 drivers/acpi/internal.h diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd6..2e90410a3035 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -39,6 +39,8 @@ #include #include +#include "internal.h" + #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("bus"); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h new file mode 100644 index 000000000000..4aee4a236fc9 --- /dev/null +++ b/drivers/acpi/internal.h @@ -0,0 +1,24 @@ +/* For use by Linux/ACPI infrastructure, not drivers */ + +/* -------------------------------------------------------------------------- + Power Resource + -------------------------------------------------------------------------- */ + +int acpi_device_sleep_wake(struct acpi_device *dev, + int enable, int sleep_state, int dev_state); +int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); +int acpi_disable_wakeup_device_power(struct acpi_device *dev); +int acpi_power_get_inferred_state(struct acpi_device *device); +int acpi_power_transition(struct acpi_device *device, int state); +extern int acpi_power_nocheck; + +/* -------------------------------------------------------------------------- + Embedded Controller + -------------------------------------------------------------------------- */ +int acpi_ec_ecdt_probe(void); +int acpi_boot_ec_enable(void); + +/*-------------------------------------------------------------------------- + Suspend/Resume + -------------------------------------------------------------------------- */ +extern int acpi_sleep_init(void); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c54d7b6c4066..2f04cd1147e9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -11,6 +11,8 @@ #include +#include "internal.h" + #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("scan"); #define STRUCT_TO_INT(s) (*((int*)&s)) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 519266654f06..0f86cf74216b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -21,6 +21,8 @@ #include #include + +#include "internal.h" #include "sleep.h" u8 sleep_states[ACPI_S_STATE_COUNT]; diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 2d34806d45dd..3f29fd53e9a6 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -8,6 +8,8 @@ #include #include #include + +#include "internal.h" #include "sleep.h" #define _COMPONENT ACPI_SYSTEM_COMPONENT diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 5fc1bb0f4a90..241d227de6c0 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -98,24 +98,6 @@ int acpi_pci_bind_root(struct acpi_device *device, struct acpi_pci_id *id, struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain, int bus); -/* -------------------------------------------------------------------------- - Power Resource - -------------------------------------------------------------------------- */ - -int acpi_device_sleep_wake(struct acpi_device *dev, - int enable, int sleep_state, int dev_state); -int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); -int acpi_disable_wakeup_device_power(struct acpi_device *dev); -int acpi_power_get_inferred_state(struct acpi_device *device); -int acpi_power_transition(struct acpi_device *device, int state); -extern int acpi_power_nocheck; - -/* -------------------------------------------------------------------------- - Embedded Controller - -------------------------------------------------------------------------- */ -int acpi_ec_ecdt_probe(void); -int acpi_boot_ec_enable(void); - /* -------------------------------------------------------------------------- Processor -------------------------------------------------------------------------- */ @@ -165,9 +147,4 @@ static inline void unregister_hotplug_dock_device(acpi_handle handle) } #endif -/*-------------------------------------------------------------------------- - Suspend/Resume - -------------------------------------------------------------------------- */ -extern int acpi_sleep_init(void); - #endif /*__ACPI_DRIVERS_H__*/ From 4bbfb85da27c27e9cc9a7fef4bd75df6361152ff Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Feb 2009 14:17:29 +0800 Subject: [PATCH 013/140] ACPICA: Add error check to debug object dump routine Add check for invalid handle in acpi_ns_dump_one_object. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nsdump.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 0da33c8e9ba2..e96d37a596b8 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -181,6 +181,12 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, } this_node = acpi_ns_map_handle_to_node(obj_handle); + if (!this_node) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n", + obj_handle)); + return (AE_OK); + } + type = this_node->type; /* Check if the owner matches */ From ac5f98db7be34cefc244026f882cf030debb7431 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Feb 2009 14:35:25 +0800 Subject: [PATCH 014/140] ACPICA: Allow OS override of all ACPI tables Previously, the table override mechanism was implemented for the DSDT only. Now, any table in the RSDT/XSDT can be replaced by the host OS. (including the DSDT). Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acglobal.h | 1 - drivers/acpi/acpica/tbutils.c | 59 ++++++++++++++++++++++++++-------- drivers/acpi/acpica/tbxface.c | 31 +----------------- include/acpi/actbl.h | 5 +-- 4 files changed, 50 insertions(+), 46 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index ddb40f5c68fc..634fb0785e7e 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -371,7 +371,6 @@ ACPI_EXTERN char *acpi_gbl_db_buffer; ACPI_EXTERN char *acpi_gbl_db_filename; ACPI_EXTERN u32 acpi_gbl_db_debug_level; ACPI_EXTERN u32 acpi_gbl_db_console_debug_level; -ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node; /* diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 22ce48985720..e285bedbb989 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -287,7 +287,10 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) * * RETURN: None * - * DESCRIPTION: Install an ACPI table into the global data structure. + * DESCRIPTION: Install an ACPI table into the global data structure. The + * table override mechanism is implemented here to allow the host + * OS to replace any table before it is installed in the root + * table array. * ******************************************************************************/ @@ -295,7 +298,10 @@ void acpi_tb_install_table(acpi_physical_address address, u8 flags, char *signature, u32 table_index) { - struct acpi_table_header *table; + acpi_status status; + struct acpi_table_header *table_to_install; + struct acpi_table_header *mapped_table; + struct acpi_table_header *override_table = NULL; if (!address) { ACPI_ERROR((AE_INFO, @@ -306,41 +312,68 @@ acpi_tb_install_table(acpi_physical_address address, /* Map just the table header */ - table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); - if (!table) { + mapped_table = + acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!mapped_table) { return; } - /* If a particular signature is expected, signature must match */ + /* If a particular signature is expected (DSDT/FACS), it must match */ - if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) { + if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) { ACPI_ERROR((AE_INFO, - "Invalid signature 0x%X for ACPI table [%s]", - *ACPI_CAST_PTR(u32, table->signature), signature)); + "Invalid signature 0x%X for ACPI table, expected [%s]", + *ACPI_CAST_PTR(u32, mapped_table->signature), + signature)); goto unmap_and_exit; } + /* + * ACPI Table Override: + * + * Before we install the table, let the host OS override it with a new + * one if desired. Any table within the RSDT/XSDT can be replaced, + * including the DSDT which is pointed to by the FADT. + */ + status = acpi_os_table_override(mapped_table, &override_table); + if (ACPI_SUCCESS(status) && override_table) { + ACPI_INFO((AE_INFO, + "%4.4s @ 0x%p Table override, replaced with:", + mapped_table->signature, ACPI_CAST_PTR(void, + address))); + + acpi_gbl_root_table_list.tables[table_index].pointer = + override_table; + flags = ACPI_TABLE_ORIGIN_OVERRIDE; + address = ACPI_PTR_TO_PHYSADDR(override_table); + + table_to_install = override_table; + } else { + table_to_install = mapped_table; + } + /* Initialize the table entry */ acpi_gbl_root_table_list.tables[table_index].address = address; - acpi_gbl_root_table_list.tables[table_index].length = table->length; + acpi_gbl_root_table_list.tables[table_index].length = + table_to_install->length; acpi_gbl_root_table_list.tables[table_index].flags = flags; ACPI_MOVE_32_TO_32(& (acpi_gbl_root_table_list.tables[table_index]. - signature), table->signature); + signature), table_to_install->signature); - acpi_tb_print_table_header(address, table); + acpi_tb_print_table_header(address, table_to_install); if (table_index == ACPI_TABLE_INDEX_DSDT) { /* Global integer width is based upon revision of the DSDT */ - acpi_ut_set_integer_width(table->revision); + acpi_ut_set_integer_width(table_to_install->revision); } unmap_and_exit: - acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); + acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header)); } /******************************************************************************* diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index c3e841f3cde9..f3f95e386334 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -491,7 +491,6 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) static acpi_status acpi_tb_load_namespace(void) { acpi_status status; - struct acpi_table_header *table; u32 i; ACPI_FUNCTION_TRACE(tb_load_namespace); @@ -515,41 +514,13 @@ static acpi_status acpi_tb_load_namespace(void) goto unlock_and_exit; } - /* - * Find DSDT table - */ - status = - acpi_os_table_override(acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT].pointer, - &table); - if (ACPI_SUCCESS(status) && table) { - /* - * DSDT table has been found - */ - acpi_tb_delete_table(&acpi_gbl_root_table_list. - tables[ACPI_TABLE_INDEX_DSDT]); - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = - table; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = - table->length; - acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = - ACPI_TABLE_ORIGIN_UNKNOWN; - - ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); - acpi_tb_print_table_header(0, table); - - if (no_auto_ssdt == 0) { - printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n"); - } - } + /* A valid DSDT is required */ status = acpi_tb_verify_table(&acpi_gbl_root_table_list. tables[ACPI_TABLE_INDEX_DSDT]); if (ACPI_FAILURE(status)) { - /* A valid DSDT is required */ - status = AE_NO_ACPI_TABLES; goto unlock_and_exit; } diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index bf8d4cfd8cf5..1f3dfdb1b370 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -310,8 +310,9 @@ struct acpi_table_desc { #define ACPI_TABLE_ORIGIN_UNKNOWN (0) #define ACPI_TABLE_ORIGIN_MAPPED (1) #define ACPI_TABLE_ORIGIN_ALLOCATED (2) -#define ACPI_TABLE_ORIGIN_MASK (3) -#define ACPI_TABLE_IS_LOADED (4) +#define ACPI_TABLE_ORIGIN_OVERRIDE (4) +#define ACPI_TABLE_ORIGIN_MASK (7) +#define ACPI_TABLE_IS_LOADED (8) /* * Get the remaining ACPI tables From 97cbb7d196845ec9a6c0e3cc33ec20503f8c4e73 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Feb 2009 14:41:03 +0800 Subject: [PATCH 015/140] ACPICA: Remove extraneous parameter in table manager Removed the Flags parameter from several internal functions since it was not being used. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/actables.h | 7 +++---- drivers/acpi/acpica/tbfadt.c | 7 +++---- drivers/acpi/acpica/tbutils.c | 14 +++++++------- drivers/acpi/acpica/tbxface.c | 3 +-- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 7ce6e33c7f78..d8f8c5df4fbc 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -49,7 +49,7 @@ acpi_status acpi_allocate_root_table(u32 initial_table_count); /* * tbfadt - FADT parse/convert/validate */ -void acpi_tb_parse_fadt(u32 table_index, u8 flags); +void acpi_tb_parse_fadt(u32 table_index); void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length); @@ -109,9 +109,8 @@ acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length); void acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index); + char *signature, u32 table_index); -acpi_status -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags); +acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address); #endif /* __ACTABLES_H__ */ diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 3636e4f8fb73..4b683ccd4a94 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -172,7 +172,6 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, * FUNCTION: acpi_tb_parse_fadt * * PARAMETERS: table_index - Index for the FADT - * Flags - Flags * * RETURN: None * @@ -181,7 +180,7 @@ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, * ******************************************************************************/ -void acpi_tb_parse_fadt(u32 table_index, u8 flags) +void acpi_tb_parse_fadt(u32 table_index) { u32 length; struct acpi_table_header *table; @@ -219,10 +218,10 @@ void acpi_tb_parse_fadt(u32 table_index, u8 flags) /* Obtain the DSDT and FACS tables via their addresses within the FADT */ acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, - flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); + ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); acpi_tb_install_table((acpi_physical_address) acpi_gbl_FADT.Xfacs, - flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); + ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS); } /******************************************************************************* diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index e285bedbb989..a0b424356b98 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -280,7 +280,6 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) * FUNCTION: acpi_tb_install_table * * PARAMETERS: Address - Physical address of DSDT or FACS - * Flags - Flags * Signature - Table signature, NULL if no need to * match * table_index - Index into root table array @@ -296,8 +295,9 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length) void acpi_tb_install_table(acpi_physical_address address, - u8 flags, char *signature, u32 table_index) + char *signature, u32 table_index) { + u8 flags; acpi_status status; struct acpi_table_header *table_to_install; struct acpi_table_header *mapped_table; @@ -344,12 +344,13 @@ acpi_tb_install_table(acpi_physical_address address, acpi_gbl_root_table_list.tables[table_index].pointer = override_table; - flags = ACPI_TABLE_ORIGIN_OVERRIDE; address = ACPI_PTR_TO_PHYSADDR(override_table); table_to_install = override_table; + flags = ACPI_TABLE_ORIGIN_OVERRIDE; } else { table_to_install = mapped_table; + flags = ACPI_TABLE_ORIGIN_MAPPED; } /* Initialize the table entry */ @@ -435,7 +436,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) * FUNCTION: acpi_tb_parse_root_table * * PARAMETERS: Rsdp - Pointer to the RSDP - * Flags - Flags * * RETURN: Status * @@ -449,7 +449,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) ******************************************************************************/ acpi_status __init -acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) +acpi_tb_parse_root_table(acpi_physical_address rsdp_address) { struct acpi_table_rsdp *rsdp; u32 table_entry_size; @@ -600,14 +600,14 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) */ for (i = 2; i < acpi_gbl_root_table_list.count; i++) { acpi_tb_install_table(acpi_gbl_root_table_list.tables[i]. - address, flags, NULL, i); + address, NULL, i); /* Special case for FADT - get the DSDT and FACS */ if (ACPI_COMPARE_NAME (&acpi_gbl_root_table_list.tables[i].signature, ACPI_SIG_FADT)) { - acpi_tb_parse_fadt(i, flags); + acpi_tb_parse_fadt(i); } } diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index f3f95e386334..416d01d9a970 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -150,8 +150,7 @@ acpi_initialize_tables(struct acpi_table_desc * initial_table_array, * Root Table Array. This array contains the information of the RSDT/XSDT * in a common, more useable format. */ - status = - acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED); + status = acpi_tb_parse_root_table(rsdp_address); return_ACPI_STATUS(status); } From d3ccaff827cef5a5c5a0f3c97e1e2e6d99f618cb Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Feb 2009 14:43:04 +0800 Subject: [PATCH 016/140] ACPICA: Add override for dynamic tables Add a call to acpi_os_table_override during the installation of a dynamic table (loaded via the Load or LoadTable AML operators). Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbinstal.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 37374b21969d..ef269a297b57 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -103,7 +103,9 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) * * RETURN: Status * - * DESCRIPTION: This function is called to add the ACPI table + * DESCRIPTION: This function is called to add an ACPI table. It is used to + * dynamically load tables via the Load and load_table AML + * operators. * ******************************************************************************/ @@ -112,6 +114,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; acpi_status status = AE_OK; + struct acpi_table_header *override_table = NULL; ACPI_FUNCTION_TRACE(tb_add_table); @@ -201,6 +204,29 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } } + /* + * ACPI Table Override: + * Allow the host to override dynamically loaded tables. + */ + status = acpi_os_table_override(table_desc->pointer, &override_table); + if (ACPI_SUCCESS(status) && override_table) { + ACPI_INFO((AE_INFO, + "%4.4s @ 0x%p Table override, replaced with:", + table_desc->pointer->signature, + ACPI_CAST_PTR(void, table_desc->address))); + + /* We can delete the table that was passed as a parameter */ + + acpi_tb_delete_table(table_desc); + + /* Setup descriptor for the new table */ + + table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table); + table_desc->pointer = override_table; + table_desc->length = override_table->length; + table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE; + } + /* Add the table to the global root table list */ status = acpi_tb_store_table(table_desc->address, table_desc->pointer, From 993958fecab6eabc6ee5b7ed65c56d716fd5cfe3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Feb 2009 15:14:33 +0800 Subject: [PATCH 017/140] ACPICA: Update FADT flag definitions Add new flags in the Boot Architecture flags field. Update comments for all FADT flags. Add FADT version when each flag was defined. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/pci/pci-acpi.c | 4 +-- include/acpi/actbl.h | 69 +++++++++++++++++++++--------------------- 2 files changed, 36 insertions(+), 37 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index deea8a187eb8..368ca72dffbc 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -386,12 +386,12 @@ static int __init acpi_pci_init(void) { int ret; - if (acpi_gbl_FADT.boot_flags & BAF_MSI_NOT_SUPPORTED) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) { printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n"); pci_no_msi(); } - if (acpi_gbl_FADT.boot_flags & BAF_PCIE_ASPM_CONTROL) { + if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); pcie_no_aspm(); } diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 1f3dfdb1b370..222733d01f36 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -214,11 +214,11 @@ struct acpi_table_fadt { u16 flush_size; /* Processor's memory cache line width, in bytes */ u16 flush_stride; /* Number of flush strides that need to be read */ u8 duty_offset; /* Processor duty cycle index in processor's P_CNT reg */ - u8 duty_width; /* Processor duty cycle value bit width in P_CNT register. */ + u8 duty_width; /* Processor duty cycle value bit width in P_CNT register */ u8 day_alarm; /* Index to day-of-month alarm in RTC CMOS RAM */ u8 month_alarm; /* Index to month-of-year alarm in RTC CMOS RAM */ u8 century; /* Index to century in RTC CMOS RAM */ - u16 boot_flags; /* IA-PC Boot Architecture Flags. See Table 5-10 for description */ + u16 boot_flags; /* IA-PC Boot Architecture Flags (see below for individual flags) */ u8 reserved; /* Reserved, must be zero */ u32 flags; /* Miscellaneous flag bits (see below for individual flags) */ struct acpi_generic_address reset_register; /* 64-bit address of the Reset register */ @@ -236,32 +236,41 @@ struct acpi_table_fadt { struct acpi_generic_address xgpe1_block; /* 64-bit Extended General Purpose Event 1 Reg Blk address */ }; +/* FADT Boot Architecture Flags (boot_flags) */ + +#define ACPI_FADT_LEGACY_DEVICES (1) /* 00: [V2] System has LPC or ISA bus devices */ +#define ACPI_FADT_8042 (1<<1) /* 01: [V3] System has an 8042 controller on port 60/64 */ +#define ACPI_FADT_NO_VGA (1<<2) /* 02: [V4] It is not safe to probe for VGA hardware */ +#define ACPI_FADT_NO_MSI (1<<3) /* 03: [V4] Message Signaled Interrupts (MSI) must not be enabled */ +#define ACPI_FADT_NO_ASPM (1<<4) /* 04: [V4] PCIe ASPM control must not be enabled */ + +#define FADT2_REVISION_ID 3 + /* FADT flags */ -#define ACPI_FADT_WBINVD (1) /* 00: The wbinvd instruction works properly */ -#define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: The wbinvd flushes but does not invalidate */ -#define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: All processors support C1 state */ -#define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: C2 state works on MP system */ -#define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: Power button is handled as a generic feature */ -#define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: Sleep button is handled as a generic feature, or not present */ -#define ACPI_FADT_FIXED_RTC (1<<6) /* 06: RTC wakeup stat not in fixed register space */ -#define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: RTC wakeup possible from S4 */ -#define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: tmr_val is 32 bits 0=24-bits */ -#define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: Docking supported */ -#define ACPI_FADT_RESET_REGISTER (1<<10) /* 10: System reset via the FADT RESET_REG supported */ -#define ACPI_FADT_SEALED_CASE (1<<11) /* 11: No internal expansion capabilities and case is sealed */ -#define ACPI_FADT_HEADLESS (1<<12) /* 12: No local video capabilities or local input devices */ -#define ACPI_FADT_SLEEP_TYPE (1<<13) /* 13: Must execute native instruction after writing SLP_TYPx register */ -#define ACPI_FADT_PCI_EXPRESS_WAKE (1<<14) /* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ -#define ACPI_FADT_PLATFORM_CLOCK (1<<15) /* 15: OSPM should use platform-provided timer (ACPI 3.0) */ -#define ACPI_FADT_S4_RTC_VALID (1<<16) /* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ -#define ACPI_FADT_REMOTE_POWER_ON (1<<17) /* 17: System is compatible with remote power on (ACPI 3.0) */ -#define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: All local APICs must use cluster model (ACPI 3.0) */ -#define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: All local x_aPICs must use physical dest mode (ACPI 3.0) */ +#define ACPI_FADT_WBINVD (1) /* 00: [V1] The wbinvd instruction works properly */ +#define ACPI_FADT_WBINVD_FLUSH (1<<1) /* 01: [V1] wbinvd flushes but does not invalidate caches */ +#define ACPI_FADT_C1_SUPPORTED (1<<2) /* 02: [V1] All processors support C1 state */ +#define ACPI_FADT_C2_MP_SUPPORTED (1<<3) /* 03: [V1] C2 state works on MP system */ +#define ACPI_FADT_POWER_BUTTON (1<<4) /* 04: [V1] Power button is handled as a control method device */ +#define ACPI_FADT_SLEEP_BUTTON (1<<5) /* 05: [V1] Sleep button is handled as a control method device */ +#define ACPI_FADT_FIXED_RTC (1<<6) /* 06: [V1] RTC wakeup status not in fixed register space */ +#define ACPI_FADT_S4_RTC_WAKE (1<<7) /* 07: [V1] RTC alarm can wake system from S4 */ +#define ACPI_FADT_32BIT_TIMER (1<<8) /* 08: [V1] ACPI timer width is 32-bit (0=24-bit) */ +#define ACPI_FADT_DOCKING_SUPPORTED (1<<9) /* 09: [V1] Docking supported */ +#define ACPI_FADT_RESET_REGISTER (1<<10) /* 10: [V2] System reset via the FADT RESET_REG supported */ +#define ACPI_FADT_SEALED_CASE (1<<11) /* 11: [V3] No internal expansion capabilities and case is sealed */ +#define ACPI_FADT_HEADLESS (1<<12) /* 12: [V3] No local video capabilities or local input devices */ +#define ACPI_FADT_SLEEP_TYPE (1<<13) /* 13: [V3] Must execute native instruction after writing SLP_TYPx register */ +#define ACPI_FADT_PCI_EXPRESS_WAKE (1<<14) /* 14: [V4] System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */ +#define ACPI_FADT_PLATFORM_CLOCK (1<<15) /* 15: [V4] OSPM should use platform-provided timer (ACPI 3.0) */ +#define ACPI_FADT_S4_RTC_VALID (1<<16) /* 16: [V4] Contents of RTC_STS valid after S4 wake (ACPI 3.0) */ +#define ACPI_FADT_REMOTE_POWER_ON (1<<17) /* 17: [V4] System is compatible with remote power on (ACPI 3.0) */ +#define ACPI_FADT_APIC_CLUSTER (1<<18) /* 18: [V4] All local APICs must use cluster model (ACPI 3.0) */ +#define ACPI_FADT_APIC_PHYSICAL (1<<19) /* 19: [V4] All local x_aPICs must use physical dest mode (ACPI 3.0) */ + +/* FADT Prefered Power Management Profiles */ -/* - * FADT Prefered Power Management Profiles - */ enum acpi_prefered_pm_profiles { PM_UNSPECIFIED = 0, PM_DESKTOP = 1, @@ -272,16 +281,6 @@ enum acpi_prefered_pm_profiles { PM_APPLIANCE_PC = 6 }; -/* FADT Boot Arch Flags */ - -#define BAF_LEGACY_DEVICES 0x0001 -#define BAF_8042_KEYBOARD_CONTROLLER 0x0002 -#define BAF_MSI_NOT_SUPPORTED 0x0008 -#define BAF_PCIE_ASPM_CONTROL 0x0010 - -#define FADT2_REVISION_ID 3 -#define FADT2_MINUS_REVISION_ID 2 - /* Reset to default packing */ #pragma pack() From 6fc69d8beb0c16311f737df2c6f677057d50ab05 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Tue, 3 Feb 2009 15:16:51 +0800 Subject: [PATCH 018/140] ACPICA: Update version to 20090123 Update version to 20090123. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c8e8cf45830f..8f9df6235255 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20081204 +#define ACPI_CA_VERSION 0x20090123 #include "actypes.h" #include "actbl.h" From 531c633d2be8e79087335a46d3c017ca5837e588 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:06:12 +0800 Subject: [PATCH 019/140] ACPICA: Split out PM1 status registers from the FADT Add new globals for the PM1 status registers (A/B), similar to the way the PM1 enable registers are handled. Instead of overloading the FADT Event Register blocks. This makes the code clearer and less prone to error. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acglobal.h | 5 +- drivers/acpi/acpica/hwregs.c | 18 +-- drivers/acpi/acpica/tbfadt.c | 246 ++++++++++++++++++--------------- 3 files changed, 147 insertions(+), 122 deletions(-) diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 634fb0785e7e..f3e87ba43dbe 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -148,9 +148,12 @@ ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT; ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; -/* These addresses are calculated from FADT address values */ +/* These addresses are calculated from the FADT Event Block addresses */ +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_status; ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1a_enable; + +ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status; ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable; /* diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 4dc43b018517..7ef0b8eadbc7 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -72,21 +72,23 @@ acpi_status acpi_hw_clear_acpi_status(void) ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", ACPI_BITMASK_ALL_FIXED_STATUS, - (u16) acpi_gbl_FADT.xpm1a_event_block.address)); + (u16) acpi_gbl_xpm1a_status.address)); lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); + /* Clear the fixed events */ + status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, ACPI_BITMASK_ALL_FIXED_STATUS); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } - /* Clear the fixed events */ + /* Write PM1B register if present */ - if (acpi_gbl_FADT.xpm1b_event_block.address) { + if (acpi_gbl_xpm1b_status.address) { status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT.xpm1b_event_block); + &acpi_gbl_xpm1b_status); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -150,14 +152,14 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_event_block); + status = acpi_read(&value1, &acpi_gbl_xpm1a_status); if (ACPI_FAILURE(status)) { goto exit; } /* PM1B is optional */ - status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_event_block); + status = acpi_read(&value2, &acpi_gbl_xpm1b_status); value1 |= value2; break; @@ -267,14 +269,14 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) /* Now we can write the data */ - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_event_block); + status = acpi_write(value, &acpi_gbl_xpm1a_status); if (ACPI_FAILURE(status)) { goto exit; } /* PM1B is optional */ - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_event_block); + status = acpi_write(value, &acpi_gbl_xpm1b_status); break; case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 4b683ccd4a94..a8191efd9aa6 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -57,6 +57,8 @@ static void acpi_tb_convert_fadt(void); static void acpi_tb_validate_fadt(void); +static void acpi_tb_setup_fadt_registers(void); + /* Table for conversion of FADT to common internal format and FADT validation */ typedef struct acpi_fadt_info { @@ -132,6 +134,35 @@ static struct acpi_fadt_info fadt_info_table[] = { #define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) +/* Table used to split Event Blocks into separate status/enable registers */ + +typedef struct acpi_fadt_pm_info { + struct acpi_generic_address *target; + u8 source; + u8 register_num; + +} acpi_fadt_pm_info; + +static struct acpi_fadt_pm_info fadt_pm_info_table[] = { + {&acpi_gbl_xpm1a_status, + ACPI_FADT_OFFSET(xpm1a_event_block), + 0}, + + {&acpi_gbl_xpm1a_enable, + ACPI_FADT_OFFSET(xpm1a_event_block), + 1}, + + {&acpi_gbl_xpm1b_status, + ACPI_FADT_OFFSET(xpm1b_event_block), + 0}, + + {&acpi_gbl_xpm1b_enable, + ACPI_FADT_OFFSET(xpm1b_event_block), + 1} +}; + +#define ACPI_FADT_PM_INFO_ENTRIES (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info)) + /******************************************************************************* * * FUNCTION: acpi_tb_init_generic_address @@ -207,7 +238,7 @@ void acpi_tb_parse_fadt(u32 table_index) */ (void)acpi_tb_verify_checksum(table, length); - /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ + /* Create a local copy of the FADT in common ACPI 2.0+ format */ acpi_tb_create_local_fadt(table, length); @@ -265,11 +296,17 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) ACPI_MEMCPY(&acpi_gbl_FADT, table, ACPI_MIN(length, sizeof(struct acpi_table_fadt))); - /* - * 1) Convert the local copy of the FADT to the common internal format - * 2) Validate some of the important values within the FADT - */ + /* Convert the local copy of the FADT to the common internal format */ + acpi_tb_convert_fadt(); + + /* Validate FADT values now, before we make any changes */ + + acpi_tb_validate_fadt(); + + /* Initialize the global ACPI register structures */ + + acpi_tb_setup_fadt_registers(); } /******************************************************************************* @@ -303,8 +340,6 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) static void acpi_tb_convert_fadt(void) { - u8 pm1_register_bit_width; - u8 pm1_register_byte_width; struct acpi_generic_address *target64; u32 i; @@ -379,112 +414,6 @@ static void acpi_tb_convert_fadt(void) address32)); } } - - /* Validate FADT values now, before we make any changes */ - - acpi_tb_validate_fadt(); - - /* - * Optionally check all register lengths against the default values and - * update them if they are incorrect. - */ - if (acpi_gbl_use_default_register_widths) { - for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target64 = - ACPI_ADD_PTR(struct acpi_generic_address, - &acpi_gbl_FADT, - fadt_info_table[i].address64); - - /* - * If a valid register (Address != 0) and the (default_length > 0) - * (Not a GPE register), then check the width against the default. - */ - if ((target64->address) && - (fadt_info_table[i].default_length > 0) && - (fadt_info_table[i].default_length != - target64->bit_width)) { - ACPI_WARNING((AE_INFO, - "Invalid length for %s: %d, using default %d", - fadt_info_table[i].name, - target64->bit_width, - fadt_info_table[i]. - default_length)); - - /* Incorrect size, set width to the default */ - - target64->bit_width = - fadt_info_table[i].default_length; - } - } - } - - /* - * Get the length of the individual PM1 registers (enable and status). - * Each register is defined to be (event block length / 2). - */ - pm1_register_bit_width = - (u8)ACPI_DIV_2(acpi_gbl_FADT.xpm1a_event_block.bit_width); - pm1_register_byte_width = (u8)ACPI_DIV_8(pm1_register_bit_width); - - /* - * Adjust the lengths of the PM1 Event Blocks so that they can be used to - * access the PM1 status register(s). Use (width / 2) - */ - acpi_gbl_FADT.xpm1a_event_block.bit_width = pm1_register_bit_width; - acpi_gbl_FADT.xpm1b_event_block.bit_width = pm1_register_bit_width; - - /* - * Calculate separate GAS structs for the PM1 Enable registers. - * These addresses do not appear (directly) in the FADT, so it is - * useful to calculate them once, here. - * - * The PM event blocks are split into two register blocks, first is the - * PM Status Register block, followed immediately by the PM Enable - * Register block. Each is of length (xpm1x_event_block.bit_width/2). - * - * On various systems the v2 fields (and particularly the bit widths) - * cannot be relied upon, though. Hence resort to using the v1 length - * here (and warn about the inconsistency). - */ - if (acpi_gbl_FADT.xpm1a_event_block.bit_width - != acpi_gbl_FADT.pm1_event_length * 8) - printk(KERN_WARNING "FADT: " - "X_PM1a_EVT_BLK.bit_width (%u) does not match" - " PM1_EVT_LEN (%u)\n", - acpi_gbl_FADT.xpm1a_event_block.bit_width, - acpi_gbl_FADT.pm1_event_length); - - /* The PM1A register block is required */ - - acpi_tb_init_generic_address(&acpi_gbl_xpm1a_enable, - acpi_gbl_FADT.xpm1a_event_block.space_id, - pm1_register_byte_width, - (acpi_gbl_FADT.xpm1a_event_block.address + - pm1_register_byte_width)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1a_enable.space_id = - acpi_gbl_FADT.xpm1a_event_block.space_id; - - /* The PM1B register block is optional, ignore if not present */ - - if (acpi_gbl_FADT.xpm1b_event_block.address) { - if (acpi_gbl_FADT.xpm1b_event_block.bit_width - != acpi_gbl_FADT.pm1_event_length * 8) - printk(KERN_WARNING "FADT: " - "X_PM1b_EVT_BLK.bit_width (%u) does not match" - " PM1_EVT_LEN (%u)\n", - acpi_gbl_FADT.xpm1b_event_block.bit_width, - acpi_gbl_FADT.pm1_event_length); - acpi_tb_init_generic_address(&acpi_gbl_xpm1b_enable, - acpi_gbl_FADT.xpm1b_event_block.space_id, - pm1_register_byte_width, - (acpi_gbl_FADT.xpm1b_event_block. - address + pm1_register_byte_width)); - /* Don't forget to copy space_id of the GAS */ - acpi_gbl_xpm1b_enable.space_id = - acpi_gbl_FADT.xpm1b_event_block.space_id; - - } } /****************************************************************************** @@ -607,3 +536,94 @@ static void acpi_tb_validate_fadt(void) } } } + +/****************************************************************************** + * + * FUNCTION: acpi_tb_setup_fadt_registers + * + * PARAMETERS: None, uses acpi_gbl_FADT. + * + * RETURN: None + * + * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally, + * force FADT register definitions to their default lengths. + * + ******************************************************************************/ + +static void acpi_tb_setup_fadt_registers(void) +{ + struct acpi_generic_address *target64; + struct acpi_generic_address *source64; + u8 pm1_register_byte_width; + u32 i; + + /* + * Optionally check all register lengths against the default values and + * update them if they are incorrect. + */ + if (acpi_gbl_use_default_register_widths) { + for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { + target64 = + ACPI_ADD_PTR(struct acpi_generic_address, + &acpi_gbl_FADT, + fadt_info_table[i].address64); + + /* + * If a valid register (Address != 0) and the (default_length > 0) + * (Not a GPE register), then check the width against the default. + */ + if ((target64->address) && + (fadt_info_table[i].default_length > 0) && + (fadt_info_table[i].default_length != + target64->bit_width)) { + ACPI_WARNING((AE_INFO, + "Invalid length for %s: %d, using default %d", + fadt_info_table[i].name, + target64->bit_width, + fadt_info_table[i]. + default_length)); + + /* Incorrect size, set width to the default */ + + target64->bit_width = + fadt_info_table[i].default_length; + } + } + } + + /* + * Get the length of the individual PM1 registers (enable and status). + * Each register is defined to be (event block length / 2). Extra divide + * by 8 converts bits to bytes. + */ + pm1_register_byte_width = + (u8)ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width); + + /* + * Calculate separate GAS structs for the PM1x (A/B) Status and Enable + * registers. These addresses do not appear (directly) in the FADT, so it + * is useful to pre-calculate them from the PM1 Event Block definitions. + * + * The PM event blocks are split into two register blocks, first is the + * PM Status Register block, followed immediately by the PM Enable + * Register block. Each is of length (pm1_event_length/2) + * + * Note: The PM1A event block is required by the ACPI specification. + * However, the PM1B event block is optional and is rarely, if ever, + * used. + */ + + for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) { + source64 = + ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, + fadt_pm_info_table[i].source); + + acpi_tb_init_generic_address(fadt_pm_info_table[i].target, + source64->space_id, + pm1_register_byte_width, + source64->address + + (fadt_pm_info_table[i]. + register_num * + pm1_register_byte_width)); + } +} From 5e053e77f233342b56fda419d347fd2c958b9849 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Wed, 4 Mar 2009 14:31:25 +0800 Subject: [PATCH 020/140] ACPICA: Check for non-zero address before being converted to GAS Reported-by: FreeBSD community Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index a8191efd9aa6..43fe886b41a2 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -618,12 +618,14 @@ static void acpi_tb_setup_fadt_registers(void) ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, fadt_pm_info_table[i].source); - acpi_tb_init_generic_address(fadt_pm_info_table[i].target, - source64->space_id, - pm1_register_byte_width, - source64->address + - (fadt_pm_info_table[i]. - register_num * - pm1_register_byte_width)); + if (source64->address) { + acpi_tb_init_generic_address(fadt_pm_info_table[i]. + target, source64->space_id, + pm1_register_byte_width, + source64->address + + (fadt_pm_info_table[i]. + register_num * + pm1_register_byte_width)); + } } } From d3319d1717a250e92be66a487dc3e0429112c284 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:07:58 +0800 Subject: [PATCH 021/140] ACPICA: Update comments in module header Enhance the explanations of the various package return types for clarity. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acpredef.h | 41 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index 16a9ca9a66e4..63f656ae3604 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -52,41 +52,44 @@ * 1) PTYPE1 packages do not contain sub-packages. * * ACPI_PTYPE1_FIXED: Fixed length, 1 or 2 object types: - * object type - * count - * object type - * count + * object type + * count + * object type + * count * * ACPI_PTYPE1_VAR: Variable length: - * object type (Int/Buf/Ref) + * object type (Int/Buf/Ref) * - * ACPI_PTYPE1_OPTION: Package has some required and some optional elements: - * Used for _PRW + * ACPI_PTYPE1_OPTION: Package has some required and some optional elements + * (Used for _PRW) * * * 2) PTYPE2 packages contain a variable number of sub-packages. Each of the * different types describe the contents of each of the sub-packages. * * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: - * object type - * count - * object type - * count + * object type + * count + * object type + * count + * (Used for _ALR,_MLS,_PSS,_TRT,_TSS) * * ACPI_PTYPE2_COUNT: Each subpackage has a count as first element: - * object type + * object type + * (Used for _CSD,_PSD,_TSD) * * ACPI_PTYPE2_PKG_COUNT: Count of subpackages at start, 1 or 2 object types: - * object type - * count - * object type - * count + * object type + * count + * object type + * count + * (Used for _CST) * - * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length: - * Used for _PRT + * ACPI_PTYPE2_FIXED: Each subpackage is of fixed length + * (Used for _PRT) * * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length - * Used for _HPX + * (Used for _HPX) * *****************************************************************************/ From c520abadbc56a2740021910d2c6412f826a10059 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:20:12 +0800 Subject: [PATCH 022/140] ACPICA: Fix writes to optional PM1B registers On read, shift B register bits above the A bits. On write, shift B bits down to zero before writing the B register. New: acpi_hw_read_multiple, acpi_hw_write_multiple. These two functions now transparently handle the (possible) split registers for PM1 Status, Enable, and Control. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwregs.c | 205 ++++++++++++++++++++++++----------- 1 file changed, 140 insertions(+), 65 deletions(-) diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 7ef0b8eadbc7..41f1173e02c2 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -51,6 +51,17 @@ #define _COMPONENT ACPI_HARDWARE ACPI_MODULE_NAME("hwregs") +/* Local Prototypes */ +static acpi_status +acpi_hw_read_multiple(u32 *value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b); + +static acpi_status +acpi_hw_write_multiple(u32 value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b); + /******************************************************************************* * * FUNCTION: acpi_hw_clear_acpi_status @@ -63,6 +74,7 @@ ACPI_MODULE_NAME("hwregs") * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ + acpi_status acpi_hw_clear_acpi_status(void) { acpi_status status; @@ -143,64 +155,49 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) acpi_status acpi_hw_register_read(u32 register_id, u32 * return_value) { - u32 value1 = 0; - u32 value2 = 0; + u32 value = 0; acpi_status status; ACPI_FUNCTION_TRACE(hw_register_read); switch (register_id) { - case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ + case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ - status = acpi_read(&value1, &acpi_gbl_xpm1a_status); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_read(&value2, &acpi_gbl_xpm1b_status); - value1 |= value2; + status = acpi_hw_read_multiple(&value, + &acpi_gbl_xpm1a_status, + &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ - status = acpi_read(&value1, &acpi_gbl_xpm1a_enable); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_read(&value2, &acpi_gbl_xpm1b_enable); - value1 |= value2; + status = acpi_hw_read_multiple(&value, + &acpi_gbl_xpm1a_enable, + &acpi_gbl_xpm1b_enable); break; - case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ + case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm1a_control_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - status = acpi_read(&value2, &acpi_gbl_FADT.xpm1b_control_block); - value1 |= value2; + status = acpi_hw_read_multiple(&value, + &acpi_gbl_FADT. + xpm1a_control_block, + &acpi_gbl_FADT. + xpm1b_control_block); break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm2_control_block); + status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_read(&value1, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ status = - acpi_os_read_port(acpi_gbl_FADT.smi_command, &value1, 8); + acpi_os_read_port(acpi_gbl_FADT.smi_command, &value, 8); break; default: @@ -209,10 +206,8 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) break; } - exit: - if (ACPI_SUCCESS(status)) { - *return_value = value1; + *return_value = value; } return_ACPI_STATUS(status); @@ -252,12 +247,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) ACPI_FUNCTION_TRACE(hw_register_write); switch (register_id) { - case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ + case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ /* Perform a read first to preserve certain bits (per ACPI spec) */ - status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, - &read_value); + status = acpi_hw_read_multiple(&read_value, + &acpi_gbl_xpm1a_status, + &acpi_gbl_xpm1b_status); if (ACPI_FAILURE(status)) { goto exit; } @@ -269,35 +265,29 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) /* Now we can write the data */ - status = acpi_write(value, &acpi_gbl_xpm1a_status); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_write(value, &acpi_gbl_xpm1b_status); + status = acpi_hw_write_multiple(value, + &acpi_gbl_xpm1a_status, + &acpi_gbl_xpm1b_status); break; - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ + case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access */ - status = acpi_write(value, &acpi_gbl_xpm1a_enable); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* PM1B is optional */ - - status = acpi_write(value, &acpi_gbl_xpm1b_enable); + status = acpi_hw_write_multiple(value, + &acpi_gbl_xpm1a_enable, + &acpi_gbl_xpm1b_enable); break; - case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ + case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ /* * Perform a read first to preserve certain bits (per ACPI spec) + * Note: This includes SCI_EN, we never want to change this bit */ - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, - &read_value); + status = acpi_hw_read_multiple(&read_value, + &acpi_gbl_FADT. + xpm1a_control_block, + &acpi_gbl_FADT. + xpm1b_control_block); if (ACPI_FAILURE(status)) { goto exit; } @@ -309,12 +299,11 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) /* Now we can write the data */ - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); - if (ACPI_FAILURE(status)) { - goto exit; - } - - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); + status = acpi_hw_write_multiple(value, + &acpi_gbl_FADT. + xpm1a_control_block, + &acpi_gbl_FADT. + xpm1b_control_block); break; case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ @@ -346,6 +335,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) break; default: + ACPI_ERROR((AE_INFO, "Unknown Register ID: %X", register_id)); status = AE_BAD_PARAMETER; break; } @@ -353,3 +343,88 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) exit: return_ACPI_STATUS(status); } + +/****************************************************************************** + * + * FUNCTION: acpi_hw_read_multiple + * + * PARAMETERS: Value - Where the register value is returned + * register_a - First ACPI register (required) + * register_b - Second ACPI register (optional) + * + * RETURN: Status + * + * DESCRIPTION: Read from the specified two-part ACPI register (such as PM1 A/B) + * + ******************************************************************************/ + +static acpi_status +acpi_hw_read_multiple(u32 *value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b) +{ + u32 value_a = 0; + u32 value_b = 0; + acpi_status status; + + /* The first register is always required */ + + status = acpi_read(&value_a, register_a); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Second register is optional */ + + if (register_b->address) { + status = acpi_read(&value_b, register_b); + if (ACPI_FAILURE(status)) { + return (status); + } + } + + /* Shift the B bits above the A bits */ + + *value = value_a | (value_b << register_a->bit_width); + return (AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_write_multiple + * + * PARAMETERS: Value - The value to write + * register_a - First ACPI register (required) + * register_b - Second ACPI register (optional) + * + * RETURN: Status + * + * DESCRIPTION: Write to the specified two-part ACPI register (such as PM1 A/B) + * + ******************************************************************************/ + +static acpi_status +acpi_hw_write_multiple(u32 value, + struct acpi_generic_address *register_a, + struct acpi_generic_address *register_b) +{ + acpi_status status; + + /* The first register is always required */ + + status = acpi_write(value, register_a); + if (ACPI_FAILURE(status)) { + return (status); + } + + /* Second register is optional */ + + if (register_b->address) { + + /* Normalize the B bits before write */ + + status = acpi_write(value >> register_a->bit_width, register_b); + } + + return (status); +} From 227243a04d645377d09eda0dc8501e0d9c26ab89 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:24:50 +0800 Subject: [PATCH 023/140] ACPICA: Remove extra write for acpi_hw_clear_acpi_status This function was writing an optional PM1B status register twice. The existing call to the low-level acpi_hw_register_write automatically handles a possibly split PM1 A/B register. ACPICA BZ 751. http://www.acpica.org/bugzilla/show_bug.cgi?id=751 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwregs.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 41f1173e02c2..9c8162128c2b 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -71,7 +71,6 @@ acpi_hw_write_multiple(u32 value, * RETURN: Status * * DESCRIPTION: Clears all fixed and general purpose status bits - * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED * ******************************************************************************/ @@ -82,13 +81,13 @@ acpi_status acpi_hw_clear_acpi_status(void) ACPI_FUNCTION_TRACE(hw_clear_acpi_status); - ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n", + ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %0llX\n", ACPI_BITMASK_ALL_FIXED_STATUS, - (u16) acpi_gbl_xpm1a_status.address)); + acpi_gbl_xpm1a_status.address)); lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - /* Clear the fixed events */ + /* Clear the fixed events in PM1 A/B */ status = acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, ACPI_BITMASK_ALL_FIXED_STATUS); @@ -96,16 +95,6 @@ acpi_status acpi_hw_clear_acpi_status(void) goto unlock_and_exit; } - /* Write PM1B register if present */ - - if (acpi_gbl_xpm1b_status.address) { - status = acpi_write(ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_xpm1b_status); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - } - /* Clear the GPE Bits in all GPE registers in all GPE blocks */ status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block, NULL); From aefc7f9a0220a40beff9b6b3b320cbeae128d0e3 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:26:02 +0800 Subject: [PATCH 024/140] ACPICA: For PM1B registers, do not shift value read or written The PM1B registers are mirrors of the PM1A registers with different bits actually implemented. From the ACPI specification: "Although the bits can be split between the two register blocks (each register block has a unique pointer within the FADT), the bit positions are maintained. The register block with unimplemented bits (that is, those implemented in the other register block) always returns zeros, and writes have no side effects" Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwregs.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 9c8162128c2b..5a64e577975f 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -372,9 +372,17 @@ acpi_hw_read_multiple(u32 *value, } } - /* Shift the B bits above the A bits */ - - *value = value_a | (value_b << register_a->bit_width); + /* + * OR the two return values together. No shifting or masking is necessary, + * because of how the PM1 registers are defined in the ACPI specification: + * + * "Although the bits can be split between the two register blocks (each + * register block has a unique pointer within the FADT), the bit positions + * are maintained. The register block with unimplemented bits (that is, + * those implemented in the other register block) always returns zeros, + * and writes have no side effects" + */ + *value = (value_a | value_b); return (AE_OK); } @@ -406,13 +414,20 @@ acpi_hw_write_multiple(u32 value, return (status); } - /* Second register is optional */ - + /* + * Second register is optional + * + * No bit shifting or clearing is necessary, because of how the PM1 + * registers are defined in the ACPI specification: + * + * "Although the bits can be split between the two register blocks (each + * register block has a unique pointer within the FADT), the bit positions + * are maintained. The register block with unimplemented bits (that is, + * those implemented in the other register block) always returns zeros, + * and writes have no side effects" + */ if (register_b->address) { - - /* Normalize the B bits before write */ - - status = acpi_write(value >> register_a->bit_width, register_b); + status = acpi_write(value, register_b); } return (status); From ac0c84502697114a378057eed83a9baba879cfc9 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:28:02 +0800 Subject: [PATCH 025/140] ACPICA: Fix parameter validation for acpi_read/write Now return AE_BAD_PARAMETER if the input register pointer is null, and AE_BAD_ADDRESS if the register has an address of zero. Previously, these cases simply returned AE_OK. For optional registers such as PM1B status/enable/control, the caller should check for a valid register address before calling. ACPICA BZ 748. http://www.acpica.org/bugzilla/show_bug.cgi?id=748 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwxface.c | 18 ++++++++---------- include/acpi/acexcep.h | 6 ++++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index ae597c0ab53f..f67562ea0010 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -107,19 +107,18 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) ACPI_FUNCTION_NAME(acpi_read); /* - * Must have a valid pointer to a GAS structure, and - * a non-zero address within. However, don't return an error - * because the PM1A/B code must not fail if B isn't present. + * Must have a valid pointer to a GAS structure, and a non-zero address + * within. */ if (!reg) { - return (AE_OK); + return (AE_BAD_PARAMETER); } /* Get a local copy of the address. Handles possible alignment issues */ ACPI_MOVE_64_TO_64(&address, ®->address); if (!address) { - return (AE_OK); + return (AE_BAD_ADDRESS); } /* Supported widths are 8/16/32 */ @@ -187,19 +186,18 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) ACPI_FUNCTION_NAME(acpi_write); /* - * Must have a valid pointer to a GAS structure, and - * a non-zero address within. However, don't return an error - * because the PM1A/B code must not fail if B isn't present. + * Must have a valid pointer to a GAS structure, and a non-zero address + * within. */ if (!reg) { - return (AE_OK); + return (AE_BAD_PARAMETER); } /* Get a local copy of the address. Handles possible alignment issues */ ACPI_MOVE_64_TO_64(&address, ®->address); if (!address) { - return (AE_OK); + return (AE_BAD_ADDRESS); } /* Supported widths are 8/16/32 */ diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index eda04546cdf6..473d584b1d31 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -103,8 +103,9 @@ #define AE_BAD_OCTAL_CONSTANT (acpi_status) (0x0006 | AE_CODE_PROGRAMMER) #define AE_BAD_DECIMAL_CONSTANT (acpi_status) (0x0007 | AE_CODE_PROGRAMMER) #define AE_MISSING_ARGUMENTS (acpi_status) (0x0008 | AE_CODE_PROGRAMMER) +#define AE_BAD_ADDRESS (acpi_status) (0x0009 | AE_CODE_PROGRAMMER) -#define AE_CODE_PGM_MAX 0x0008 +#define AE_CODE_PGM_MAX 0x0009 /* * Acpi table exceptions @@ -224,7 +225,8 @@ char const *acpi_gbl_exception_names_pgm[] = { "AE_BAD_HEX_CONSTANT", "AE_BAD_OCTAL_CONSTANT", "AE_BAD_DECIMAL_CONSTANT", - "AE_MISSING_ARGUMENTS" + "AE_MISSING_ARGUMENTS", + "AE_BAD_ADDRESS" }; char const *acpi_gbl_exception_names_tbl[] = { From 82d79b86646504a0ab97fe50ac137df65f651a27 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:31:05 +0800 Subject: [PATCH 026/140] ACPICA: Remove redundant ACPI_BITREG_SLEEP_TYPE_B This type is the same as TYPE_A. Removed this and all related instances. Renamed SLEEP_TYPE_A to simply SLEEP_TYPE. ACPICA BZ 754. http://www.acpica.org/bugzilla/show_bug.cgi?id=754 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/aclocal.h | 4 ++-- drivers/acpi/acpica/hwsleep.c | 4 ++-- drivers/acpi/acpica/utglobal.c | 9 +++------ include/acpi/actypes.h | 9 ++++----- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 492d02761bb7..b9a0aa67ab10 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -818,7 +818,7 @@ struct acpi_bit_register_info { #define ACPI_BITMASK_SCI_ENABLE 0x0001 #define ACPI_BITMASK_BUS_MASTER_RLD 0x0002 #define ACPI_BITMASK_GLOBAL_LOCK_RELEASE 0x0004 -#define ACPI_BITMASK_SLEEP_TYPE_X 0x1C00 +#define ACPI_BITMASK_SLEEP_TYPE 0x1C00 #define ACPI_BITMASK_SLEEP_ENABLE 0x2000 #define ACPI_BITMASK_ARB_DISABLE 0x0001 @@ -844,7 +844,7 @@ struct acpi_bit_register_info { #define ACPI_BITPOSITION_SCI_ENABLE 0x00 #define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01 #define ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE 0x02 -#define ACPI_BITPOSITION_SLEEP_TYPE_X 0x0A +#define ACPI_BITPOSITION_SLEEP_TYPE 0x0A #define ACPI_BITPOSITION_SLEEP_ENABLE 0x0D #define ACPI_BITPOSITION_ARB_DISABLE 0x00 diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index a2af2a4f2f26..1a7d260f7826 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -242,7 +242,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) } sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); @@ -486,7 +486,7 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) &acpi_gbl_sleep_type_b); if (ACPI_SUCCESS(status)) { sleep_type_reg_info = - acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A); + acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE); sleep_enable_reg_info = acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE); diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index a3ab9d9da299..bec0e21673cb 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -294,12 +294,9 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG] = { /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE}, - /* ACPI_BITREG_SLEEP_TYPE_A */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_TYPE_X, - ACPI_BITMASK_SLEEP_TYPE_X}, - /* ACPI_BITREG_SLEEP_TYPE_B */ {ACPI_REGISTER_PM1_CONTROL, - ACPI_BITPOSITION_SLEEP_TYPE_X, - ACPI_BITMASK_SLEEP_TYPE_X}, + /* ACPI_BITREG_SLEEP_TYPE */ {ACPI_REGISTER_PM1_CONTROL, + ACPI_BITPOSITION_SLEEP_TYPE, + ACPI_BITMASK_SLEEP_TYPE}, /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE}, diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index a20aab510173..1b9601c665e6 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -777,15 +777,14 @@ typedef u8 acpi_adr_space_type; #define ACPI_BITREG_SCI_ENABLE 0x0E #define ACPI_BITREG_BUS_MASTER_RLD 0x0F #define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x10 -#define ACPI_BITREG_SLEEP_TYPE_A 0x11 -#define ACPI_BITREG_SLEEP_TYPE_B 0x12 -#define ACPI_BITREG_SLEEP_ENABLE 0x13 +#define ACPI_BITREG_SLEEP_TYPE 0x11 +#define ACPI_BITREG_SLEEP_ENABLE 0x12 /* PM2 Control register */ -#define ACPI_BITREG_ARB_DISABLE 0x14 +#define ACPI_BITREG_ARB_DISABLE 0x13 -#define ACPI_BITREG_MAX 0x14 +#define ACPI_BITREG_MAX 0x13 #define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 /* From 32c9ef994d91352b710b948ec369cd18d6bca51b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:36:05 +0800 Subject: [PATCH 027/140] ACPICA: Add function to handle PM1 control registers Added acpi_hw_write_pm1_control. This function writes both of the PM1 control registers (A/B). These registers are different than than the PM1 A/B status and enable registers in that different values can be written to the A/B registers. Most notably, the SLP_TYP bits can be different, as per the values returned from the _Sx predefined methods. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/achware.h | 5 ++- drivers/acpi/acpica/aclocal.h | 10 ++--- drivers/acpi/acpica/hwregs.c | 46 ++++++++++++++----- drivers/acpi/acpica/hwsleep.c | 84 +++++++++++++++-------------------- 4 files changed, 78 insertions(+), 67 deletions(-) diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 58c69dc49ab4..4fa6ee6b1f7c 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -64,8 +64,9 @@ u32 acpi_hw_get_mode(void); */ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); -acpi_status -acpi_hw_register_read(u32 register_id, u32 * return_value); +acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); + +acpi_status acpi_hw_register_read(u32 register_id, u32 *return_value); acpi_status acpi_hw_register_write(u32 register_id, u32 value); diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index b9a0aa67ab10..6feebc8f789a 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -781,12 +781,10 @@ struct acpi_bit_register_info { #define ACPI_REGISTER_PM1_STATUS 0x01 #define ACPI_REGISTER_PM1_ENABLE 0x02 #define ACPI_REGISTER_PM1_CONTROL 0x03 -#define ACPI_REGISTER_PM1A_CONTROL 0x04 -#define ACPI_REGISTER_PM1B_CONTROL 0x05 -#define ACPI_REGISTER_PM2_CONTROL 0x06 -#define ACPI_REGISTER_PM_TIMER 0x07 -#define ACPI_REGISTER_PROCESSOR_BLOCK 0x08 -#define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x09 +#define ACPI_REGISTER_PM2_CONTROL 0x04 +#define ACPI_REGISTER_PM_TIMER 0x05 +#define ACPI_REGISTER_PROCESSOR_BLOCK 0x06 +#define ACPI_REGISTER_SMI_COMMAND_BLOCK 0x07 /* Masks used to access the bit_registers */ diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 5a64e577975f..edc627c9fc0d 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -129,6 +129,42 @@ struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id) return (&acpi_gbl_bit_register_info[register_id]); } +/****************************************************************************** + * + * FUNCTION: acpi_hw_write_pm1_control + * + * PARAMETERS: pm1a_control - Value to be written to PM1A control + * pm1b_control - Value to be written to PM1B control + * + * RETURN: Status + * + * DESCRIPTION: Write the PM1 A/B control registers. These registers are + * different than than the PM1 A/B status and enable registers + * in that different values can be written to the A/B registers. + * Most notably, the SLP_TYP bits can be different, as per the + * values returned from the _Sx predefined methods. + * + ******************************************************************************/ + +acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) +{ + acpi_status status; + + ACPI_FUNCTION_TRACE(hw_write_pm1_control); + + status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (acpi_gbl_FADT.xpm1b_control_block.address) { + status = + acpi_write(pm1b_control, + &acpi_gbl_FADT.xpm1b_control_block); + } + return_ACPI_STATUS(status); +} + /****************************************************************************** * * FUNCTION: acpi_hw_register_read @@ -295,16 +331,6 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) xpm1b_control_block); break; - case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1a_control_block); - break; - - case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ - - status = acpi_write(value, &acpi_gbl_FADT.xpm1b_control_block); - break; - case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 1a7d260f7826..51868f48159c 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -147,9 +147,8 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state) ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep); - /* - * _PSW methods could be run here to enable wake-on keyboard, LAN, etc. - */ + /* _PSW methods could be run here to enable wake-on keyboard, LAN, etc. */ + status = acpi_get_sleep_type_data(sleep_state, &acpi_gbl_sleep_type_a, &acpi_gbl_sleep_type_b); @@ -223,8 +222,8 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep) ******************************************************************************/ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) { - u32 PM1Acontrol; - u32 PM1Bcontrol; + u32 pm1a_control; + u32 pm1b_control; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; u32 in_value; @@ -289,24 +288,25 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Get current value of PM1A control */ - status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol); + status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, + &pm1a_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Entering sleep state [S%d]\n", sleep_state)); - /* Clear SLP_EN and SLP_TYP fields */ + /* Clear the SLP_EN and SLP_TYP fields */ - PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | - sleep_enable_reg_info->access_bit_mask); - PM1Bcontrol = PM1Acontrol; + pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info->access_bit_mask); + pm1b_control = pm1a_control; - /* Insert SLP_TYP bits */ + /* Insert the SLP_TYP bits */ - PM1Acontrol |= + pm1a_control |= (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position); - PM1Bcontrol |= + pm1b_control |= (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position); /* @@ -314,37 +314,25 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) * poorly implemented hardware. */ - /* Write #1: fill in SLP_TYP data */ + /* Write #1: write the SLP_TYP data to the PM1 Control registers */ - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); + status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Insert the sleep enable (SLP_EN) bit */ - /* Insert SLP_ENABLE bit */ + pm1a_control |= sleep_enable_reg_info->access_bit_mask; + pm1b_control |= sleep_enable_reg_info->access_bit_mask; - PM1Acontrol |= sleep_enable_reg_info->access_bit_mask; - PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask; - - /* Write #2: SLP_TYP + SLP_EN */ + /* Flush caches, as per ACPI specification */ ACPI_FLUSH_CPU_CACHE(); - status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } + /* Write #2: Write both SLP_TYP + SLP_EN */ - status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); + status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -471,8 +459,8 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) acpi_status status; struct acpi_bit_register_info *sleep_type_reg_info; struct acpi_bit_register_info *sleep_enable_reg_info; - u32 PM1Acontrol; - u32 PM1Bcontrol; + u32 pm1a_control; + u32 pm1b_control; ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep); @@ -493,31 +481,29 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) /* Get current value of PM1A control */ status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, - &PM1Acontrol); + &pm1a_control); if (ACPI_SUCCESS(status)) { - /* Clear SLP_EN and SLP_TYP fields */ + /* Clear the SLP_EN and SLP_TYP fields */ - PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask | - sleep_enable_reg_info-> - access_bit_mask); - PM1Bcontrol = PM1Acontrol; + pm1a_control &= ~(sleep_type_reg_info->access_bit_mask | + sleep_enable_reg_info-> + access_bit_mask); + pm1b_control = pm1a_control; - /* Insert SLP_TYP bits */ + /* Insert the SLP_TYP bits */ - PM1Acontrol |= + pm1a_control |= (acpi_gbl_sleep_type_a << sleep_type_reg_info-> bit_position); - PM1Bcontrol |= + pm1b_control |= (acpi_gbl_sleep_type_b << sleep_type_reg_info-> bit_position); - /* Just ignore any errors */ + /* Write the control registers and ignore any errors */ - (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL, - PM1Acontrol); - (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL, - PM1Bcontrol); + (void)acpi_hw_write_pm1_control(pm1a_control, + pm1b_control); } } From 3371c19c294a4cb3649aa4e84606be8a1d999e61 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:44:03 +0800 Subject: [PATCH 028/140] ACPICA: Remove ACPI_GET_OBJECT_TYPE macro Remove all instances of this obsolete macro, since it is now a simple reference to ->common.type. There were about 150 invocations of the macro across 41 files. ACPICA BZ 755. http://www.acpica.org/bugzilla/show_bug.cgi?id=755 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acmacros.h | 4 ---- drivers/acpi/acpica/dsmthdat.c | 2 +- drivers/acpi/acpica/dsobject.c | 6 +++--- drivers/acpi/acpica/dsopcode.c | 8 +++----- drivers/acpi/acpica/dsutils.c | 2 +- drivers/acpi/acpica/dswexec.c | 5 ++--- drivers/acpi/acpica/evgpeblk.c | 8 ++++---- drivers/acpi/acpica/evregion.c | 2 +- drivers/acpi/acpica/exconfig.c | 4 ++-- drivers/acpi/acpica/exconvrt.c | 11 +++++------ drivers/acpi/acpica/exdump.c | 19 ++++++++----------- drivers/acpi/acpica/exfield.c | 29 +++++++++++++---------------- drivers/acpi/acpica/exfldio.c | 8 ++++---- drivers/acpi/acpica/exmisc.c | 14 +++++++------- drivers/acpi/acpica/exoparg1.c | 13 +++++-------- drivers/acpi/acpica/exoparg2.c | 2 +- drivers/acpi/acpica/exoparg3.c | 7 +++---- drivers/acpi/acpica/exprep.c | 2 +- drivers/acpi/acpica/exresnte.c | 8 ++++---- drivers/acpi/acpica/exresolv.c | 9 ++++----- drivers/acpi/acpica/exresop.c | 23 +++++++++++------------ drivers/acpi/acpica/exstore.c | 18 ++++++++---------- drivers/acpi/acpica/exstoren.c | 29 ++++++++++++----------------- drivers/acpi/acpica/exutils.c | 2 +- drivers/acpi/acpica/hwxface.c | 6 +++--- drivers/acpi/acpica/nsaccess.c | 3 +-- drivers/acpi/acpica/nsdump.c | 2 +- drivers/acpi/acpica/nsobject.c | 18 ++++++++---------- drivers/acpi/acpica/nspredef.c | 8 ++++---- drivers/acpi/acpica/nsxfeval.c | 3 +-- drivers/acpi/acpica/rscalc.c | 7 +++---- drivers/acpi/acpica/rscreate.c | 15 +++++++-------- drivers/acpi/acpica/utcopy.c | 25 ++++++++++++------------- drivers/acpi/acpica/utdelete.c | 6 +++--- drivers/acpi/acpica/uteval.c | 12 ++++++------ drivers/acpi/acpica/utglobal.c | 2 +- drivers/acpi/acpica/utmisc.c | 3 +-- drivers/acpi/acpica/utobject.c | 7 +++---- 38 files changed, 158 insertions(+), 194 deletions(-) diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 9c127e8e2d6d..91ac7d7b4402 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -292,10 +292,6 @@ #define ACPI_GET_DESCRIPTOR_TYPE(d) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type) #define ACPI_SET_DESCRIPTOR_TYPE(d, t) (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t) -/* Macro to test the object type */ - -#define ACPI_GET_OBJECT_TYPE(d) (((union acpi_operand_object *)(void *)(d))->common.type) - /* * Macros for the master AML opcode table */ diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index da0f5468184c..22b1a3ce2c94 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -713,6 +713,6 @@ acpi_ds_method_data_get_type(u16 opcode, /* Get the object type */ - return_VALUE(ACPI_GET_OBJECT_TYPE(object)); + return_VALUE(object->type); } #endif diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 15c628e6aa00..dab3f48f0b42 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -565,7 +565,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, /* Re-type the object according to its argument */ - node->type = ACPI_GET_OBJECT_TYPE(obj_desc); + node->type = obj_desc->common.type; /* Attach obj to node */ @@ -619,7 +619,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, /* Perform per-object initialization */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: /* @@ -803,7 +803,7 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, default: ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", - ACPI_GET_OBJECT_TYPE(obj_desc))); + obj_desc->common.type)); status = AE_AML_OPERAND_TYPE; break; diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 0c3b4dd60e8a..602ddaa10c29 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -484,7 +484,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Host object must be a Buffer */ - if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { + if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "Target of Create Field is not a Buffer object - %s", acpi_ut_get_object_type_name(buffer_desc))); @@ -1365,10 +1365,8 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) - && - (ACPI_GET_OBJECT_TYPE - (walk_state->results->results.obj_desc[0]) == - ACPI_TYPE_LOCAL_REFERENCE) + && ((walk_state->results->results.obj_desc[0])-> + common.type == ACPI_TYPE_LOCAL_REFERENCE) && ((walk_state->results->results.obj_desc[0])-> reference.class != ACPI_REFCLASS_INDEX)) { status = diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index dabc23a46176..dfa104102926 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -816,7 +816,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) goto push_result; } - type = ACPI_GET_OBJECT_TYPE(*operand); + type = (*operand)->common.type; status = acpi_ex_resolve_to_value(operand, walk_state); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 350e6656bc89..f0280856dc0e 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -138,11 +138,10 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, goto cleanup; } - if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { + if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", - obj_desc, walk_state, - ACPI_GET_OBJECT_TYPE(obj_desc))); + obj_desc, walk_state, obj_desc->common.type)); status = AE_AML_OPERAND_TYPE; goto cleanup; diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 484cc0565d5b..f7b3d2af9401 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -408,7 +408,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, */ obj_desc = pkg_desc->package.elements[0]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Use FADT-defined GPE device (from definition of _PRW) */ @@ -417,14 +417,14 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, /* Integer is the GPE number in the FADT described GPE blocks */ gpe_number = (u32) obj_desc->integer.value; - } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + } else if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { /* Package contains a GPE reference and GPE number within a GPE block */ if ((obj_desc->package.count < 2) || - (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) != + ((obj_desc->package.elements[0])->common.type != ACPI_TYPE_LOCAL_REFERENCE) - || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) != + || ((obj_desc->package.elements[1])->common.type != ACPI_TYPE_INTEGER)) { goto cleanup; } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 665c0887ab4d..86cbbdbfc5cd 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -691,7 +691,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, /* Devices are handled different than regions */ - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { + if (obj_desc->common.type == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 932bbc26aa04..70b39c7daeab 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -291,7 +291,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, /* Source Object can be either an op_region or a Buffer/Field */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_REGION: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -501,7 +501,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) */ if ((!ddb_handle) || (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) || - (ACPI_GET_OBJECT_TYPE(ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) { + (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 0be10188316e..37d0d39e60a6 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -82,7 +82,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: /* No conversion necessary */ @@ -116,7 +116,7 @@ acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, /* String conversion is different than Buffer conversion */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_STRING: /* @@ -206,7 +206,7 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: /* No conversion necessary */ @@ -409,7 +409,7 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_STRING: /* No conversion necessary */ @@ -605,8 +605,7 @@ acpi_ex_convert_to_target_type(acpi_object_type destination_type, default: /* No conversion allowed for these types */ - if (destination_type != - ACPI_GET_OBJECT_TYPE(source_desc)) { + if (destination_type != source_desc->common.type) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Explicit operator, will store (%s) over existing type (%s)\n", acpi_ut_get_object_type_name diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index aa313574b0df..193d23312e18 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -492,7 +492,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) /* Decode object type */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: acpi_os_printf("Reference: [%s] ", @@ -531,7 +531,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("%X", obj_desc->reference.value); - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Value is an Integer */ @@ -548,7 +548,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) acpi_os_printf("%X", obj_desc->reference.value); - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Value is an Integer */ @@ -686,9 +686,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) if (!obj_desc->buffer_field.buffer_obj) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n")); - } else - if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj) - != ACPI_TYPE_BUFFER) { + } else if ((obj_desc->buffer_field.buffer_obj)->common.type != + ACPI_TYPE_BUFFER) { acpi_os_printf("*not a Buffer*\n"); } else { acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj, @@ -737,8 +736,7 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) default: /* Unknown Type */ - acpi_os_printf("Unknown Type %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc)); + acpi_os_printf("Unknown Type %X\n", obj_desc->common.type); break; } @@ -939,7 +937,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, /* Packages may only contain a few object types */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: acpi_os_printf("[Integer] = %8.8X%8.8X\n", @@ -990,8 +988,7 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, default: - acpi_os_printf("[Unknown Type] %X\n", - ACPI_GET_OBJECT_TYPE(obj_desc)); + acpi_os_printf("[Unknown Type] %X\n", obj_desc->common.type); break; } } diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index a352d0233857..546dcdd86785 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -84,7 +84,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_BAD_PARAMETER); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. @@ -95,9 +95,8 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } } - } else - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) - && (obj_desc->field.region_obj->region.space_id == + } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { /* * This is an SMBus read. We must create a buffer to hold the data @@ -163,7 +162,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", - obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer, + obj_desc, obj_desc->common.type, buffer, (u32) length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n", @@ -222,7 +221,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(AE_AML_NO_OPERAND); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. @@ -233,9 +232,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } } - } else - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) - && (obj_desc->field.region_obj->region.space_id == + } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) { /* * This is an SMBus write. We will bypass the entire field mechanism @@ -243,7 +241,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, * * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). */ - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { + if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "SMBus write requires Buffer, found type %s", acpi_ut_get_object_type_name(source_desc))); @@ -291,7 +289,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* Get a pointer to the data to be written */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); @@ -314,15 +312,14 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE - (source_desc)), - ACPI_GET_OBJECT_TYPE(source_desc), buffer, length)); + acpi_ut_get_type_name(source_desc->common.type), + source_desc->common.type, buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)), - ACPI_GET_OBJECT_TYPE(obj_desc), + acpi_ut_get_type_name(obj_desc->common.type), + obj_desc->common.type, obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index ef58ac4e687b..1053e7cd92a1 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -94,9 +94,9 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, /* We must have a valid region */ - if (ACPI_GET_OBJECT_TYPE(rgn_desc) != ACPI_TYPE_REGION) { + if (rgn_desc->common.type != ACPI_TYPE_REGION) { ACPI_ERROR((AE_INFO, "Needed Region, found type %X (%s)", - ACPI_GET_OBJECT_TYPE(rgn_desc), + rgn_desc->common.type, acpi_ut_get_object_type_name(rgn_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -390,7 +390,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, * index_field - Write to an Index Register, then read/write from/to a * Data Register */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER_FIELD: /* * If the buffer_field arguments have not been previously evaluated, @@ -527,7 +527,7 @@ acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, default: ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X", - ACPI_GET_OBJECT_TYPE(obj_desc))); + obj_desc->common.type)); status = AE_AML_INTERNAL; break; } diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index 6b0747ac683b..998eac329937 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -80,7 +80,7 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) { case ACPI_DESC_TYPE_OPERAND: - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { + if (obj_desc->common.type != ACPI_TYPE_LOCAL_REFERENCE) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -260,7 +260,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { + switch (operand0->common.type) { case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); @@ -277,7 +277,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, default: ACPI_ERROR((AE_INFO, "Invalid object type: %X", - ACPI_GET_OBJECT_TYPE(operand0))); + operand0->common.type)); status = AE_AML_INTERNAL; } @@ -298,7 +298,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { + switch (operand0->common.type) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ @@ -379,7 +379,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* Invalid object type, should not happen here */ ACPI_ERROR((AE_INFO, "Invalid object type: %X", - ACPI_GET_OBJECT_TYPE(operand0))); + operand0->common.type)); status = AE_AML_INTERNAL; goto cleanup; } @@ -581,7 +581,7 @@ acpi_ex_do_logical_op(u16 opcode, * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ - switch (ACPI_GET_OBJECT_TYPE(operand0)) { + switch (operand0->common.type) { case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer(operand1, &local_operand1, 16); @@ -608,7 +608,7 @@ acpi_ex_do_logical_op(u16 opcode, /* * Two cases: 1) Both Integers, 2) Both Strings or Buffers */ - if (ACPI_GET_OBJECT_TYPE(operand0) == ACPI_TYPE_INTEGER) { + if (operand0->common.type == ACPI_TYPE_INTEGER) { /* * 1) Both operands are of type integer * Note: local_operand1 may have changed above diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index b530480cc7d5..9635d21e568d 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -807,11 +807,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_namespace_node *) operand[0]); if (temp_desc - && - ((ACPI_GET_OBJECT_TYPE(temp_desc) == - ACPI_TYPE_STRING) - || (ACPI_GET_OBJECT_TYPE(temp_desc) == - ACPI_TYPE_LOCAL_REFERENCE))) { + && ((temp_desc->common.type == ACPI_TYPE_STRING) + || (temp_desc->common.type == + ACPI_TYPE_LOCAL_REFERENCE))) { operand[0] = temp_desc; acpi_ut_add_reference(temp_desc); } else { @@ -819,7 +817,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) goto cleanup; } } else { - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + switch ((operand[0])->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: /* * This is a deref_of (local_x | arg_x) @@ -877,8 +875,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) != ACPI_DESC_TYPE_NAMED) { - if (ACPI_GET_OBJECT_TYPE(operand[0]) == - ACPI_TYPE_STRING) { + if ((operand[0])->common.type == ACPI_TYPE_STRING) { /* * This is a deref_of (String). The string is a reference * to a named ACPI object. diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index 0b4f513ca885..85d95c92dfd3 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -399,7 +399,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) * At this point, the Source operand is a String, Buffer, or Package. * Verify that the index is within range. */ - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + switch ((operand[0])->common.type) { case ACPI_TYPE_STRING: if (index >= operand[0]->string.length) { diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index c6520bbf882b..253f9e122584 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -161,9 +161,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) * Create the return object. The Source operand is guaranteed to be * either a String or a Buffer, so just use its type. */ - return_desc = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE - (operand[0])); + return_desc = acpi_ut_create_internal_object((operand[0])-> + common.type); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; @@ -191,7 +190,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* Strings always have a sub-pointer, not so for buffers */ - switch (ACPI_GET_OBJECT_TYPE(operand[0])) { + switch ((operand[0])->common.type) { case ACPI_TYPE_STRING: /* Always allocate a new buffer for the String */ diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index a226f74d4a5c..52fec07064f0 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -279,7 +279,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, return_UINT32(0); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_BUFFER_FIELD) { + if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * buffer_field access can be on any byte boundary, so the * byte_alignment is always 1 byte -- regardless of any byte_alignment diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index a063a74006f6..607958ff467c 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -136,7 +136,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, switch (entry_type) { case ACPI_TYPE_PACKAGE: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_PACKAGE) { + if (source_desc->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Object not a Package, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -154,7 +154,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_BUFFER: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) { + if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "Object not a Buffer, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -172,7 +172,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_STRING: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) { + if (source_desc->common.type != ACPI_TYPE_STRING) { ACPI_ERROR((AE_INFO, "Object not a String, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); @@ -186,7 +186,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, case ACPI_TYPE_INTEGER: - if (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) { + if (source_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "Object not a Integer, type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index f6105a6d6126..c93b54ce7f78 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -149,7 +149,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, /* This is a union acpi_operand_object */ - switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { + switch (stack_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: ref_type = stack_desc->reference.class; @@ -297,8 +297,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "FieldRead SourceDesc=%p Type=%X\n", - stack_desc, - ACPI_GET_OBJECT_TYPE(stack_desc))); + stack_desc, stack_desc->common.type)); status = acpi_ex_read_data_from_field(walk_state, stack_desc, @@ -386,7 +385,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, * specification of the object_type and size_of operators). This means * traversing the list of possibly many nested references. */ - while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { + while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { switch (obj_desc->reference.class) { case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_NAME: @@ -518,7 +517,7 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, * Now we are guaranteed to have an object that has not been created * via the ref_of or Index operators. */ - type = ACPI_GET_OBJECT_TYPE(obj_desc); + type = obj_desc->common.type; exit: /* Convert internal types to external types */ diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 3c3802764bfb..5c729a9e9131 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -212,7 +212,7 @@ acpi_ex_resolve_operands(u16 opcode, /* ACPI internal object */ - object_type = ACPI_GET_OBJECT_TYPE(obj_desc); + object_type = obj_desc->common.type; /* Check for bad acpi_object_type */ @@ -287,8 +287,7 @@ acpi_ex_resolve_operands(u16 opcode, if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_OBJECT_TYPE(obj_desc) == - ACPI_TYPE_STRING)) { + && (obj_desc->common.type == ACPI_TYPE_STRING)) { /* * String found - the string references a named object and * must be resolved to a node @@ -336,7 +335,7 @@ acpi_ex_resolve_operands(u16 opcode, * -- All others must be resolved below. */ if ((opcode == AML_STORE_OP) && - (ACPI_GET_OBJECT_TYPE(*stack_ptr) == + ((*stack_ptr)->common.type == ACPI_TYPE_LOCAL_REFERENCE) && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) { goto next_operand; @@ -490,7 +489,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need an operand of type INTEGER, STRING or BUFFER */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -512,7 +511,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need an operand of type STRING or BUFFER */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -553,7 +552,7 @@ acpi_ex_resolve_operands(u16 opcode, * The only reference allowed here is a direct reference to * a namespace node. */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -576,7 +575,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need a buffer or package or (ACPI 2.0) String */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: @@ -598,7 +597,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_REGION: @@ -619,7 +618,7 @@ acpi_ex_resolve_operands(u16 opcode, /* Used by the Store() operator only */ - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: @@ -677,8 +676,8 @@ acpi_ex_resolve_operands(u16 opcode, * required object type (Simple cases only). */ status = acpi_ex_check_object_type(type_needed, - ACPI_GET_OBJECT_TYPE - (*stack_ptr), *stack_ptr); + (*stack_ptr)->common.type, + *stack_ptr); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index e35e9b4f6a4e..90d606196c99 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -129,7 +129,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: /* Output correct integer width */ @@ -324,7 +324,7 @@ acpi_ex_store(union acpi_operand_object *source_desc, /* Destination object must be a Reference or a Constant object */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + switch (dest_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: break; @@ -460,9 +460,8 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, */ obj_desc = *(index_desc->reference.where); - if (ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE - && source_desc->reference.class == ACPI_REFCLASS_TABLE) { + if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE && + source_desc->reference.class == ACPI_REFCLASS_TABLE) { /* This is a DDBHandle, just add a reference to it */ @@ -520,8 +519,8 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * by the INDEX_OP code. */ obj_desc = index_desc->reference.object; - if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) { + if ((obj_desc->common.type != ACPI_TYPE_BUFFER) && + (obj_desc->common.type != ACPI_TYPE_STRING)) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -529,7 +528,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * The assignment of the individual elements will be slightly * different for each source type. */ - switch (ACPI_GET_OBJECT_TYPE(source_desc)) { + switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: /* Use the least-significant byte of the integer */ @@ -707,8 +706,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, /* No conversions for all other types. Just attach the source object */ status = acpi_ns_attach_object(node, source_desc, - ACPI_GET_OBJECT_TYPE - (source_desc)); + source_desc->common.type); break; } diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index 145d15305f70..608e838d537e 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -96,8 +96,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, * are all essentially the same. This case handles the * "interchangeable" types Integer, String, and Buffer. */ - if (ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE) { + if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) { /* Resolve a reference object first */ @@ -117,13 +116,11 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, /* Must have a Integer, Buffer, or String */ - if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) && - (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) && - (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && - !((ACPI_GET_OBJECT_TYPE(source_desc) == - ACPI_TYPE_LOCAL_REFERENCE) - && (source_desc->reference.class == - ACPI_REFCLASS_TABLE))) { + if ((source_desc->common.type != ACPI_TYPE_INTEGER) && + (source_desc->common.type != ACPI_TYPE_BUFFER) && + (source_desc->common.type != ACPI_TYPE_STRING) && + !((source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && + (source_desc->reference.class == ACPI_REFCLASS_TABLE))) { /* Conversion successful but still not a valid type */ @@ -218,8 +215,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } - if (ACPI_GET_OBJECT_TYPE(source_desc) != - ACPI_GET_OBJECT_TYPE(dest_desc)) { + if (source_desc->common.type != dest_desc->common.type) { /* * The source type does not match the type of the destination. * Perform the "implicit conversion" of the source to the current type @@ -229,11 +225,10 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, * Otherwise, actual_src_desc is a temporary object to hold the * converted object. */ - status = - acpi_ex_convert_to_target_type(ACPI_GET_OBJECT_TYPE - (dest_desc), source_desc, - &actual_src_desc, - walk_state); + status = acpi_ex_convert_to_target_type(dest_desc->common.type, + source_desc, + &actual_src_desc, + walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -252,7 +247,7 @@ acpi_ex_store_object_to_object(union acpi_operand_object *source_desc, * We now have two objects of identical types, and we can perform a * copy of the *value* of the source object. */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + switch (dest_desc->common.type) { case ACPI_TYPE_INTEGER: dest_desc->integer.value = actual_src_desc->integer.value; diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 32b85d68e756..87730e944132 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -221,7 +221,7 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) */ if ((!obj_desc) || (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || - (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { + (obj_desc->common.type != ACPI_TYPE_INTEGER)) { return; } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index f67562ea0010..4df9eacb7c88 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -532,7 +532,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) /* It must be of type Package */ - else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) { + else if (info->return_object->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; @@ -553,9 +553,9 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) /* The first two elements must both be of type Integer */ - else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0]) + else if (((info->return_object->package.elements[0])->common.type != ACPI_TYPE_INTEGER) || - (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1]) + ((info->return_object->package.elements[1])->common.type != ACPI_TYPE_INTEGER)) { ACPI_ERROR((AE_INFO, "Sleep State return package elements are not both Integers (%s, %s)", diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 88303ebe924c..b6968a65cd4f 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -234,8 +234,7 @@ acpi_status acpi_ns_root_initialize(void) /* Store pointer to value descriptor in the Node */ status = acpi_ns_attach_object(new_node, obj_desc, - ACPI_GET_OBJECT_TYPE - (obj_desc)); + obj_desc->common.type); /* Remove local reference to the object */ diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index e96d37a596b8..7bfa6c1286f1 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -515,7 +515,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, case ACPI_DESC_TYPE_OPERAND: - obj_type = ACPI_GET_OBJECT_TYPE(obj_desc); + obj_type = obj_desc->common.type; if (obj_type > ACPI_TYPE_LOCAL_MAX) { acpi_os_printf diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index 08a97a57f8f9..3eb20bfda9d8 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -209,8 +209,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) obj_desc = node->object; - if (!obj_desc || - (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA)) { + if (!obj_desc || (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { return_VOID; } @@ -220,8 +219,7 @@ void acpi_ns_detach_object(struct acpi_namespace_node *node) if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_OPERAND) { node->object = obj_desc->common.next_object; if (node->object && - (ACPI_GET_OBJECT_TYPE(node->object) != - ACPI_TYPE_LOCAL_DATA)) { + ((node->object)->common.type != ACPI_TYPE_LOCAL_DATA)) { node->object = node->object->common.next_object; } } @@ -267,7 +265,7 @@ union acpi_operand_object *acpi_ns_get_attached_object(struct ((ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_OPERAND) && (ACPI_GET_DESCRIPTOR_TYPE(node->object) != ACPI_DESC_TYPE_NAMED)) - || (ACPI_GET_OBJECT_TYPE(node->object) == ACPI_TYPE_LOCAL_DATA)) { + || ((node->object)->common.type == ACPI_TYPE_LOCAL_DATA)) { return_PTR(NULL); } @@ -294,9 +292,9 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc); if ((!obj_desc) || - (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) || + (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) || (!obj_desc->common.next_object) || - (ACPI_GET_OBJECT_TYPE(obj_desc->common.next_object) == + ((obj_desc->common.next_object)->common.type == ACPI_TYPE_LOCAL_DATA)) { return_PTR(NULL); } @@ -331,7 +329,7 @@ acpi_ns_attach_data(struct acpi_namespace_node *node, prev_obj_desc = NULL; obj_desc = node->object; while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && (obj_desc->data.handler == handler)) { return (AE_ALREADY_EXISTS); } @@ -385,7 +383,7 @@ acpi_ns_detach_data(struct acpi_namespace_node * node, prev_obj_desc = NULL; obj_desc = node->object; while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && (obj_desc->data.handler == handler)) { if (prev_obj_desc) { prev_obj_desc->common.next_object = @@ -428,7 +426,7 @@ acpi_ns_get_attached_data(struct acpi_namespace_node * node, obj_desc = node->object; while (obj_desc) { - if ((ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) && + if ((obj_desc->common.type == ACPI_TYPE_LOCAL_DATA) && (obj_desc->data.handler == handler)) { *data = obj_desc->data.pointer; return (AE_OK); diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 452703290d35..72dd7b198520 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -221,7 +221,7 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, /* For returned Package objects, check the type of all sub-objects */ - if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_PACKAGE) { + if (return_object->common.type == ACPI_TYPE_PACKAGE) { status = acpi_ns_check_package(pathname, return_object_ptr, predefined); @@ -858,7 +858,7 @@ acpi_ns_check_object_type(char *pathname, * from all of the predefined names (including elements of returned * packages) */ - switch (ACPI_GET_OBJECT_TYPE(return_object)) { + switch (return_object->common.type) { case ACPI_TYPE_INTEGER: return_btype = ACPI_RTYPE_INTEGER; break; @@ -901,7 +901,7 @@ acpi_ns_check_object_type(char *pathname, /* For reference objects, check that the reference type is correct */ - if (ACPI_GET_OBJECT_TYPE(return_object) == ACPI_TYPE_LOCAL_REFERENCE) { + if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { status = acpi_ns_check_reference(pathname, return_object); } @@ -1006,7 +1006,7 @@ acpi_ns_repair_object(u32 expected_btypes, union acpi_operand_object *new_object; acpi_size length; - switch (ACPI_GET_OBJECT_TYPE(return_object)) { + switch (return_object->common.type) { case ACPI_TYPE_BUFFER: if (!(expected_btypes & ACPI_RTYPE_STRING)) { diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 22a7171ac1ed..2583a66a60a7 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -387,8 +387,7 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) /* We are interested in reference objects only */ - if (ACPI_GET_OBJECT_TYPE(info->return_object) != - ACPI_TYPE_LOCAL_REFERENCE) { + if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) { return; } diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 52865ee6bc77..b6667ff059e5 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -557,9 +557,9 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, table_index++) { if (*sub_object_list && /* Null object allowed */ ((ACPI_TYPE_STRING == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) || + (*sub_object_list)->common.type) || ((ACPI_TYPE_LOCAL_REFERENCE == - ACPI_GET_OBJECT_TYPE(*sub_object_list)) && + (*sub_object_list)->common.type) && ((*sub_object_list)->reference.class == ACPI_REFCLASS_NAME)))) { name_found = TRUE; @@ -575,8 +575,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object, /* Was a String type found? */ if (name_found) { - if (ACPI_GET_OBJECT_TYPE(*sub_object_list) == - ACPI_TYPE_STRING) { + if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) { /* * The length String.Length field does not include the * terminating NULL, add 1 diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index 61566b1a0616..663f692fffcf 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -212,7 +212,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* Each element of the top-level package must also be a package */ - if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) { + if ((*top_object_list)->common.type != ACPI_TYPE_PACKAGE) { ACPI_ERROR((AE_INFO, "(PRT[%X]) Need sub-package, found %s", index, @@ -240,7 +240,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 1) First subobject: Dereference the PRT.Address */ obj_desc = sub_object_list[0]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].Address) Need Integer, found %s", index, @@ -253,7 +253,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 2) Second subobject: Dereference the PRT.Pin */ obj_desc = sub_object_list[1]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].Pin) Need Integer, found %s", index, @@ -265,7 +265,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * If BIOS erroneously reversed the _PRT source_name and source_index, * then reverse them back. */ - if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) != + if ((sub_object_list[3])->common.type != ACPI_TYPE_INTEGER) { if (acpi_gbl_enable_interpreter_slack) { source_name_index = 3; @@ -291,8 +291,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, * other ACPI implementations. */ obj_desc = sub_object_list[3]; - if (!obj_desc - || (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { + if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) { sub_object_list[3] = sub_object_list[2]; sub_object_list[2] = obj_desc; @@ -307,7 +306,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, */ obj_desc = sub_object_list[source_name_index]; if (obj_desc) { - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_LOCAL_REFERENCE: if (obj_desc->reference.class != @@ -380,7 +379,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 4) Fourth subobject: Dereference the PRT.source_index */ obj_desc = sub_object_list[source_index_index]; - if (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER) { + if (obj_desc->common.type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "(PRT[%X].SourceIndex) Need Integer, found %s", index, diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index b0dcfd3c872a..cabe860ce007 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -135,11 +135,11 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, * In general, the external object will be the same type as * the internal object */ - external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); + external_object->type = internal_object->common.type; /* However, only a limited number of external types are supported */ - switch (ACPI_GET_OBJECT_TYPE(internal_object)) { + switch (internal_object->common.type) { case ACPI_TYPE_STRING: external_object->string.pointer = (char *)data_space; @@ -222,8 +222,8 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, */ ACPI_ERROR((AE_INFO, "Unsupported object type, cannot convert to external object: %s", - acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE - (internal_object)))); + acpi_ut_get_type_name(internal_object->common. + type))); return_ACPI_STATUS(AE_SUPPORT); } @@ -355,7 +355,7 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, info.object_space = 0; info.num_packages = 1; - external_object->type = ACPI_GET_OBJECT_TYPE(internal_object); + external_object->type = internal_object->common.type; external_object->package.count = internal_object->package.count; external_object->package.elements = ACPI_CAST_PTR(union acpi_object, info.free_space); @@ -399,7 +399,7 @@ acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); - if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) { + if (internal_object->common.type == ACPI_TYPE_PACKAGE) { /* * Package object: Copy all subobjects (including * nested packages) @@ -697,7 +697,7 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, /* Handle the objects with extra data */ - switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { + switch (dest_desc->common.type) { case ACPI_TYPE_BUFFER: /* * Allocate and copy the actual buffer if and only if: @@ -814,8 +814,8 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type, * This is a simple object, just copy it */ target_object = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE - (source_object)); + acpi_ut_create_internal_object(source_object-> + common.type); if (!target_object) { return (AE_NO_MEMORY); } @@ -892,7 +892,7 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); - dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj); + dest_obj->common.type = source_obj->common.type; dest_obj->common.flags = source_obj->common.flags; dest_obj->package.count = source_obj->package.count; @@ -950,15 +950,14 @@ acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, /* Create the top level object */ - *dest_desc = - acpi_ut_create_internal_object(ACPI_GET_OBJECT_TYPE(source_desc)); + *dest_desc = acpi_ut_create_internal_object(source_desc->common.type); if (!*dest_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Copy the object and possible subobjects */ - if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_PACKAGE) { + if (source_desc->common.type == ACPI_TYPE_PACKAGE) { status = acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc, walk_state); diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index a0be9e39531e..a5ee23bc4f55 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -86,7 +86,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) * Must delete or free any pointers within the object that are not * actual ACPI objects (for example, a raw buffer pointer). */ - switch (ACPI_GET_OBJECT_TYPE(object)) { + switch (object->common.type) { case ACPI_TYPE_STRING: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, @@ -382,7 +382,7 @@ acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) object, new_count)); } - if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) { + if (object->common.type == ACPI_TYPE_METHOD) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Method Obj %p Refs=%X, [Decremented]\n", object, new_count)); @@ -469,7 +469,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) * All sub-objects must have their reference count incremented also. * Different object types have different subobjects. */ - switch (ACPI_GET_OBJECT_TYPE(object)) { + switch (object->common.type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 9c9897dbe907..99bfbd23258b 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -248,7 +248,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, /* Map the return object type to the bitmapped type */ - switch (ACPI_GET_OBJECT_TYPE(info->return_object)) { + switch ((info->return_object)->common.type) { case ACPI_TYPE_INTEGER: return_btype = ACPI_BTYPE_INTEGER; break; @@ -418,7 +418,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node, return_ACPI_STATUS(status); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Convert the Numeric HID to string */ @@ -459,7 +459,7 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, struct acpi_compatible_id *one_cid) { - switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { + switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: /* Convert the Numeric CID to string */ @@ -527,7 +527,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, /* Get the number of _CIDs returned */ count = 1; - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { count = obj_desc->package.count; } @@ -555,7 +555,7 @@ acpi_ut_execute_CID(struct acpi_namespace_node * device_node, /* The _CID object can be either a single CID or a package (list) of CIDs */ - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { /* Translate each package element */ @@ -620,7 +620,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, return_ACPI_STATUS(status); } - if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { /* Convert the Numeric UID to string */ diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index bec0e21673cb..7fc35d33adb1 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -473,7 +473,7 @@ char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) return ("[NULL Object Descriptor]"); } - return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc))); + return (acpi_ut_get_type_name(obj_desc->common.type)); } /******************************************************************************* diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index c1f7f4e1a72d..1c9e250caefb 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -938,8 +938,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object, if ((!this_source_obj) || (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) != ACPI_DESC_TYPE_OPERAND) - || (ACPI_GET_OBJECT_TYPE(this_source_obj) != - ACPI_TYPE_PACKAGE)) { + || (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) { status = walk_callback(ACPI_COPY_TYPE_SIMPLE, this_source_obj, state, context); diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index fd5ea7543e5b..ae337a717438 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -457,7 +457,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, * must be accessed bytewise or there may be alignment problems on * certain processors */ - switch (ACPI_GET_OBJECT_TYPE(internal_object)) { + switch (internal_object->common.type) { case ACPI_TYPE_STRING: length += (acpi_size) internal_object->string.length + 1; @@ -518,8 +518,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, ACPI_ERROR((AE_INFO, "Cannot convert to external object - " "unsupported type [%s] %X in object %p", acpi_ut_get_object_type_name(internal_object), - ACPI_GET_OBJECT_TYPE(internal_object), - internal_object)); + internal_object->common.type, internal_object)); status = AE_TYPE; break; } @@ -664,7 +663,7 @@ acpi_ut_get_object_size(union acpi_operand_object *internal_object, if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_OPERAND) - && (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE)) { + && (internal_object->common.type == ACPI_TYPE_PACKAGE)) { status = acpi_ut_get_package_object_size(internal_object, obj_length); From 4f70e371cdf6ab4f988fbaf2257e6259422ba662 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:52:43 +0800 Subject: [PATCH 029/140] ACPICA: Conditionally compile acpi_set_firmware_waking_vector64 This function is only needed on 64-bit host operating systems. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwsleep.c | 5 ++++- include/acpi/acpixf.h | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 51868f48159c..26e249e69ead 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -90,6 +90,7 @@ acpi_set_firmware_waking_vector(u32 physical_address) ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) +#if ACPI_MACHINE_WIDTH == 64 /******************************************************************************* * * FUNCTION: acpi_set_firmware_waking_vector64 @@ -100,7 +101,8 @@ ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector) * RETURN: Status * * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if - * it exists in the table. + * it exists in the table. This function is intended for use with + * 64-bit host operating systems. * ******************************************************************************/ acpi_status @@ -124,6 +126,7 @@ acpi_set_firmware_waking_vector64(u64 physical_address) } ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64) +#endif /******************************************************************************* * diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 8f9df6235255..e10c89691043 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -351,11 +351,11 @@ acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value); acpi_status acpi_set_register(u32 register_id, u32 value); -acpi_status -acpi_set_firmware_waking_vector(u32 physical_address); +acpi_status acpi_set_firmware_waking_vector(u32 physical_address); -acpi_status -acpi_set_firmware_waking_vector64(u64 physical_address); +#if ACPI_MACHINE_WIDTH == 64 +acpi_status acpi_set_firmware_waking_vector64(u64 physical_address); +#endif acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg); From c114e4b6c606c7f174b752f946fcfb0e7e61a347 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Feb 2009 11:00:00 +0800 Subject: [PATCH 030/140] ACPICA: Debug output: print result of _OSI invocations Print input strings and the result (supported or not supported) for invocations of the _OSI method. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/uteval.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 99bfbd23258b..9c4ae6f26b9d 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -98,6 +98,7 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) acpi_status status; union acpi_operand_object *string_desc; union acpi_operand_object *return_desc; + u32 return_value; u32 i; ACPI_FUNCTION_TRACE(ut_osi_implementation); @@ -116,10 +117,9 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) return_ACPI_STATUS(AE_NO_MEMORY); } - /* Default return value is 0, NOT-SUPPORTED */ + /* Default return value is 0, NOT SUPPORTED */ - return_desc->integer.value = 0; - walk_state->return_desc = return_desc; + return_value = 0; /* Compare input string to static table of supported interfaces */ @@ -127,8 +127,11 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) if (!ACPI_STRCMP (string_desc->string.pointer, acpi_interfaces_supported[i])) { - return_desc->integer.value = ACPI_UINT32_MAX; - goto done; + + /* The interface is supported */ + + return_value = ACPI_UINT32_MAX; + goto exit; } } @@ -139,15 +142,22 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) */ status = acpi_os_validate_interface(string_desc->string.pointer); if (ACPI_SUCCESS(status)) { - return_desc->integer.value = ACPI_UINT32_MAX; + + /* The interface is supported */ + + return_value = ACPI_UINT32_MAX; } -done: - ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, "ACPI: BIOS _OSI(%s) %ssupported\n", - string_desc->string.pointer, - return_desc->integer.value == 0 ? "not-" : "")); +exit: + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + "ACPI: BIOS _OSI(%s) is %ssupported\n", + string_desc->string.pointer, return_value == 0 ? "not " : "")); - return_ACPI_STATUS(AE_OK); + /* Complete the return value */ + + return_desc->integer.value = return_value; + walk_state->return_desc = return_desc; + return_ACPI_STATUS (AE_OK); } /******************************************************************************* From 7bcc06e845479bde939059bafa088bf25ede9dbf Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 14:58:08 +0800 Subject: [PATCH 031/140] ACPICA: Debug output: decrease verbosity of DB_INFO debug level Removed some of the extraneous debug prints using the DB_INFO level. This should make the DB_INFO more useful. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nseval.c | 2 +- drivers/acpi/acpica/nsutils.c | 2 +- drivers/acpi/acpica/utobject.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 0f3d5f9b5966..8e7dec1176c9 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -155,7 +155,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) } - ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:", + ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index 3e1149bf4aa5..d30b0e65ab3c 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -872,7 +872,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL, return_node); if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n", pathname, acpi_format_exception(status))); } diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index ae337a717438..0207b625274a 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -310,7 +310,7 @@ u8 acpi_ut_valid_internal_object(void *object) /* Check for a null pointer */ if (!object) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Null Object Ptr\n")); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "**** Null Object Ptr\n")); return (FALSE); } @@ -324,7 +324,7 @@ u8 acpi_ut_valid_internal_object(void *object) return (TRUE); default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p is not not an ACPI operand obj [%s]\n", object, acpi_ut_get_descriptor_name(object))); break; From ec41f193eadb6301f3c052b5e0dbc0b5636982e8 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 15:03:30 +0800 Subject: [PATCH 032/140] ACPICA: Formatting update - no functional changes Split some long lines. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 33 ++++++++++++++++++------------ drivers/acpi/acpica/tbinstal.c | 9 +++++---- drivers/acpi/acpica/tbutils.c | 17 ++++++++-------- drivers/acpi/acpica/tbxface.c | 37 +++++++++++++++------------------- drivers/acpi/acpica/tbxfroot.c | 4 ++-- drivers/acpi/acpica/utcopy.c | 5 +++-- drivers/acpi/acpica/uteval.c | 5 ++--- drivers/acpi/acpica/utglobal.c | 5 ++++- 8 files changed, 61 insertions(+), 54 deletions(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 43fe886b41a2..af8fbe12d8b7 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -132,7 +132,8 @@ static struct acpi_fadt_info fadt_info_table[] = { ACPI_FADT_SEPARATE_LENGTH} }; -#define ACPI_FADT_INFO_ENTRIES (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) +#define ACPI_FADT_INFO_ENTRIES \ + (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) /* Table used to split Event Blocks into separate status/enable registers */ @@ -161,7 +162,8 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = { 1} }; -#define ACPI_FADT_PM_INFO_ENTRIES (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info)) +#define ACPI_FADT_PM_INFO_ENTRIES \ + (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info)) /******************************************************************************* * @@ -416,7 +418,7 @@ static void acpi_tb_convert_fadt(void) } } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_tb_validate_fadt * @@ -503,7 +505,8 @@ static void acpi_tb_validate_fadt(void) */ if (!address64->address || !length) { ACPI_ERROR((AE_INFO, - "Required field %s has zero address and/or length: %8.8X%8.8X/%X", + "Required field %s has zero address and/or length:" + " %8.8X%8.8X/%X", name, ACPI_FORMAT_UINT64(address64-> address), @@ -512,12 +515,14 @@ static void acpi_tb_validate_fadt(void) } else if (fadt_info_table[i].type & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (PM2Control, GPE0, GPE1) AND has its own - * length field. If present, both the address and length must be valid. + * length field. If present, both the address and length must + * be valid. */ - if ((address64->address && !length) - || (!address64->address && length)) { + if ((address64->address && !length) || + (!address64->address && length)) { ACPI_WARNING((AE_INFO, - "Optional field %s has zero address or length: %8.8X%8.8X/%X", + "Optional field %s has zero address or length: " + "%8.8X%8.8X/%X", name, ACPI_FORMAT_UINT64(address64-> address), @@ -525,8 +530,10 @@ static void acpi_tb_validate_fadt(void) } } - /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ - + /* + * If both 32- and 64-bit addresses are valid (non-zero), + * they must match + */ if (address64->address && *address32 && (address64->address != (u64) * address32)) { ACPI_ERROR((AE_INFO, @@ -537,7 +544,7 @@ static void acpi_tb_validate_fadt(void) } } -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_tb_setup_fadt_registers * @@ -596,8 +603,8 @@ static void acpi_tb_setup_fadt_registers(void) * Each register is defined to be (event block length / 2). Extra divide * by 8 converts bits to bytes. */ - pm1_register_byte_width = - (u8)ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width); + pm1_register_byte_width = (u8) + ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width); /* * Calculate separate GAS structs for the PM1x (A/B) Status and Enable diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index ef269a297b57..c37993003f2c 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -273,8 +273,9 @@ acpi_status acpi_tb_resize_root_table_list(void) /* Increase the Table Array size */ tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list. - size + ACPI_ROOT_TABLE_SIZE_INCREMENT) - * sizeof(struct acpi_table_desc)); + size + + ACPI_ROOT_TABLE_SIZE_INCREMENT) * + sizeof(struct acpi_table_desc)); if (!tables) { ACPI_ERROR((AE_INFO, "Could not allocate new root table array")); @@ -561,8 +562,8 @@ u8 acpi_tb_is_table_loaded(u32 table_index) (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); if (table_index < acpi_gbl_root_table_list.count) { is_loaded = (u8) - (acpi_gbl_root_table_list.tables[table_index]. - flags & ACPI_TABLE_IS_LOADED); + (acpi_gbl_root_table_list.tables[table_index].flags & + ACPI_TABLE_IS_LOADED); } (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index a0b424356b98..dc45b49e5cb9 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -413,7 +413,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) } else { /* * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return - * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit + * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, + * return 64-bit */ ACPI_MOVE_64_TO_64(&address64, table_entry); @@ -423,7 +424,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) /* Will truncate 64-bit address to 32 bits, issue warning */ ACPI_WARNING((AE_INFO, - "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating", + "64-bit Physical Address in XSDT is too large (%8.8X%8.8X)," + " truncating", ACPI_FORMAT_UINT64(address64))); } #endif @@ -546,13 +548,12 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address) /* Calculate the number of tables described in the root table */ - table_count = - (u32) ((table->length - - sizeof(struct acpi_table_header)) / table_entry_size); - + table_count = (u32)((table->length - sizeof(struct acpi_table_header)) / + table_entry_size); /* - * First two entries in the table array are reserved for the DSDT and FACS, - * which are not actually present in the RSDT/XSDT - they come from the FADT + * First two entries in the table array are reserved for the DSDT + * and FACS, which are not actually present in the RSDT/XSDT - they + * come from the FADT */ table_entry = ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header); diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 416d01d9a970..dbca22651504 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -246,7 +246,7 @@ acpi_status acpi_load_table(struct acpi_table_header *table_ptr) ACPI_EXPORT_SYMBOL(acpi_load_table) -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_get_table_header * @@ -261,7 +261,7 @@ ACPI_EXPORT_SYMBOL(acpi_load_table) * NOTE: Caller is responsible in unmapping the header with * acpi_os_unmap_memory * - *****************************************************************************/ + ******************************************************************************/ acpi_status acpi_get_table_header(char *signature, u32 instance, struct acpi_table_header *out_table_header) @@ -276,9 +276,8 @@ acpi_get_table_header(char *signature, return (AE_BAD_PARAMETER); } - /* - * Walk the root table list - */ + /* Walk the root table list */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { if (!ACPI_COMPARE_NAME (&(acpi_gbl_root_table_list.tables[i].signature), @@ -291,8 +290,8 @@ acpi_get_table_header(char *signature, } if (!acpi_gbl_root_table_list.tables[i].pointer) { - if ((acpi_gbl_root_table_list.tables[i]. - flags & ACPI_TABLE_ORIGIN_MASK) == + if ((acpi_gbl_root_table_list.tables[i].flags & + ACPI_TABLE_ORIGIN_MASK) == ACPI_TABLE_ORIGIN_MAPPED) { header = acpi_os_map_memory(acpi_gbl_root_table_list. @@ -323,7 +322,7 @@ acpi_get_table_header(char *signature, ACPI_EXPORT_SYMBOL(acpi_get_table_header) -/****************************************************************************** +/******************************************************************************* * * FUNCTION: acpi_unload_table_id * @@ -374,7 +373,7 @@ ACPI_EXPORT_SYMBOL(acpi_unload_table_id) * * DESCRIPTION: Finds and verifies an ACPI table. * - *****************************************************************************/ + ******************************************************************************/ acpi_status acpi_get_table(char *signature, u32 instance, struct acpi_table_header **out_table) @@ -389,9 +388,8 @@ acpi_get_table(char *signature, return (AE_BAD_PARAMETER); } - /* - * Walk the root table list - */ + /* Walk the root table list */ + for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { if (!ACPI_COMPARE_NAME (&(acpi_gbl_root_table_list.tables[i].signature), @@ -526,17 +524,15 @@ static acpi_status acpi_tb_load_namespace(void) (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - /* - * Load and parse tables. - */ + /* Load and parse tables */ + status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } - /* - * Load any SSDT or PSDT tables. Note: Loop leaves tables locked - */ + /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ + (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { if ((!ACPI_COMPARE_NAME @@ -589,9 +585,8 @@ acpi_status acpi_load_tables(void) ACPI_FUNCTION_TRACE(acpi_load_tables); - /* - * Load the namespace from the tables - */ + /* Load the namespace from the tables */ + status = acpi_tb_load_namespace(); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index b7fc8dd43341..85ea834199e2 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -75,8 +75,8 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ - if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) - != 0) { + if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, + sizeof(ACPI_SIG_RSDP) - 1) != 0) { /* Nope, BAD Signature */ diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index cabe860ce007..919624f123d5 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -496,8 +496,9 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, case ACPI_TYPE_STRING: internal_object->string.pointer = - ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string. - length + 1); + ACPI_ALLOCATE_ZEROED((acpi_size) + external_object->string.length + 1); + if (!internal_object->string.pointer) { goto error_exit; } diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 9c4ae6f26b9d..3b9152579d04 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -124,9 +124,8 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) /* Compare input string to static table of supported interfaces */ for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { - if (!ACPI_STRCMP - (string_desc->string.pointer, - acpi_interfaces_supported[i])) { + if (!ACPI_STRCMP(string_desc->string.pointer, + acpi_interfaces_supported[i])) { /* The interface is supported */ diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 7fc35d33adb1..256ce7778565 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -746,7 +746,10 @@ acpi_status acpi_ut_init_globals(void) for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) { acpi_gbl_owner_id_mask[i] = 0; } - acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* Last ID is never valid */ + + /* Last owner_iD is never valid */ + + acpi_gbl_owner_id_mask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; /* GPE support */ From 9892dd23cbbfab1f7d4818622296e415979a9c77 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 15:10:07 +0800 Subject: [PATCH 033/140] ACPICA: Optimize ACPI register locking Removed locking for reads from the ACPI bit registers in PM1 Status, Enable, Control, and PM2 Control. The lock is not required when reading the single-bit registers. The acpi_get_register_unlocked function is no longer needed and has been removed. This will improve performance for reads on these registers. ACPICA BZ 760. http://www.acpica.org/bugzilla/show_bug.cgi?id=760 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwsleep.c | 2 +- drivers/acpi/acpica/hwxface.c | 65 +++++++++++++++-------------------- drivers/acpi/processor_idle.c | 2 +- include/acpi/acpixf.h | 2 -- 4 files changed, 29 insertions(+), 42 deletions(-) diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 26e249e69ead..677ccb6bceea 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -365,7 +365,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Wait until we enter sleep state */ do { - status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS, + status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 4df9eacb7c88..c8100199634b 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -242,24 +242,35 @@ ACPI_EXPORT_SYMBOL(acpi_write) /******************************************************************************* * - * FUNCTION: acpi_get_register_unlocked + * FUNCTION: acpi_get_register * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * return_value - Value that was read from the register + * PARAMETERS: register_id - ID of ACPI Bit Register to access + * return_value - Value that was read from the register, + * normalized to bit position zero. * - * RETURN: Status and the value read from specified Register. Value + * RETURN: Status and the value read from the specified Register. Value * returned is normalized to bit0 (is shifted all the way right) * * DESCRIPTION: ACPI bit_register read function. Does not acquire the HW lock. * + * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and + * PM2 Control. + * + * Note: The hardware lock is not required when reading the ACPI bit registers + * since almost all of them are single bit and it does not matter that + * the parent hardware register can be split across two physical + * registers. The only multi-bit field is SLP_TYP in the PM1 control + * register, but this field does not cross an 8-bit boundary (nor does + * it make much sense to actually read this field.) + * ******************************************************************************/ -acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) +acpi_status acpi_get_register(u32 register_id, u32 *return_value) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_get_register_unlocked); + ACPI_FUNCTION_TRACE(acpi_get_register); /* Get the info structure corresponding to the requested ACPI Register */ @@ -268,7 +279,7 @@ acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* Read from the register */ + /* Read the entire parent register */ status = acpi_hw_register_read(bit_reg_info->parent_register, ®ister_value); @@ -291,46 +302,24 @@ acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_get_register_unlocked) - -/******************************************************************************* - * - * FUNCTION: acpi_get_register - * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * return_value - Value that was read from the register - * - * RETURN: Status and the value read from specified Register. Value - * returned is normalized to bit0 (is shifted all the way right) - * - * DESCRIPTION: ACPI bit_register read function. - * - ******************************************************************************/ -acpi_status acpi_get_register(u32 register_id, u32 *return_value) -{ - acpi_status status; - acpi_cpu_flags flags; - - flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - status = acpi_get_register_unlocked(register_id, return_value); - acpi_os_release_lock(acpi_gbl_hardware_lock, flags); - - return (status); -} - ACPI_EXPORT_SYMBOL(acpi_get_register) /******************************************************************************* * * FUNCTION: acpi_set_register * - * PARAMETERS: register_id - ID of ACPI bit_register to access - * Value - (only used on write) value to write to the - * Register, NOT pre-normalized to the bit pos + * PARAMETERS: register_id - ID of ACPI Bit Register to access + * Value - Value to write to the register, in bit + * position zero. The bit is automaticallly + * shifted to the correct position. * * RETURN: Status * - * DESCRIPTION: ACPI Bit Register write function. + * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock + * since most operations require a read/modify/write sequence. + * + * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and + * PM2 Control. * ******************************************************************************/ acpi_status acpi_set_register(u32 register_id, u32 value) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 7bc22a471fe3..6946047d0096 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -800,7 +800,7 @@ static int acpi_idle_bm_check(void) { u32 bm_status = 0; - acpi_get_register_unlocked(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); + acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); if (bm_status) acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); /* diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index e10c89691043..325d4b073aca 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -347,8 +347,6 @@ acpi_status acpi_reset(void); acpi_status acpi_get_register(u32 register_id, u32 * return_value); -acpi_status acpi_get_register_unlocked(u32 register_id, u32 *return_value); - acpi_status acpi_set_register(u32 register_id, u32 value); acpi_status acpi_set_firmware_waking_vector(u32 physical_address); From 50ffba1bd3120b069617455545bc27bcf3cf7579 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Feb 2009 15:02:07 +0800 Subject: [PATCH 034/140] ACPICA: Rename ACPI bit register access functions Rename acpi_get_register and acpi_set_register to clarify the purpose of these functions. New names are acpi_read_bit_register and acpi_write_bit_register. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/evevent.c | 12 ++++++------ drivers/acpi/acpica/evmisc.c | 4 ++-- drivers/acpi/acpica/evxfevnt.c | 24 ++++++++++++------------ drivers/acpi/acpica/hwacpi.c | 2 +- drivers/acpi/acpica/hwsleep.c | 15 ++++++++------- drivers/acpi/acpica/hwxface.c | 16 ++++++++-------- drivers/acpi/processor_idle.c | 10 +++++----- drivers/acpi/sleep.c | 2 +- include/acpi/acpixf.h | 4 ++-- 9 files changed, 45 insertions(+), 44 deletions(-) diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 803edd9e3f6a..246f8775ec13 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -204,8 +204,8 @@ static acpi_status acpi_ev_fixed_event_initialize(void) if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { status = - acpi_set_register(acpi_gbl_fixed_event_info[i]. - enable_register_id, 0); + acpi_write_bit_register(acpi_gbl_fixed_event_info + [i].enable_register_id, 0); if (ACPI_FAILURE(status)) { return (status); } @@ -288,16 +288,16 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) /* Clear the status bit */ - (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + status_register_id, 1); /* * Make sure we've got a handler. If not, report an error. The event is * disabled to prevent further interrupts. */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { - (void)acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, 0); ACPI_ERROR((AE_INFO, "No installed handler for fixed event [%08X]", diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 5f893057bcc6..0e9e12b2f2bb 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -534,8 +534,8 @@ acpi_status acpi_ev_release_global_lock(void) */ if (pending) { status = - acpi_set_register(ACPI_BITREG_GLOBAL_LOCK_RELEASE, - 1); + acpi_write_bit_register + (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1); } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 35485e4b60a6..484c9793ca06 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -172,8 +172,8 @@ acpi_status acpi_enable_event(u32 event, u32 flags) * register bit) */ status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 1); + acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -181,8 +181,8 @@ acpi_status acpi_enable_event(u32 event, u32 flags) /* Make sure that the hardware responded */ status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -354,15 +354,15 @@ acpi_status acpi_disable_event(u32 event, u32 flags) * register bit) */ status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, 0); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, &value); + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. + enable_register_id, &value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -407,8 +407,8 @@ acpi_status acpi_clear_event(u32 event) * register bit) */ status = - acpi_set_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. + status_register_id, 1); return_ACPI_STATUS(status); } @@ -495,7 +495,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) /* Get the status of the requested fixed event */ status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. enable_register_id, &value); if (ACPI_FAILURE(status)) return_ACPI_STATUS(status); @@ -503,7 +503,7 @@ acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status) *event_status = value; status = - acpi_get_register(acpi_gbl_fixed_event_info[event]. + acpi_read_bit_register(acpi_gbl_fixed_event_info[event]. status_register_id, &value); if (ACPI_FAILURE(status)) return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index a9d4fea4167f..8902db8c670f 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -172,7 +172,7 @@ u32 acpi_hw_get_mode(void) return_UINT32(ACPI_SYS_MODE_ACPI); } - status = acpi_get_register(ACPI_BITREG_SCI_ENABLE, &value); + status = acpi_read_bit_register(ACPI_BITREG_SCI_ENABLE, &value); if (ACPI_FAILURE(status)) { return_UINT32(ACPI_SYS_MODE_LEGACY); } diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 677ccb6bceea..78d62b8a5c31 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -250,7 +250,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Clear wake status */ - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -365,7 +365,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Wait until we enter sleep state */ do { - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, + status = acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -399,7 +399,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -431,7 +431,8 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) do { acpi_os_stall(1000); - status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value); + status = + acpi_read_bit_register(ACPI_BITREG_WAKE_STATUS, &in_value); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -592,18 +593,18 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) * it to determine whether the system is rebooting or resuming. Clear * it for compatibility. */ - acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); acpi_gbl_system_awake_and_running = TRUE; /* Enable power button */ (void) - acpi_set_register(acpi_gbl_fixed_event_info + acpi_write_bit_register(acpi_gbl_fixed_event_info [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); (void) - acpi_set_register(acpi_gbl_fixed_event_info + acpi_write_bit_register(acpi_gbl_fixed_event_info [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); arg.integer.value = ACPI_SST_WORKING; diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index c8100199634b..529251c7f911 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -242,7 +242,7 @@ ACPI_EXPORT_SYMBOL(acpi_write) /******************************************************************************* * - * FUNCTION: acpi_get_register + * FUNCTION: acpi_read_bit_register * * PARAMETERS: register_id - ID of ACPI Bit Register to access * return_value - Value that was read from the register, @@ -264,13 +264,13 @@ ACPI_EXPORT_SYMBOL(acpi_write) * it make much sense to actually read this field.) * ******************************************************************************/ -acpi_status acpi_get_register(u32 register_id, u32 *return_value) +acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_get_register); + ACPI_FUNCTION_TRACE(acpi_read_bit_register); /* Get the info structure corresponding to the requested ACPI Register */ @@ -302,11 +302,11 @@ acpi_status acpi_get_register(u32 register_id, u32 *return_value) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_get_register) +ACPI_EXPORT_SYMBOL(acpi_read_bit_register) /******************************************************************************* * - * FUNCTION: acpi_set_register + * FUNCTION: acpi_write_bit_register * * PARAMETERS: register_id - ID of ACPI Bit Register to access * Value - Value to write to the register, in bit @@ -322,14 +322,14 @@ ACPI_EXPORT_SYMBOL(acpi_get_register) * PM2 Control. * ******************************************************************************/ -acpi_status acpi_set_register(u32 register_id, u32 value) +acpi_status acpi_write_bit_register(u32 register_id, u32 value) { u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; acpi_status status; acpi_cpu_flags lock_flags; - ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id); + ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id); /* Get the info structure corresponding to the requested ACPI Register */ @@ -459,7 +459,7 @@ acpi_status acpi_set_register(u32 register_id, u32 value) return_ACPI_STATUS(status); } -ACPI_EXPORT_SYMBOL(acpi_set_register) +ACPI_EXPORT_SYMBOL(acpi_write_bit_register) /******************************************************************************* * diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 6946047d0096..5c69e85c1e4d 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -630,7 +630,7 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, * In either case, the proper way to * handle BM_RLD is to set it and leave it set. */ - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1); + acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1); return; } @@ -800,9 +800,9 @@ static int acpi_idle_bm_check(void) { u32 bm_status = 0; - acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); + acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); if (bm_status) - acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); + acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); /* * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect * the true state of bus mastering activity; forcing us to @@ -1028,7 +1028,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); + acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); @@ -1041,7 +1041,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, /* Re-enable bus master arbitration */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); } diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 00456fccfa38..837ac7d5801b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -248,7 +248,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) /* If ACPI is not enabled by the BIOS, we need to enable it here. */ if (set_sci_en_on_resume) - acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1); + acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); else acpi_enable(); diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 325d4b073aca..a5525a5518a9 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -345,9 +345,9 @@ acpi_resource_to_address64(struct acpi_resource *resource, */ acpi_status acpi_reset(void); -acpi_status acpi_get_register(u32 register_id, u32 * return_value); +acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value); -acpi_status acpi_set_register(u32 register_id, u32 value); +acpi_status acpi_write_bit_register(u32 register_id, u32 value); acpi_status acpi_set_firmware_waking_vector(u32 physical_address); From 88dcb04a813265e1a5a1bc74af2db7efa7d62ee6 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 18 Feb 2009 16:01:04 +0800 Subject: [PATCH 035/140] ACPICA: Restructure bit register access functions Update code for acpi_read_bit_register and acpi_write_bit_register. Simplified code path, condensed duplicate code. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwxface.c | 181 ++++++++++++---------------------- 1 file changed, 64 insertions(+), 117 deletions(-) diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 529251c7f911..caad51680bd6 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -133,8 +133,8 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) *value = 0; /* - * Two address spaces supported: Memory or IO. - * PCI_Config is not supported here because the GAS struct is insufficient + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient */ switch (reg->space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: @@ -266,11 +266,12 @@ ACPI_EXPORT_SYMBOL(acpi_write) ******************************************************************************/ acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) { - u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; + u32 register_value; + u32 value; acpi_status status; - ACPI_FUNCTION_TRACE(acpi_read_bit_register); + ACPI_FUNCTION_TRACE_U32(acpi_read_bit_register, register_id); /* Get the info structure corresponding to the requested ACPI Register */ @@ -283,23 +284,22 @@ acpi_status acpi_read_bit_register(u32 register_id, u32 *return_value) status = acpi_hw_register_read(bit_reg_info->parent_register, ®ister_value); - - if (ACPI_SUCCESS(status)) { - - /* Normalize the value that was read */ - - register_value = - ((register_value & bit_reg_info->access_bit_mask) - >> bit_reg_info->bit_position); - - *return_value = register_value; - - ACPI_DEBUG_PRINT((ACPI_DB_IO, "Read value %8.8X register %X\n", - register_value, - bit_reg_info->parent_register)); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } - return_ACPI_STATUS(status); + /* Normalize the value that was read, mask off other bits */ + + value = ((register_value & bit_reg_info->access_bit_mask) + >> bit_reg_info->bit_position); + + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n", + register_id, bit_reg_info->parent_register, + register_value, value)); + + *return_value = value; + return_ACPI_STATUS(AE_OK); } ACPI_EXPORT_SYMBOL(acpi_read_bit_register) @@ -321,13 +321,16 @@ ACPI_EXPORT_SYMBOL(acpi_read_bit_register) * SUPPORTS: Bit fields in PM1 Status, PM1 Enable, PM1 Control, and * PM2 Control. * + * Note that at this level, the fact that there may be actually two + * hardware registers (A and B - and B may not exist) is abstracted. + * ******************************************************************************/ acpi_status acpi_write_bit_register(u32 register_id, u32 value) { - u32 register_value = 0; struct acpi_bit_register_info *bit_reg_info; - acpi_status status; acpi_cpu_flags lock_flags; + u32 register_value; + acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_U32(acpi_write_bit_register, register_id); @@ -335,127 +338,71 @@ acpi_status acpi_write_bit_register(u32 register_id, u32 value) bit_reg_info = acpi_hw_get_bit_register_info(register_id); if (!bit_reg_info) { - ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X", - register_id)); return_ACPI_STATUS(AE_BAD_PARAMETER); } lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock); - /* Always do a register read first so we can insert the new bits */ - - status = acpi_hw_register_read(bit_reg_info->parent_register, - ®ister_value); - if (ACPI_FAILURE(status)) { - goto unlock_and_exit; - } - /* - * Decode the Register ID - * Register ID = [Register block ID] | [bit ID] - * - * Check bit ID to fine locate Register offset. - * Check Mask to determine Register offset, and then read-write. + * At this point, we know that the parent register is one of the + * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control */ - switch (bit_reg_info->parent_register) { - case ACPI_REGISTER_PM1_STATUS: - + if (bit_reg_info->parent_register != ACPI_REGISTER_PM1_STATUS) { /* - * Status Registers are different from the rest. Clear by - * writing 1, and writing 0 has no effect. So, the only relevant - * information is the single bit we're interested in, all others should - * be written as 0 so they will be left unchanged. + * 1) Case for PM1 Enable, PM1 Control, and PM2 Control + * + * Perform a register read to preserve the bits that we are not + * interested in */ - value = ACPI_REGISTER_PREPARE_BITS(value, - bit_reg_info->bit_position, - bit_reg_info-> - access_bit_mask); - if (value) { - status = - acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, - (u16) value); - register_value = 0; - } - break; - - case ACPI_REGISTER_PM1_ENABLE: - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_ENABLE, - (u16) register_value); - break; - - case ACPI_REGISTER_PM1_CONTROL: - - /* - * Write the PM1 Control register. - * Note that at this level, the fact that there are actually TWO - * registers (A and B - and B may not exist) is abstracted. - */ - ACPI_DEBUG_PRINT((ACPI_DB_IO, "PM1 control: Read %X\n", - register_value)); - - ACPI_REGISTER_INSERT_VALUE(register_value, - bit_reg_info->bit_position, - bit_reg_info->access_bit_mask, - value); - - status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL, - (u16) register_value); - break; - - case ACPI_REGISTER_PM2_CONTROL: - - status = acpi_hw_register_read(ACPI_REGISTER_PM2_CONTROL, + status = acpi_hw_register_read(bit_reg_info->parent_register, ®ister_value); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "PM2 control: Read %X from %8.8X%8.8X\n", - register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); - + /* + * Insert the input bit into the value that was just read + * and write the register + */ ACPI_REGISTER_INSERT_VALUE(register_value, bit_reg_info->bit_position, bit_reg_info->access_bit_mask, value); - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "About to write %4.4X to %8.8X%8.8X\n", - register_value, - ACPI_FORMAT_UINT64(acpi_gbl_FADT. - xpm2_control_block. - address))); + status = acpi_hw_register_write(bit_reg_info->parent_register, + register_value); + } else { + /* + * 2) Case for PM1 Status + * + * The Status register is different from the rest. Clear an event + * by writing 1, writing 0 has no effect. So, the only relevant + * information is the single bit we're interested in, all others + * should be written as 0 so they will be left unchanged. + */ + register_value = ACPI_REGISTER_PREPARE_BITS(value, + bit_reg_info-> + bit_position, + bit_reg_info-> + access_bit_mask); - status = acpi_hw_register_write(ACPI_REGISTER_PM2_CONTROL, - (u8) (register_value)); - break; + /* No need to write the register if value is all zeros */ - default: - break; + if (register_value) { + status = + acpi_hw_register_write(ACPI_REGISTER_PM1_STATUS, + register_value); + } } - unlock_and_exit: + ACPI_DEBUG_PRINT((ACPI_DB_IO, + "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n", + register_id, bit_reg_info->parent_register, value, + register_value)); + +unlock_and_exit: acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags); - - /* Normalize the value that was read */ - - ACPI_DEBUG_EXEC(register_value = - ((register_value & bit_reg_info->access_bit_mask) >> - bit_reg_info->bit_position)); - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Set bits: %8.8X actual %8.8X register %X\n", value, - register_value, bit_reg_info->parent_register)); return_ACPI_STATUS(status); } From b6bc342dd543f40b6feccbaf6719d9f836c9964a Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Feb 2009 10:26:19 +0800 Subject: [PATCH 036/140] ACPICA: Update table header print function Cleanup table header output. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbutils.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index dc45b49e5cb9..ef7d2c2d8f0b 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -177,19 +177,23 @@ acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header *header) { + /* + * The reason that the Address is cast to a void pointer is so that we + * can use %p which will work properly on both 32-bit and 64-bit hosts. + */ if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { - /* FACS only has signature and length fields of common table header */ + /* FACS only has signature and length fields */ - ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X", - header->signature, (unsigned long)address, + ACPI_INFO((AE_INFO, "%4.4s %p %05X", + header->signature, ACPI_CAST_PTR(void, address), header->length)); } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { /* RSDP has no common fields */ - ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)", - (unsigned long)address, + ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", + ACPI_CAST_PTR (void, address), (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> revision > 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, @@ -202,8 +206,8 @@ acpi_tb_print_table_header(acpi_physical_address address, /* Standard ACPI table with full common header */ ACPI_INFO((AE_INFO, - "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)", - header->signature, (unsigned long)address, + "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", + header->signature, ACPI_CAST_PTR (void, address), header->length, header->revision, header->oem_id, header->oem_table_id, header->oem_revision, header->asl_compiler_id, From 2affa28605fa5387192c72d9889a00c9c51aa712 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Feb 2009 10:27:07 +0800 Subject: [PATCH 037/140] ACPICA: Update version to 20090220 Version 20090220. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index a5525a5518a9..666182b5ca31 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20090123 +#define ACPI_CA_VERSION 0x20090220 #include "actypes.h" #include "actbl.h" From 768aaaf196e8a40f5cfc792d9d365795cc52ed13 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 6 Mar 2009 09:49:25 +0800 Subject: [PATCH 038/140] ACPICA: Add manifest constants for bit register values Add and deploy constants for the PM status/enable/control registers. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/evevent.c | 12 +++++++----- drivers/acpi/acpica/evmisc.c | 3 ++- drivers/acpi/acpica/evxfevnt.c | 6 +++--- drivers/acpi/acpica/hwsleep.c | 14 ++++++++++---- include/acpi/actypes.h | 9 +++++++++ 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index 246f8775ec13..cd55c774e882 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -183,7 +183,7 @@ acpi_status acpi_ev_install_xrupt_handlers(void) * * RETURN: Status * - * DESCRIPTION: Install the fixed event handlers and enable the fixed events. + * DESCRIPTION: Install the fixed event handlers and disable all fixed events. * ******************************************************************************/ @@ -200,12 +200,13 @@ static acpi_status acpi_ev_fixed_event_initialize(void) acpi_gbl_fixed_event_handlers[i].handler = NULL; acpi_gbl_fixed_event_handlers[i].context = NULL; - /* Enable the fixed event */ + /* Disable the fixed event */ if (acpi_gbl_fixed_event_info[i].enable_register_id != 0xFF) { status = acpi_write_bit_register(acpi_gbl_fixed_event_info - [i].enable_register_id, 0); + [i].enable_register_id, + ACPI_DISABLE_EVENT); if (ACPI_FAILURE(status)) { return (status); } @@ -289,7 +290,7 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) /* Clear the status bit */ (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + status_register_id, ACPI_CLEAR_STATUS); /* * Make sure we've got a handler. If not, report an error. The event is @@ -297,7 +298,8 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event) */ if (NULL == acpi_gbl_fixed_event_handlers[event].handler) { (void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + enable_register_id, + ACPI_DISABLE_EVENT); ACPI_ERROR((AE_INFO, "No installed handler for fixed event [%08X]", diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 0e9e12b2f2bb..417a9b920dd3 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -535,7 +535,8 @@ acpi_status acpi_ev_release_global_lock(void) if (pending) { status = acpi_write_bit_register - (ACPI_BITREG_GLOBAL_LOCK_RELEASE, 1); + (ACPI_BITREG_GLOBAL_LOCK_RELEASE, + ACPI_ENABLE_EVENT); } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 484c9793ca06..d0a080747ec3 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -173,7 +173,7 @@ acpi_status acpi_enable_event(u32 event, u32 flags) */ status = acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 1); + enable_register_id, ACPI_ENABLE_EVENT); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -355,7 +355,7 @@ acpi_status acpi_disable_event(u32 event, u32 flags) */ status = acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. - enable_register_id, 0); + enable_register_id, ACPI_DISABLE_EVENT); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -408,7 +408,7 @@ acpi_status acpi_clear_event(u32 event) */ status = acpi_write_bit_register(acpi_gbl_fixed_event_info[event]. - status_register_id, 1); + status_register_id, ACPI_CLEAR_STATUS); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 78d62b8a5c31..4d14b49a0f6c 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -250,7 +250,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) /* Clear wake status */ - status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); + status = + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -399,7 +400,10 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios); - status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, 1); + /* Clear the wake status bit (PM1) */ + + status = + acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -601,11 +605,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) (void) acpi_write_bit_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1); + [ACPI_EVENT_POWER_BUTTON]. + enable_register_id, ACPI_ENABLE_EVENT); (void) acpi_write_bit_register(acpi_gbl_fixed_event_info - [ACPI_EVENT_POWER_BUTTON].status_register_id, 1); + [ACPI_EVENT_POWER_BUTTON]. + status_register_id, ACPI_CLEAR_STATUS); arg.integer.value = ACPI_SST_WORKING; status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL); diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 1b9601c665e6..f555d927f7c0 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -787,6 +787,15 @@ typedef u8 acpi_adr_space_type; #define ACPI_BITREG_MAX 0x13 #define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1 +/* Status register values. A 1 clears a status bit. 0 = no effect */ + +#define ACPI_CLEAR_STATUS 1 + +/* Enable and Control register values */ + +#define ACPI_ENABLE_EVENT 1 +#define ACPI_DISABLE_EVENT 0 + /* * External ACPI object definition */ From d4913dc6d0c680aa106d1d80b5ad2a9325367afd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 6 Mar 2009 10:05:18 +0800 Subject: [PATCH 039/140] ACPICA: Formatting update - no functional changes Split long lines, update comments. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/evgpe.c | 7 ++-- drivers/acpi/acpica/evgpeblk.c | 64 ++++++++++++++++------------------ drivers/acpi/acpica/evmisc.c | 11 +++--- drivers/acpi/acpica/evregion.c | 3 +- drivers/acpi/acpica/evrgnini.c | 22 ++++++------ drivers/acpi/acpica/evxface.c | 3 +- drivers/acpi/acpica/evxfregn.c | 3 +- drivers/acpi/acpica/hwacpi.c | 3 +- drivers/acpi/acpica/hwgpe.c | 21 +++++------ drivers/acpi/acpica/hwsleep.c | 14 ++++---- drivers/acpi/acpica/hwxface.c | 3 +- drivers/acpi/acpica/nsaccess.c | 51 +++++++++++++-------------- drivers/acpi/acpica/nsalloc.c | 24 +++++-------- drivers/acpi/acpica/nsdump.c | 16 ++++----- drivers/acpi/acpica/nsinit.c | 19 +++++----- drivers/acpi/acpica/nsload.c | 4 +-- drivers/acpi/acpica/nsparse.c | 10 +++--- drivers/acpi/acpica/nspredef.c | 6 ++-- drivers/acpi/acpica/nssearch.c | 14 ++++---- drivers/acpi/acpica/nsutils.c | 25 +++++++------ drivers/acpi/acpica/nswalk.c | 12 +++---- 21 files changed, 161 insertions(+), 174 deletions(-) diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index f345ced36477..b9d8ee69ca6c 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -88,10 +88,10 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type) status = acpi_ev_disable_gpe(gpe_event_info); - /* Type was validated above */ + /* Clear the type bits and insert the new Type */ - gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */ - gpe_event_info->flags |= type; /* Insert type */ + gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK; + gpe_event_info->flags |= type; return_ACPI_STATUS(status); } @@ -122,6 +122,7 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, if (!gpe_register_info) { return_ACPI_STATUS(AE_NOT_EXIST); } + register_bit = (u8) (1 << (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index f7b3d2af9401..7b3463639422 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -104,9 +104,9 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) while (gpe_block) { if ((&gpe_block->event_info[0] <= gpe_event_info) && - (&gpe_block-> - event_info[((acpi_size) gpe_block-> - register_count) * 8] > + (&gpe_block->event_info[((acpi_size) + gpe_block-> + register_count) * 8] > gpe_event_info)) { return (TRUE); } @@ -210,10 +210,9 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { - gpe_event_info = - &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + gpe_event_info = &gpe_block->event_info[((acpi_size) i * + ACPI_GPE_REGISTER_WIDTH) + + j]; if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { @@ -293,8 +292,8 @@ acpi_ev_save_method_info(acpi_handle obj_handle, /* Unknown method type, just ignore it! */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)", - name)); + "Ignoring unknown GPE method type: %s " + "(name not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } @@ -306,17 +305,16 @@ acpi_ev_save_method_info(acpi_handle obj_handle, /* Conversion failed; invalid method, just ignore it */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, - "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", - name)); + "Could not extract GPE number from name: %s " + "(name is not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ if ((gpe_number < gpe_block->block_base_number) || - (gpe_number >= - (gpe_block->block_base_number + - (gpe_block->register_count * 8)))) { + (gpe_number >= (gpe_block->block_base_number + + (gpe_block->register_count * 8)))) { /* * Not valid for this GPE block, just ignore it. However, it may be * valid for a different GPE block, since GPE0 and GPE1 methods both @@ -423,9 +421,9 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, if ((obj_desc->package.count < 2) || ((obj_desc->package.elements[0])->common.type != - ACPI_TYPE_LOCAL_REFERENCE) - || ((obj_desc->package.elements[1])->common.type != - ACPI_TYPE_INTEGER)) { + ACPI_TYPE_LOCAL_REFERENCE) || + ((obj_desc->package.elements[1])->common.type != + ACPI_TYPE_INTEGER)) { goto cleanup; } @@ -450,11 +448,11 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, */ if ((gpe_device == target_gpe_device) && (gpe_number >= gpe_block->block_base_number) && - (gpe_number < - gpe_block->block_base_number + (gpe_block->register_count * 8))) { - gpe_event_info = - &gpe_block->event_info[gpe_number - - gpe_block->block_base_number]; + (gpe_number < gpe_block->block_base_number + + (gpe_block->register_count * 8))) { + gpe_event_info = &gpe_block->event_info[gpe_number - + gpe_block-> + block_base_number]; /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ @@ -1033,8 +1031,8 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, * 1) are "runtime" or "run/wake" GPEs, and * 2) have a corresponding _Lxx or _Exx method * - * Any other GPEs within this block must be enabled via the acpi_enable_gpe() - * external interface. + * Any other GPEs within this block must be enabled via the + * acpi_enable_gpe() external interface. */ wake_gpe_count = 0; gpe_enabled_count = 0; @@ -1044,14 +1042,13 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, /* Get the info block for this particular GPE */ - gpe_event_info = - &gpe_block-> - event_info[((acpi_size) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + gpe_event_info = &gpe_block->event_info[((acpi_size) i * + ACPI_GPE_REGISTER_WIDTH) + + j]; if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_METHOD) - && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { + ACPI_GPE_DISPATCH_METHOD) && + (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) { gpe_enabled_count++; } @@ -1105,8 +1102,8 @@ acpi_status acpi_ev_gpe_initialize(void) /* * Initialize the GPE Block(s) defined in the FADT * - * Why the GPE register block lengths are divided by 2: From the ACPI Spec, - * section "General-Purpose Event Registers", we have: + * Why the GPE register block lengths are divided by 2: From the ACPI + * Spec, section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the @@ -1163,7 +1160,8 @@ acpi_status acpi_ev_gpe_initialize(void) if ((register_count0) && (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) { ACPI_ERROR((AE_INFO, - "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", + "GPE0 block (GPE 0 to %d) overlaps the GPE1 block " + "(GPE %d to %d) - Ignoring GPE1", gpe_number_max, acpi_gbl_FADT.gpe1_base, acpi_gbl_FADT.gpe1_base + ((register_count1 * diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 417a9b920dd3..ce224e1eaa89 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -163,10 +163,10 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, * 2) Global device notify handler * 3) Per-device notify handler */ - if ((acpi_gbl_system_notify.handler - && (notify_value <= ACPI_MAX_SYS_NOTIFY)) - || (acpi_gbl_device_notify.handler - && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { + if ((acpi_gbl_system_notify.handler && + (notify_value <= ACPI_MAX_SYS_NOTIFY)) || + (acpi_gbl_device_notify.handler && + (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state(); if (!notify_info) { return (AE_NO_MEMORY); @@ -174,7 +174,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, if (!handler_obj) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Executing system notify handler for Notify (%4.4s, %X) node %p\n", + "Executing system notify handler for Notify (%4.4s, %X) " + "node %p\n", acpi_ut_get_node_name(node), notify_value, node)); } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 86cbbdbfc5cd..538d63264555 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -703,7 +703,8 @@ acpi_ev_install_handler(acpi_handle obj_handle, if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) { ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Found handler for region [%s] in device %p(%p) handler %p\n", + "Found handler for region [%s] in device %p(%p) " + "handler %p\n", acpi_ut_get_region_name (handler_obj->address_space. space_id), obj_desc, diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index f3f1fb45c3dc..284a7becbe96 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -241,7 +241,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, status = AE_OK; } else { ACPI_EXCEPTION((AE_INFO, status, - "Could not install PciConfig handler for Root Bridge %4.4s", + "Could not install PciConfig handler " + "for Root Bridge %4.4s", acpi_ut_get_node_name (pci_root_node))); } @@ -293,9 +294,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, * Get the PCI device and function numbers from the _ADR object contained * in the parent's scope. */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, - &pci_value); + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, + pci_device_node, &pci_value); /* * The default is zero, and since the allocation above zeroed the data, @@ -308,18 +308,16 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, /* The PCI segment number comes from the _SEG method */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, - &pci_value); + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, + pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->segment = ACPI_LOWORD(pci_value); } /* The PCI bus number comes from the _BBN method */ - status = - acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, - &pci_value); + status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, + pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->bus = ACPI_LOWORD(pci_value); } @@ -632,8 +630,8 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, acpi_ns_locked); /* - * Tell all users that this region is usable by running the _REG - * method + * Tell all users that this region is usable by + * running the _REG method */ if (acpi_ns_locked) { status = diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 3aca9010a11e..10b8543dd466 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -631,7 +631,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device, /* Setup up dispatch flags to indicate handler (vs. method) */ - gpe_event_info->flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ + gpe_event_info->flags &= + ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER); acpi_os_release_lock(acpi_gbl_gpe_lock, flags); diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 479e7a3721be..7c3d2d356ffb 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -193,7 +193,8 @@ acpi_remove_address_space_handler(acpi_handle device, /* Matched space_id, first dereference this in the Regions */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, - "Removing address handler %p(%p) for region %s on Device %p(%p)\n", + "Removing address handler %p(%p) for region %s " + "on Device %p(%p)\n", handler_obj, handler, acpi_ut_get_region_name(space_id), node, obj_desc)); diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index 8902db8c670f..e7949b133365 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -86,7 +86,8 @@ acpi_status acpi_hw_set_mode(u32 mode) */ if (!acpi_gbl_FADT.acpi_enable && !acpi_gbl_FADT.acpi_disable) { ACPI_ERROR((AE_INFO, - "No ACPI mode transition supported in this system (enable/disable both zero)")); + "No ACPI mode transition supported in this system " + "(enable/disable both zero)")); return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 2013b66745d2..d3b7e37c9eed 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -89,10 +89,9 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) /* Clear just the bit that corresponds to this GPE */ - ACPI_CLEAR_BIT(enable_mask, - ((u32) 1 << - (gpe_event_info->gpe_number - - gpe_register_info->base_gpe_number))); + ACPI_CLEAR_BIT(enable_mask, ((u32)1 << + (gpe_event_info->gpe_number - + gpe_register_info->base_gpe_number))); /* Write the updated enable mask */ @@ -156,10 +155,9 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) ACPI_FUNCTION_ENTRY(); - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + register_bit = (u8)(1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); /* * Write a one to the appropriate bit in the status register to @@ -206,10 +204,9 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* Get the register bitmask for this GPE */ - register_bit = (u8) - (1 << - (gpe_event_info->gpe_number - - gpe_event_info->register_info->base_gpe_number)); + register_bit = (u8)(1 << + (gpe_event_info->gpe_number - + gpe_event_info->register_info->base_gpe_number)); /* GPE currently enabled? (enabled for runtime?) */ diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 4d14b49a0f6c..2ea4c59e8838 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -349,8 +349,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) * Wait ten seconds, then try again. This is to get S4/S5 to work on * all machines. * - * We wait so long to allow chipsets that poll this reg very slowly to - * still read the right value. Ideally, this block would go + * We wait so long to allow chipsets that poll this reg very slowly + * to still read the right value. Ideally, this block would go * away entirely. */ acpi_os_stall(10000000); @@ -501,12 +501,10 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state) /* Insert the SLP_TYP bits */ - pm1a_control |= - (acpi_gbl_sleep_type_a << sleep_type_reg_info-> - bit_position); - pm1b_control |= - (acpi_gbl_sleep_type_b << sleep_type_reg_info-> - bit_position); + pm1a_control |= (acpi_gbl_sleep_type_a << + sleep_type_reg_info->bit_position); + pm1b_control |= (acpi_gbl_sleep_type_b << + sleep_type_reg_info->bit_position); /* Write the control registers and ignore any errors */ diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index caad51680bd6..26e66427f4ff 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -494,7 +494,8 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) ((info->return_object->package.elements[1])->common.type != ACPI_TYPE_INTEGER)) { ACPI_ERROR((AE_INFO, - "Sleep State return package elements are not both Integers (%s, %s)", + "Sleep State return package elements are not both Integers " + "(%s, %s)", acpi_ut_get_object_type_name(info->return_object-> package.elements[0]), acpi_ut_get_object_type_name(info->return_object-> diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index b6968a65cd4f..9c3cdbe2d82a 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -118,9 +118,8 @@ acpi_status acpi_ns_root_initialize(void) } /* - * Name entered successfully. - * If entry in pre_defined_names[] specifies an - * initial value, create the initial value. + * Name entered successfully. If entry in pre_defined_names[] specifies + * an initial value, create the initial value. */ if (init_val->val) { status = acpi_os_predefined_override(init_val, &val); @@ -178,9 +177,8 @@ acpi_status acpi_ns_root_initialize(void) case ACPI_TYPE_STRING: - /* - * Build an object around the static string - */ + /* Build an object around the static string */ + obj_desc->string.length = (u32) ACPI_STRLEN(val); obj_desc->string.pointer = val; @@ -314,10 +312,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, return_ACPI_STATUS(AE_NO_NAMESPACE); } - /* - * Get the prefix scope. - * A null scope means use the root scope - */ + /* Get the prefix scope. A null scope means use the root scope */ + if ((!scope_info) || (!scope_info->scope.node)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", @@ -337,8 +333,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { /* * This node might not be a actual "scope" node (such as a - * Device/Method, etc.) It could be a Package or other object node. - * Backup up the tree to find the containing scope node. + * Device/Method, etc.) It could be a Package or other object + * node. Backup up the tree to find the containing scope node. */ while (!acpi_ns_opens_scope(prefix_node->type) && prefix_node->type != ACPI_TYPE_ANY) { @@ -348,7 +344,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, } } - /* Save type TBD: may be no longer necessary */ + /* Save type. TBD: may be no longer necessary */ type_to_check_for = type; @@ -413,6 +409,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Name is fully qualified, no search rules apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; + /* * Point past this prefix to the name segment * part or the next Parent Prefix @@ -428,7 +425,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, - "ACPI path has too many parent prefixes (^) - reached beyond root node")); + "ACPI path has too many parent prefixes (^) " + "- reached beyond root node")); return_ACPI_STATUS(AE_NOT_FOUND); } } @@ -530,9 +528,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, while (num_segments && current_node) { num_segments--; if (!num_segments) { - /* - * This is the last segment, enable typechecking - */ + + /* This is the last segment, enable typechecking */ + this_search_type = type; /* @@ -583,9 +581,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, if (num_segments > 0) { /* * If we have an alias to an object that opens a scope (such as a - * device or processor), we need to dereference the alias here so that - * we can access any children of the original node (via the remaining - * segments). + * device or processor), we need to dereference the alias here so + * that we can access any children of the original node (via the + * remaining segments). */ if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { if (!this_node->object) { @@ -593,8 +591,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, } if (acpi_ns_opens_scope - (((struct acpi_namespace_node *)this_node-> - object)->type)) { + (((struct acpi_namespace_node *) + this_node->object)->type)) { this_node = (struct acpi_namespace_node *) this_node->object; @@ -638,8 +636,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, /* * If this is the last name segment and we are not looking for a - * specific type, but the type of found object is known, use that type - * to (later) see if it opens a scope. + * specific type, but the type of found object is known, use that + * type to (later) see if it opens a scope. */ if (type == ACPI_TYPE_ANY) { type = this_node->type; @@ -652,9 +650,8 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, current_node = this_node; } - /* - * Always check if we need to open a new scope - */ + /* Always check if we need to open a new scope */ + if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) { /* * If entry is a type which opens a scope, push the new scope on the diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index f976d848fe82..aceb93111967 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -76,8 +76,7 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++); #ifdef ACPI_DBG_TRACK_ALLOCATIONS - temp = - acpi_gbl_ns_node_list->total_allocated - + temp = acpi_gbl_ns_node_list->total_allocated - acpi_gbl_ns_node_list->total_freed; if (temp > acpi_gbl_ns_node_list->max_occupied) { acpi_gbl_ns_node_list->max_occupied = temp; @@ -145,9 +144,8 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node) ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); - /* - * Detach an object if there is one, then delete the node - */ + /* Detach an object if there is one, then delete the node */ + acpi_ns_detach_object(node); (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); return_VOID; @@ -183,9 +181,8 @@ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namesp ACPI_FUNCTION_TRACE(ns_install_node); /* - * Get the owner ID from the Walk state - * The owner ID is used to track table deletion and - * deletion of objects created by methods + * Get the owner ID from the Walk state. The owner ID is used to track + * table deletion and deletion of objects created by methods. */ if (walk_state) { owner_id = walk_state->owner_id; @@ -260,9 +257,8 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) return_VOID; } - /* - * Deallocate all children at this level - */ + /* Deallocate all children at this level */ + do { /* Get the things we need */ @@ -285,9 +281,8 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) "Object %p, Remaining %X\n", child_node, acpi_gbl_current_node_count)); - /* - * Detach an object if there is one, then free the child node - */ + /* Detach an object if there is one, then free the child node */ + acpi_ns_detach_object(child_node); /* Now we can delete the node */ @@ -304,7 +299,6 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) /* Clear the parent's child pointer */ parent_node->child = NULL; - return_VOID; } diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 7bfa6c1286f1..2bad613db73a 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -220,9 +220,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node)); } - /* - * Now we can print out the pertinent information - */ + /* Now we can print out the pertinent information */ + acpi_os_printf(" %-12s %p %2.2X ", acpi_ut_get_type_name(type), this_node, this_node->owner_id); @@ -545,9 +544,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, goto cleanup; } - /* - * Valid object, get the pointer to next level, if any - */ + /* Valid object, get the pointer to next level, if any */ + switch (obj_type) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: @@ -608,14 +606,14 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, * display_type - 0 or ACPI_DISPLAY_SUMMARY * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX * for an effectively unlimited depth. - * owner_id - Dump only objects owned by this ID. Use + * owner_id - Dump only objects owned by this ID. Use * ACPI_UINT32_MAX to match all owners. * start_handle - Where in namespace to start/end search * * RETURN: None * - * DESCRIPTION: Dump typed objects within the loaded namespace. - * Uses acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object. + * DESCRIPTION: Dump typed objects within the loaded namespace. Uses + * acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object. * ******************************************************************************/ diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 13501cb81863..2adfcf329e15 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -103,7 +103,8 @@ acpi_status acpi_ns_initialize_objects(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n", + "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd " + "Buffers %hd/%hd Packages (%hd nodes)\n", info.op_region_init, info.op_region_count, info.field_init, info.field_count, info.buffer_init, info.buffer_count, @@ -148,7 +149,8 @@ acpi_status acpi_ns_initialize_devices(void) info.num_INI = 0; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "Initializing Device/Processor/Thermal objects by executing _INI methods:")); + "Initializing Device/Processor/Thermal objects " + "by executing _INI methods:")); /* Tree analysis: find all subtrees that contain _INI methods */ @@ -180,7 +182,8 @@ acpi_status acpi_ns_initialize_devices(void) } ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, - "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n", + "\nExecuted %hd _INI methods requiring %hd _STA executions " + "(examined %hd objects)\n", info.num_INI, info.num_STA, info.device_count)); return_ACPI_STATUS(status); @@ -263,16 +266,14 @@ acpi_ns_init_one_object(acpi_handle obj_handle, return (AE_OK); } - /* - * If the object is already initialized, nothing else to do - */ + /* If the object is already initialized, nothing else to do */ + if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } - /* - * Must lock the interpreter before executing AML code - */ + /* Must lock the interpreter before executing AML code */ + acpi_ex_enter_interpreter(); /* diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index a0ba9e12379e..dcd7a6adbbbc 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -128,12 +128,12 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) * parse trees. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Begin Table Method Parsing and Object Initialization ****\n")); + "**** Begin Table Method Parsing and Object Initialization\n")); status = acpi_ds_initialize_objects(table_index, node); ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "**** Completed Table Method Parsing and Object Initialization ****\n")); + "**** Completed Table Method Parsing and Object Initialization\n")); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index b9e8d0070b6f..662a4bd5b621 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -176,9 +176,8 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) * performs another complete parse of the AML. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); - status = - acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, - start_node); + status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, + table_index, start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -193,9 +192,8 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) * parse objects are all cached. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); - status = - acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, - start_node); + status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, + table_index, start_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 72dd7b198520..0d0b4ee1358e 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -302,7 +302,8 @@ acpi_ns_check_parameter_count(char *pathname, if ((user_param_count != required_params_current) && (user_param_count != required_params_old)) { ACPI_WARNING((AE_INFO, - "%s: Parameter count mismatch - caller passed %d, ACPI requires %d", + "%s: Parameter count mismatch - " + "caller passed %d, ACPI requires %d", pathname, user_param_count, required_params_current)); } @@ -974,7 +975,8 @@ acpi_ns_check_reference(char *pathname, } ACPI_WARNING((AE_INFO, - "%s: Return type mismatch - unexpected reference object type [%s] %2.2X", + "%s: Return type mismatch - " + "unexpected reference object type [%s] %2.2X", pathname, acpi_ut_get_reference_name(return_object), return_object->reference.class)); diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index 6fea13f3f52d..f9b4f51bf8f2 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -167,7 +167,8 @@ acpi_ns_search_one_scope(u32 target_name, /* Searched entire namespace level, not found */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, - "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n", + "Name [%4.4s] (%s) not found in search in scope [%4.4s] " + "%p first child %p\n", ACPI_CAST_PTR(char, &target_name), acpi_ut_get_type_name(type), acpi_ut_get_node_name(parent_node), parent_node, @@ -239,9 +240,8 @@ acpi_ns_search_parent_tree(u32 target_name, acpi_ut_get_node_name(parent_node), ACPI_CAST_PTR(char, &target_name))); - /* - * Search parents until target is found or we have backed up to the root - */ + /* Search parents until target is found or we have backed up to the root */ + while (parent_node) { /* * Search parent scope. Use TYPE_ANY because we don't care about the @@ -395,9 +395,9 @@ acpi_ns_search_and_enter(u32 target_name, return_ACPI_STATUS(AE_NO_MEMORY); } #ifdef ACPI_ASL_COMPILER - /* - * Node is an object defined by an External() statement - */ + + /* Node is an object defined by an External() statement */ + if (flags & ACPI_NS_EXTERNAL) { new_node->flags |= ANOBJ_IS_EXTERNAL; } diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index d30b0e65ab3c..78277ed08339 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -325,9 +325,8 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) next_external_char++; } } else { - /* - * Handle Carat prefixes - */ + /* Handle Carat prefixes */ + while (*next_external_char == '^') { info->num_carats++; next_external_char++; @@ -552,9 +551,8 @@ acpi_ns_externalize_name(u32 internal_name_length, return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* - * Check for a prefix (one '\' | one or more '^'). - */ + /* Check for a prefix (one '\' | one or more '^') */ + switch (internal_name[0]) { case '\\': prefix_length = 1; @@ -580,7 +578,7 @@ acpi_ns_externalize_name(u32 internal_name_length, } /* - * Check for object names. Note that there could be 0-255 of these + * Check for object names. Note that there could be 0-255 of these * 4-byte elements. */ if (prefix_length < internal_name_length) { @@ -637,9 +635,8 @@ acpi_ns_externalize_name(u32 internal_name_length, return_ACPI_STATUS(AE_BAD_PATHNAME); } - /* - * Build converted_name - */ + /* Build the converted_name */ + *converted_name = ACPI_ALLOCATE_ZEROED(required_length); if (!(*converted_name)) { return_ACPI_STATUS(AE_NO_MEMORY); @@ -685,6 +682,9 @@ acpi_ns_externalize_name(u32 internal_name_length, * and keep all pointers within this subsystem - however this introduces * more (and perhaps unnecessary) overhead. * + * The current implemenation is basically a placeholder until such time comes + * that it is needed. + * ******************************************************************************/ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) @@ -692,9 +692,8 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) ACPI_FUNCTION_ENTRY(); - /* - * Simple implementation - */ + /* Parameter validation */ + if ((!handle) || (handle == ACPI_ROOT_OBJECT)) { return (acpi_gbl_root_node); } diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 200895fa2728..83e3aa6d4b9b 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -135,8 +135,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct * starting (and ending) at the node specified by start_handle. * The user_function is called whenever a node that matches * the type parameter is found. If the user function returns - * a non-zero value, the search is terminated immediately and this - * value is returned to the caller. + * a non-zero value, the search is terminated immediately and + * this value is returned to the caller. * * The point of this procedure is to provide a generic namespace * walk routine that can be called from multiple places to @@ -200,10 +200,10 @@ acpi_ns_walk_namespace(acpi_object_type type, /* * Ignore all temporary namespace nodes (created during control * method execution) unless told otherwise. These temporary nodes - * can cause a race condition because they can be deleted during the - * execution of the user function (if the namespace is unlocked before - * invocation of the user function.) Only the debugger namespace dump - * will examine the temporary nodes. + * can cause a race condition because they can be deleted during + * the execution of the user function (if the namespace is + * unlocked before invocation of the user function.) Only the + * debugger namespace dump will examine the temporary nodes. */ if ((child_node->flags & ANOBJ_TEMPORARY) && !(flags & ACPI_NS_WALK_TEMP_NODES)) { From aab61b676a024d3527f6201e2b31285a96f7a1d2 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 6 Mar 2009 10:09:00 +0800 Subject: [PATCH 040/140] ACPICA: FADT: Fix extraneous length mismatch warning Incorrect register length mismatch between the 32 and 64 bit registers in some cases. Code was was checking the wrong pointer for non-zero, should be looking at the address within the GAS structure. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index af8fbe12d8b7..ff89cfee0e7e 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -491,7 +491,8 @@ static void acpi_tb_validate_fadt(void) * For each extended field, check for length mismatch between the * legacy length field and the corresponding 64-bit X length field. */ - if (address64 && (address64->bit_width != ACPI_MUL_8(length))) { + if (address64->address && + (address64->bit_width != ACPI_MUL_8(length))) { ACPI_WARNING((AE_INFO, "32/64X length mismatch in %s: %d/%d", name, ACPI_MUL_8(length), From 8a335a2331c72e60c6b3ef09b2dedd3ba00da1b1 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 9 Mar 2009 16:31:04 +0800 Subject: [PATCH 041/140] ACPICA: Fix AcpiWalkNamespace race condition with table unload Added a reader/writer locking mechanism to allow multiple concurrent namespace walks (readers), but a dynamic table unload will have exclusive access to the namespace. This fixes a problem where a table unload could delete the portion of the namespace that is currently being examined by a walk. Adds a new file, utlock.c that implements the reader/writer lock mechanism. ACPICA BZ 749. http://www.acpica.org/bugzilla/show_bug.cgi?id=749 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/Makefile | 2 +- drivers/acpi/acpica/acglobal.h | 4 + drivers/acpi/acpica/aclocal.h | 8 ++ drivers/acpi/acpica/actables.h | 2 +- drivers/acpi/acpica/acutils.h | 15 +++ drivers/acpi/acpica/dsinit.c | 16 ++- drivers/acpi/acpica/exconfig.c | 13 +-- drivers/acpi/acpica/nsxfeval.c | 33 +++++-- drivers/acpi/acpica/tbinstal.c | 47 +++++++-- drivers/acpi/acpica/utlock.c | 175 +++++++++++++++++++++++++++++++++ drivers/acpi/acpica/utmutex.c | 23 +++-- 11 files changed, 304 insertions(+), 34 deletions(-) create mode 100644 drivers/acpi/acpica/utlock.c diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 3f23298ee3fd..290be74b774d 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -41,4 +41,4 @@ obj-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o obj-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ - utstate.o utmutex.o utobject.o utresrc.o + utstate.o utmutex.o utobject.o utresrc.o utlock.o diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index f3e87ba43dbe..f431b997d2f8 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -165,6 +165,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width; ACPI_EXTERN u8 acpi_gbl_integer_byte_width; ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock; + /***************************************************************************** * * Mutual exlusion within ACPICA subsystem diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 6feebc8f789a..18a8d96eaa49 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -108,6 +108,14 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { #endif #endif +/* Lock structure for reader/writer interfaces */ + +struct acpi_rw_lock { + acpi_mutex writer_mutex; + acpi_mutex reader_mutex; + u32 num_readers; +}; + /* * Predefined handles for spinlocks used within the subsystem. * These spinlocks are created by acpi_ut_mutex_initialize diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index d8f8c5df4fbc..01c76b8ea7ba 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -79,7 +79,7 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc); void acpi_tb_terminate(void); -void acpi_tb_delete_namespace_by_owner(u32 table_index); +acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index); acpi_status acpi_tb_allocate_owner_id(u32 table_index); diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 80d8813484fe..897810ba0ccc 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -345,6 +345,21 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node, acpi_status acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest); +/* + * utlock - reader/writer locks + */ +acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock); + +void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock); + +acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock); + +acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock); + +acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock); + +void acpi_ut_release_write_lock(struct acpi_rw_lock *lock); + /* * utobject - internal object create/delete/cache routines */ diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index eb144b13d8fa..3aae13f30c5e 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -180,11 +180,23 @@ acpi_ds_initialize_objects(u32 table_index, /* Walk entire namespace from the supplied root */ - status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, - acpi_ds_init_one_object, &info, NULL); + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * We don't use acpi_walk_namespace since we do not want to acquire + * the namespace reader lock. + */ + status = + acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ds_init_one_object, + &info, NULL); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); } + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); status = acpi_get_table_by_index(table_index, &table); if (ACPI_FAILURE(status)) { diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 70b39c7daeab..3deb20a126b2 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -520,13 +520,14 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) } } - /* - * Delete the entire namespace under this table Node - * (Offset contains the table_id) - */ - acpi_tb_delete_namespace_by_owner(table_index); - (void)acpi_tb_release_owner_id(table_index); + /* Delete the portion of the namespace owned by this table */ + status = acpi_tb_delete_namespace_by_owner(table_index); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + (void)acpi_tb_release_owner_id(table_index); acpi_tb_set_table_loaded_flag(table_index, FALSE); /* Table unloaded, remove a reference to the ddb_handle object */ diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 2583a66a60a7..045054037c2d 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -475,21 +475,40 @@ acpi_walk_namespace(acpi_object_type type, } /* - * Lock the namespace around the walk. - * The namespace will be unlocked/locked around each call - * to the user function - since this function - * must be allowed to make Acpi calls itself. + * Need to acquire the namespace reader lock to prevent interference + * with any concurrent table unloads (which causes the deletion of + * namespace objects). We cannot allow the deletion of a namespace node + * while the user function is using it. The exception to this are the + * nodes created and deleted during control method execution -- these + * nodes are marked as temporary nodes and are ignored by the namespace + * walk. Thus, control methods can be executed while holding the + * namespace deletion lock (and the user function can execute control + * methods.) + */ + status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock); + if (ACPI_FAILURE(status)) { + return status; + } + + /* + * Lock the namespace around the walk. The namespace will be + * unlocked/locked around each call to the user function - since the user + * function must be allowed to make ACPICA calls itself (for example, it + * will typically execute control methods during device enumeration.) */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto unlock_and_exit; } status = acpi_ns_walk_namespace(type, start_object, max_depth, - ACPI_NS_WALK_UNLOCK, - user_function, context, return_value); + ACPI_NS_WALK_UNLOCK, user_function, + context, return_value); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + + unlock_and_exit: + (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index c37993003f2c..f865d5a096de 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -434,27 +434,56 @@ void acpi_tb_terminate(void) * * PARAMETERS: table_index - Table index * - * RETURN: None + * RETURN: Status * * DESCRIPTION: Delete all namespace objects created when this table was loaded. * ******************************************************************************/ -void acpi_tb_delete_namespace_by_owner(u32 table_index) +acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) { acpi_owner_id owner_id; + acpi_status status; - (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - if (table_index < acpi_gbl_root_table_list.count) { - owner_id = - acpi_gbl_root_table_list.tables[table_index].owner_id; - } else { - (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); - return; + ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); + + status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } + if (table_index >= acpi_gbl_root_table_list.count) { + + /* The table index does not exist */ + + (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + return_ACPI_STATUS(AE_NOT_EXIST); + } + + /* Get the owner ID for this table, used to delete namespace nodes */ + + owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); + + /* + * Need to acquire the namespace writer lock to prevent interference + * with any concurrent namespace walks. The interpreter must be + * released during the deletion since the acquisition of the deletion + * lock may block, and also since the execution of a namespace walk + * must be allowed to use the interpreter. + */ + acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); + status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); + acpi_ns_delete_namespace_by_owner(owner_id); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); + + status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); + return_ACPI_STATUS(status); } /******************************************************************************* diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c new file mode 100644 index 000000000000..25e03120686d --- /dev/null +++ b/drivers/acpi/acpica/utlock.c @@ -0,0 +1,175 @@ +/****************************************************************************** + * + * Module Name: utlock - Reader/Writer lock interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2009, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES +ACPI_MODULE_NAME("utlock") + +/******************************************************************************* + * + * FUNCTION: acpi_ut_create_rw_lock + * acpi_ut_delete_rw_lock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader/writer lock creation and deletion interfaces. + * + ******************************************************************************/ +acpi_status acpi_ut_create_rw_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + lock->num_readers = 0; + status = acpi_os_create_mutex(&lock->reader_mutex); + if (ACPI_FAILURE(status)) { + return status; + } + + status = acpi_os_create_mutex(&lock->writer_mutex); + return status; +} + +void acpi_ut_delete_rw_lock(struct acpi_rw_lock *lock) +{ + + acpi_os_delete_mutex(lock->reader_mutex); + acpi_os_delete_mutex(lock->writer_mutex); + + lock->num_readers = 0; + lock->reader_mutex = NULL; + lock->writer_mutex = NULL; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_acquire_read_lock + * acpi_ut_release_read_lock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition, + * only the first reader acquires the write mutex. On release, + * only the last reader releases the write mutex. Although this + * algorithm can in theory starve writers, this should not be a + * problem with ACPICA since the subsystem is infrequently used + * in comparison to (for example) an I/O system. + * + ******************************************************************************/ + +acpi_status acpi_ut_acquire_read_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return status; + } + + /* Acquire the write lock only for the first reader */ + + lock->num_readers++; + if (lock->num_readers == 1) { + status = + acpi_os_acquire_mutex(lock->writer_mutex, + ACPI_WAIT_FOREVER); + } + + acpi_os_release_mutex(lock->reader_mutex); + return status; +} + +acpi_status acpi_ut_release_read_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(lock->reader_mutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE(status)) { + return status; + } + + /* Release the write lock only for the very last reader */ + + lock->num_readers--; + if (lock->num_readers == 0) { + acpi_os_release_mutex(lock->writer_mutex); + } + + acpi_os_release_mutex(lock->reader_mutex); + return status; +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_acquire_write_lock + * acpi_ut_release_write_lock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or + * release the writer mutex associated with the lock. Acquisition + * of the lock is fully exclusive and will block all readers and + * writers until it is released. + * + ******************************************************************************/ + +acpi_status acpi_ut_acquire_write_lock(struct acpi_rw_lock *lock) +{ + acpi_status status; + + status = acpi_os_acquire_mutex(lock->writer_mutex, ACPI_WAIT_FOREVER); + return status; +} + +void acpi_ut_release_write_lock(struct acpi_rw_lock *lock) +{ + + acpi_os_release_mutex(lock->writer_mutex); +} diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 14eb52c4d647..26c93a748e64 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -60,7 +60,8 @@ static acpi_status acpi_ut_delete_mutex(acpi_mutex_handle mutex_id); * * RETURN: Status * - * DESCRIPTION: Create the system mutex objects. + * DESCRIPTION: Create the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. * ******************************************************************************/ @@ -71,9 +72,8 @@ acpi_status acpi_ut_mutex_initialize(void) ACPI_FUNCTION_TRACE(ut_mutex_initialize); - /* - * Create each of the predefined mutex objects - */ + /* Create each of the predefined mutex objects */ + for (i = 0; i < ACPI_NUM_MUTEX; i++) { status = acpi_ut_create_mutex(i); if (ACPI_FAILURE(status)) { @@ -86,6 +86,9 @@ acpi_status acpi_ut_mutex_initialize(void) spin_lock_init(acpi_gbl_gpe_lock); spin_lock_init(acpi_gbl_hardware_lock); + /* Create the reader/writer lock for namespace access */ + + status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock); return_ACPI_STATUS(status); } @@ -97,7 +100,8 @@ acpi_status acpi_ut_mutex_initialize(void) * * RETURN: None. * - * DESCRIPTION: Delete all of the system mutex objects. + * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. * ******************************************************************************/ @@ -107,9 +111,8 @@ void acpi_ut_mutex_terminate(void) ACPI_FUNCTION_TRACE(ut_mutex_terminate); - /* - * Delete each predefined mutex object - */ + /* Delete each predefined mutex object */ + for (i = 0; i < ACPI_NUM_MUTEX; i++) { (void)acpi_ut_delete_mutex(i); } @@ -118,6 +121,10 @@ void acpi_ut_mutex_terminate(void) acpi_os_delete_lock(acpi_gbl_gpe_lock); acpi_os_delete_lock(acpi_gbl_hardware_lock); + + /* Delete the reader/writer lock */ + + acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock); return_VOID; } From 8636f8d257b3edf5a1529df93119cdc630ed85c7 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 9 Mar 2009 16:32:20 +0800 Subject: [PATCH 042/140] ACPICA: Change handling of PM1 Status register ignored bit Ignored bits must be preserved according to the ACPI spec. Usually this means a read/modify/write when writing to the register. However, for status registers, writing a one means clear the event. Writing a zero means preserve the event (do not clear.) This behavior is clarified in the ACPI 4.0 spec, and the ACPICA code now simply always writes a zero to the ignored bit. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwregs.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index edc627c9fc0d..fd7abe277db3 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -273,22 +273,17 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ - - /* Perform a read first to preserve certain bits (per ACPI spec) */ - - status = acpi_hw_read_multiple(&read_value, - &acpi_gbl_xpm1a_status, - &acpi_gbl_xpm1b_status); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Insert the bits to be preserved */ - - ACPI_INSERT_BITS(value, ACPI_PM1_STATUS_PRESERVED_BITS, - read_value); - - /* Now we can write the data */ + /* + * Handle the "ignored" bit in PM1 Status. According to the ACPI + * specification, ignored bits are to be preserved when writing. + * Normally, this would mean a read/modify/write sequence. However, + * preserving a bit in the status register is different. Writing a + * one clears the status, and writing a zero preserves the status. + * Therefore, we must always write zero to the ignored bit. + * + * This behavior is clarified in the ACPI 4.0 specification. + */ + value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; status = acpi_hw_write_multiple(value, &acpi_gbl_xpm1a_status, From 20869dcfde204e1c21b642608d708d82472fee2b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 13 Mar 2009 09:10:46 +0800 Subject: [PATCH 043/140] ACPICA: Preserve all PM control reserved and ignored bits As per the ACPI specification, preserve (read/modify/write) all bits that are defined as either reserved or ignored (PM control control registers only.) Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/aclocal.h | 10 +++++++++- drivers/acpi/acpica/hwregs.c | 15 +++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 18a8d96eaa49..f01e155b2bcc 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -780,7 +780,15 @@ struct acpi_bit_register_info { * must be preserved. */ #define ACPI_PM1_STATUS_PRESERVED_BITS 0x0800 /* Bit 11 */ -#define ACPI_PM1_CONTROL_PRESERVED_BITS 0x0200 /* Bit 9 (whatever) */ + +/* For control registers, both ignored and reserved bits must be preserved */ + +#define ACPI_PM1_CONTROL_IGNORED_BITS 0x0201 /* Bits 9, 0(SCI_EN) */ +#define ACPI_PM1_CONTROL_RESERVED_BITS 0xC1F8 /* Bits 14-15, 3-8 */ +#define ACPI_PM1_CONTROL_PRESERVED_BITS \ + (ACPI_PM1_CONTROL_IGNORED_BITS | ACPI_PM1_CONTROL_RESERVED_BITS) + +#define ACPI_PM2_CONTROL_PRESERVED_BITS 0xFFFFFFFE /* All except bit 0 */ /* * Register IDs diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index fd7abe277db3..611736266f9f 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -328,6 +328,21 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ + /* + * For control registers, all reserved bits must be preserved, + * as per the ACPI spec. + */ + status = + acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block); + if (ACPI_FAILURE(status)) { + goto exit; + } + + /* Insert the bits to be preserved */ + + ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, + read_value); + status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); break; From 7f0719039085cc40114abce84cf29fe57da226f4 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 09:37:47 +0800 Subject: [PATCH 044/140] ACPICA: New: I/O port protection Protect certain I/O ports from reads/writes. Provides MS compatibility. New module, hwvalid.c Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/Makefile | 2 +- drivers/acpi/acpica/acglobal.h | 1 + drivers/acpi/acpica/achware.h | 7 + drivers/acpi/acpica/aclocal.h | 24 ++++ drivers/acpi/acpica/exregion.c | 4 +- drivers/acpi/acpica/hwacpi.c | 4 +- drivers/acpi/acpica/hwregs.c | 4 +- drivers/acpi/acpica/hwsleep.c | 2 +- drivers/acpi/acpica/hwvalid.c | 240 +++++++++++++++++++++++++++++++++ drivers/acpi/acpica/hwxface.c | 4 +- drivers/acpi/acpica/uteval.c | 55 +++++--- drivers/acpi/acpica/utglobal.c | 1 + 12 files changed, 319 insertions(+), 29 deletions(-) create mode 100644 drivers/acpi/acpica/hwvalid.c diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 290be74b774d..17e50824a6f1 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -18,7 +18,7 @@ obj-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o -obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o +obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o obj-$(ACPI_FUTURE_USAGE) += hwtimer.o diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index f431b997d2f8..16e5210ae936 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -252,6 +252,7 @@ ACPI_EXTERN u8 acpi_gbl_step_to_next_call; ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; ACPI_EXTERN u8 acpi_gbl_events_initialized; ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; +ACPI_EXTERN u8 acpi_gbl_osi_data; #ifndef DEFINE_ACPI_GLOBALS diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 4fa6ee6b1f7c..4afa3d8e0efb 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -72,6 +72,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value); acpi_status acpi_hw_clear_acpi_status(void); +/* + * hwvalid - Port I/O with validation + */ +acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width); + +acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); + /* * hwgpe - GPE support */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index f01e155b2bcc..42ef0cbf70f8 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -863,6 +863,30 @@ struct acpi_bit_register_info { #define ACPI_BITPOSITION_ARB_DISABLE 0x00 +/* Structs and definitions for _OSI support and I/O port validation */ + +#define ACPI_OSI_WIN_2000 0x01 +#define ACPI_OSI_WIN_XP 0x02 +#define ACPI_OSI_WIN_XP_SP1 0x03 +#define ACPI_OSI_WINSRV_2003 0x04 +#define ACPI_OSI_WIN_XP_SP2 0x05 +#define ACPI_OSI_WINSRV_2003_SP1 0x06 +#define ACPI_OSI_WIN_VISTA 0x07 + +#define ACPI_ALWAYS_ILLEGAL 0x00 + +struct acpi_interface_info { + char *name; + u8 value; +}; + +struct acpi_port_info { + char *name; + u16 start; + u16 end; + u8 osi_dependency; +}; + /***************************************************************************** * * Resource descriptors diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 76ec8ff903b8..3a54b737d2da 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -294,14 +294,14 @@ acpi_ex_system_io_space_handler(u32 function, switch (function) { case ACPI_READ: - status = acpi_os_read_port((acpi_io_address) address, + status = acpi_hw_read_port((acpi_io_address) address, &value32, bit_width); *value = value32; break; case ACPI_WRITE: - status = acpi_os_write_port((acpi_io_address) address, + status = acpi_hw_write_port((acpi_io_address) address, (u32) * value, bit_width); break; diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index e7949b133365..9af361a191e7 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -96,7 +96,7 @@ acpi_status acpi_hw_set_mode(u32 mode) /* BIOS should have disabled ALL fixed and GP events */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, (u32) acpi_gbl_FADT.acpi_enable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Attempting to enable ACPI mode\n")); @@ -108,7 +108,7 @@ acpi_status acpi_hw_set_mode(u32 mode) * BIOS should clear all fixed status bits and restore fixed event * enable bits to default */ - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, (u32) acpi_gbl_FADT.acpi_disable, 8); ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 611736266f9f..f8ee0a7fd44d 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -222,7 +222,7 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ status = - acpi_os_read_port(acpi_gbl_FADT.smi_command, &value, 8); + acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8); break; default: @@ -356,7 +356,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) /* SMI_CMD is currently always in IO space */ status = - acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); + acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8); break; default: diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 2ea4c59e8838..baa5fc05e124 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -430,7 +430,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) ACPI_FLUSH_CPU_CACHE(); - status = acpi_os_write_port(acpi_gbl_FADT.smi_command, + status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, (u32) acpi_gbl_FADT.S4bios_request, 8); do { diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c new file mode 100644 index 000000000000..e0b562fbe7c1 --- /dev/null +++ b/drivers/acpi/acpica/hwvalid.c @@ -0,0 +1,240 @@ + +/****************************************************************************** + * + * Module Name: hwvalid - I/O request validation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2009, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#include +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE +ACPI_MODULE_NAME("hwvalid") + +/* Local prototypes */ +static acpi_status +acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width); + +/* + * Protected I/O ports. Some ports are always illegal, and some are + * conditionally illegal. This table must remain ordered by port address. + * + * The table is used to implement the Microsoft port access rules that + * first appeared in Windows XP. Some ports are always illegal, and some + * ports are only illegal if the BIOS calls _OSI with a win_xP string or + * later (meaning that the BIOS itelf is post-XP.) + * + * This provides ACPICA with the desired port protections and + * Microsoft compatibility. + */ +static const struct acpi_port_info acpi_protected_ports[] = { + {"DMA1", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, + {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL}, + {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP}, + {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP}, + {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP}, + {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP}, + {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP}, + {"DMA1", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, + {"DMA2", 0x0089, 0x0089, ACPI_OSI_WIN_XP}, + {"DMA2", 0x008A, 0x008B, ACPI_OSI_WIN_XP}, + {"DMA2", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, + {"Arb", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, + {"Setup", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, + {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP}, + {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, + {"DMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, + {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, + {"PCI", 0x0CF8, 0x0D00, ACPI_OSI_WIN_XP} +}; + +#define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (acpi_protected_ports) + +/****************************************************************************** + * + * FUNCTION: acpi_hw_validate_io_request + * + * PARAMETERS: Address Address of I/O port/register + * bit_width Number of bits (8,16,32) + * + * RETURN: Status + * + * DESCRIPTION: Validates an I/O request (address/length). Certain ports are + * always illegal and some ports are only illegal depending on + * the requests the BIOS AML code makes to the predefined + * _OSI method. + * + ******************************************************************************/ + +static acpi_status +acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) +{ + u32 i; + u32 byte_width; + acpi_io_address last_address; + const struct acpi_port_info *port_info; + + ACPI_FUNCTION_TRACE(hw_validate_io_request); + + /* Supported widths are 8/16/32 */ + + if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { + return AE_BAD_PARAMETER; + } + + port_info = acpi_protected_ports; + byte_width = ACPI_DIV_8(bit_width); + last_address = address + byte_width - 1; + + ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X", + ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, + last_address), + byte_width)); + + /* Maximum 16-bit address in I/O space */ + + if (last_address > ACPI_UINT16_MAX) { + ACPI_ERROR((AE_INFO, + "Illegal I/O port address/length above 64K: 0x%p/%X", + ACPI_CAST_PTR(void, address), byte_width)); + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + + /* Exit if requested address is not within the protected port table */ + + if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) { + return_ACPI_STATUS(AE_OK); + } + + /* Check request against the list of protected I/O ports */ + + for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) { + /* + * Check if the requested address range will write to a reserved + * port. Four cases to consider: + * + * 1) Address range is contained completely in the port address range + * 2) Address range overlaps port range at the port range start + * 3) Address range overlaps port range at the port range end + * 4) Address range completely encompasses the port range + */ + if ((address <= port_info->end) + && (last_address >= port_info->start)) { + + /* Port illegality may depend on the _OSI calls made by the BIOS */ + + if (acpi_gbl_osi_data >= port_info->osi_dependency) { + ACPI_ERROR((AE_INFO, + "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", + ACPI_CAST_PTR(void, address), + byte_width, port_info->name, + port_info->start, port_info->end)); + + return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); + } + } + + /* Finished if address range ends before the end of this port */ + + if (last_address <= port_info->end) { + break; + } + } + + return_ACPI_STATUS(AE_OK); +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_read_port + * + * PARAMETERS: Address Address of I/O port/register to read + * Value Where value is placed + * Width Number of bits + * + * RETURN: Value read from port + * + * DESCRIPTION: Read data from an I/O port or register. This is a front-end + * to acpi_os_read_port that performs validation on both the port + * address and the length. + * + *****************************************************************************/ + +acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) +{ + acpi_status status; + + status = acpi_hw_validate_io_request(address, width); + if (ACPI_FAILURE(status)) { + return status; + } + + status = acpi_os_read_port(address, value, width); + return status; +} + +/****************************************************************************** + * + * FUNCTION: acpi_hw_write_port + * + * PARAMETERS: Address Address of I/O port/register to write + * Value Value to write + * Width Number of bits + * + * RETURN: None + * + * DESCRIPTION: Write data to an I/O port or register. This is a front-end + * to acpi_os_write_port that performs validation on both the port + * address and the length. + * + *****************************************************************************/ + +acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) +{ + acpi_status status; + + status = acpi_hw_validate_io_request(address, width); + if (ACPI_FAILURE(status)) { + return status; + } + + status = acpi_os_write_port(address, value, width); + return status; +} diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 26e66427f4ff..9829979f2bdd 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -146,7 +146,7 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) case ACPI_ADR_SPACE_SYSTEM_IO: status = - acpi_os_read_port((acpi_io_address) address, value, width); + acpi_hw_read_port((acpi_io_address) address, value, width); break; default: @@ -220,7 +220,7 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) case ACPI_ADR_SPACE_SYSTEM_IO: - status = acpi_os_write_port((acpi_io_address) address, value, + status = acpi_hw_write_port((acpi_io_address) address, value, width); break; diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 3b9152579d04..006b16c26017 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -59,26 +59,35 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, /* * Strings supported by the _OSI predefined (internal) method. + * + * March 2009: Removed "Linux" as this host no longer wants to respond true + * for this string. Basically, the only safe OS strings are windows-related + * and in many or most cases represent the only test path within the + * BIOS-provided ASL code. + * + * The second element of each entry is used to track the newest version of + * Windows that the BIOS has requested. */ -static char *acpi_interfaces_supported[] = { +static struct acpi_interface_info acpi_interfaces_supported[] = { /* Operating System Vendor Strings */ - "Windows 2000", /* Windows 2000 */ - "Windows 2001", /* Windows XP */ - "Windows 2001 SP1", /* Windows XP SP1 */ - "Windows 2001 SP2", /* Windows XP SP2 */ - "Windows 2001.1", /* Windows Server 2003 */ - "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ - "Windows 2006", /* Windows Vista - Added 03/2006 */ + {"Windows 2000", ACPI_OSI_WIN_2000}, /* Windows 2000 */ + {"Windows 2001", ACPI_OSI_WIN_XP}, /* Windows XP */ + {"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ + {"Windows 2001.1", ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ + {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ + {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ + {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ /* Feature Group Strings */ - "Extended Address Space Descriptor" - /* - * All "optional" feature group strings (features that are implemented - * by the host) should be implemented in the host version of - * acpi_os_validate_interface and should not be added here. - */ + {"Extended Address Space Descriptor", 0} + + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be implemented in the host version of + * acpi_os_validate_interface and should not be added here. + */ }; /******************************************************************************* @@ -125,9 +134,17 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { if (!ACPI_STRCMP(string_desc->string.pointer, - acpi_interfaces_supported[i])) { - - /* The interface is supported */ + acpi_interfaces_supported[i].name)) { + /* + * The interface is supported. + * Update the osi_data if necessary. We keep track of the latest + * version of Windows that has been requested by the BIOS. + */ + if (acpi_interfaces_supported[i].value > + acpi_gbl_osi_data) { + acpi_gbl_osi_data = + acpi_interfaces_supported[i].value; + } return_value = ACPI_UINT32_MAX; goto exit; @@ -176,8 +193,8 @@ acpi_status acpi_osi_invalidate(char *interface) int i; for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { - if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) { - *acpi_interfaces_supported[i] = '\0'; + if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) { + *acpi_interfaces_supported[i].name = '\0'; return AE_OK; } } diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 256ce7778565..59e46f257c02 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -789,6 +789,7 @@ acpi_status acpi_ut_init_globals(void) acpi_gbl_trace_dbg_layer = 0; acpi_gbl_debugger_configuration = DEBUGGER_THREADING; acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; + acpi_gbl_osi_data = 0; /* Hardware oriented */ From f9ca058430333c9a24c5ca926aa445125f88df18 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 09:47:16 +0800 Subject: [PATCH 045/140] ACPICA: Remove obsolete acpi_os_validate_address interface This interface is no longer necessary. Requests should be validated on a per-field basis, not on the entire operation region. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/acobject.h | 1 - drivers/acpi/acpica/dsopcode.c | 24 ------------------------ drivers/acpi/acpica/exfldio.c | 6 ------ include/acpi/acpiosxf.h | 4 ---- 4 files changed, 35 deletions(-) diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index eb6f038b03d9..544dcf834922 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -97,7 +97,6 @@ #define AOPOBJ_OBJECT_INITIALIZED 0x08 #define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SINGLE_DATUM 0x20 -#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ /****************************************************************************** * diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 602ddaa10c29..b4c87b5053e6 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -397,30 +397,6 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), extra_desc->extra.aml_length, extra_desc->extra.aml_start); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate the region address/length via the host OS */ - - status = acpi_os_validate_address(obj_desc->region.space_id, - obj_desc->region.address, - (acpi_size) obj_desc->region.length, - acpi_ut_get_node_name(node)); - - if (ACPI_FAILURE(status)) { - /* - * Invalid address/length. We will emit an error message and mark - * the region as invalid, so that it will cause an additional error if - * it is ever used. Then return AE_OK. - */ - ACPI_EXCEPTION((AE_INFO, status, - "During address validation of OpRegion [%4.4s]", - node->name.ascii)); - obj_desc->common.flags |= AOPOBJ_INVALID; - status = AE_OK; - } - return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 1053e7cd92a1..99cee61e655d 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -113,12 +113,6 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } } - /* Exit if Address/Length have been disallowed by the host OS */ - - if (rgn_desc->common.flags & AOPOBJ_INVALID) { - return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); - } - /* * Exit now for SMBus address space, it has a non-linear address space * and the request cannot be directly validated diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index a62720a7edc0..178adfb80237 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -241,10 +241,6 @@ acpi_os_derive_pci_id(acpi_handle rhandle, acpi_status acpi_os_validate_interface(char *interface); acpi_status acpi_osi_invalidate(char* interface); -acpi_status -acpi_os_validate_address(u8 space_id, acpi_physical_address address, - acpi_size length, char *name); - u64 acpi_os_get_timer(void); acpi_status acpi_os_signal(u32 function, void *info); From c3dd25f4c1ca84baa170c0a3a15a884f4f06297e Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 19 Mar 2009 09:51:01 +0800 Subject: [PATCH 046/140] ACPICA: Clear PM register write-only bits on reading Affects PM1 Control register only. When reading the register, zero the write-only bits as per the ACPI spec. ACPICA BZ 443. Lin Ming. http://www.acpica.org/bugzilla/show_bug.cgi?id=443 Signed-off-by: Lin Ming Signed-off-by: Bob Moore Signed-off-by: Len Brown --- drivers/acpi/acpica/aclocal.h | 4 ++++ drivers/acpi/acpica/hwregs.c | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 42ef0cbf70f8..772ee5c4ccca 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -781,6 +781,10 @@ struct acpi_bit_register_info { */ #define ACPI_PM1_STATUS_PRESERVED_BITS 0x0800 /* Bit 11 */ +/* Write-only bits must be zeroed by software */ + +#define ACPI_PM1_CONTROL_WRITEONLY_BITS 0x2004 /* Bits 13, 2 */ + /* For control registers, both ignored and reserved bits must be preserved */ #define ACPI_PM1_CONTROL_IGNORED_BITS 0x0201 /* Bits 9, 0(SCI_EN) */ diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index f8ee0a7fd44d..7b2fb602b5cb 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -207,6 +207,13 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) xpm1a_control_block, &acpi_gbl_FADT. xpm1b_control_block); + + /* + * Zero the write-only bits. From the ACPI specification, "Hardware + * Write-Only Bits": "Upon reads to registers with write-only bits, + * software masks out all write-only bits." + */ + value &= ~ACPI_PM1_CONTROL_WRITEONLY_BITS; break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ From 91a56e631fc837852304ee7bc2876d6e444b7fdb Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 09:52:34 +0800 Subject: [PATCH 047/140] ACPICA: Remove unused code, no functional change Removed unused code for dump of args and locals. General cleanup and splitting of long lines. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/exdump.c | 46 ++++++++---------------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 193d23312e18..89d141fdae0b 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -350,6 +350,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, break; case ACPI_EXD_TYPE: + acpi_ex_out_string("Type", acpi_ut_get_object_type_name (obj_desc)); @@ -422,6 +423,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, break; default: + acpi_os_printf("**** Invalid table opcode [%X] ****\n", info->opcode); return; @@ -527,46 +529,18 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) type)); break; - case ACPI_REFCLASS_ARG: - - acpi_os_printf("%X", obj_desc->reference.value); - - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - - /* Value is an Integer */ - - acpi_os_printf(" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64(obj_desc-> - integer. - value)); - } - - acpi_os_printf("\n"); - break; - - case ACPI_REFCLASS_LOCAL: - - acpi_os_printf("%X", obj_desc->reference.value); - - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - - /* Value is an Integer */ - - acpi_os_printf(" value is [%8.8X%8.8x]", - ACPI_FORMAT_UINT64(obj_desc-> - integer. - value)); - } - - acpi_os_printf("\n"); - break; - case ACPI_REFCLASS_NAME: acpi_os_printf("- [%4.4s]\n", obj_desc->reference.node->name.ascii); break; + case ACPI_REFCLASS_ARG: + case ACPI_REFCLASS_LOCAL: + + acpi_os_printf("%X\n", obj_desc->reference.value); + break; + default: /* Unknown reference class */ acpi_os_printf("%2.2X\n", obj_desc->reference.class); @@ -661,8 +635,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf - ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", - obj_desc->field.bit_length, + ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at " + "byte=%X bit=%X of below:\n", obj_desc->field.bit_length, obj_desc->field.access_byte_width, obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, From ee6a0fbd0ccb7736a3be56630e3ad65ceddfb5bd Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 09:53:35 +0800 Subject: [PATCH 048/140] ACPICA: Condense some protected ports One entry in the protected port table eliminated. Added extra comments to describe each table entry. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwvalid.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index e0b562fbe7c1..105b818eba45 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -63,24 +63,42 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width); * * This provides ACPICA with the desired port protections and * Microsoft compatibility. + * + * Description of port entries: + * DMA: DMA controller + * PIC0: Programmable Interrupt Controller (8259_a) + * PIT1: System Timer 1 + * PIT2: System Timer 2 failsafe + * RTC: Real-time clock + * CMOS: Extended CMOS + * DMA1: DMA 1 page registers + * DMA1L: DMA 1 Ch 0 low page + * DMA2: DMA 2 page registers + * DMA2L: DMA 2 low page refresh + * ARBC: Arbitration control + * SETUP: Reserved system board setup + * POS: POS channel select + * PIC1: Cascaded PIC + * IDMA: ISA DMA + * ELCR: PIC edge/level registers + * PCI: PCI configuration space */ static const struct acpi_port_info acpi_protected_ports[] = { - {"DMA1", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, + {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL}, {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP}, {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP}, {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP}, {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP}, {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP}, - {"DMA1", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, - {"DMA2", 0x0089, 0x0089, ACPI_OSI_WIN_XP}, - {"DMA2", 0x008A, 0x008B, ACPI_OSI_WIN_XP}, - {"DMA2", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, - {"Arb", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, - {"Setup", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, + {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, + {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP}, + {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, + {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, + {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP}, {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, - {"DMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, + {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, {"PCI", 0x0CF8, 0x0D00, ACPI_OSI_WIN_XP} }; From f28ad2c3daf0691081d91488df4d9d101e1a2b5d Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 09:54:31 +0800 Subject: [PATCH 049/140] ACPICA: Fix PCI configuration space port address range Microsoft website uses 0xCF8-0xD00. Should be 0xCF8-0xCFF (Two 32-bit registers.) Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/hwvalid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index 105b818eba45..bd3c937b0ac0 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -100,7 +100,7 @@ static const struct acpi_port_info acpi_protected_ports[] = { {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, - {"PCI", 0x0CF8, 0x0D00, ACPI_OSI_WIN_XP} + {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP} }; #define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (acpi_protected_ports) From 31fbc073a35a017e34840deb9e865a701e986002 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 10:12:13 +0800 Subject: [PATCH 050/140] ACPICA: FADT: Favor 32-bit register addresses for compatibility Use the 32-bit register addresses whenever they are non-zero. This means that the 32-bit addresses are favored over the 64-bit (GAS) addresses. The 64-bit addresses are only used if the 32-bit addresses are zero. This change provides compatibility with all versions of Windows. The worst case that this solves is when both the 32-bit and 64-bit addresses are non-zero, but only the 32-bit addresses are actually valid. This appears to happen in some BIOSes because in this case, Windows uses the 32-bit addresses. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 86 +++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index ff89cfee0e7e..f87bfb259ef6 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -320,29 +320,35 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) * RETURN: None * * DESCRIPTION: Converts all versions of the FADT to a common internal format. - * Expand all 32-bit addresses to 64-bit. + * Expand 32-bit addresses to 64-bit as necessary. * * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), * and must contain a copy of the actual FADT. * - * ACPICA will use the "X" fields of the FADT for all addresses. + * Notes on 64-bit register addresses: * - * "X" fields are optional extensions to the original V1.0 fields. Even if - * they are present in the structure, they can be optionally not used by - * setting them to zero. Therefore, we must selectively expand V1.0 fields - * if the corresponding X field is zero. + * After this FADT conversion, later ACPICA code will only use the 64-bit "X" + * fields of the FADT for all ACPI register addresses. * - * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding - * "X" fields. + * The 64-bit "X" fields are optional extensions to the original 32-bit FADT + * V1.0 fields. Even if they are present in the FADT, they are optional and + * are unused if the BIOS sets them to zero. Therefore, we must copy/expand + * 32-bit V1.0 fields if the corresponding X field is zero. * - * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by - * expanding the corresponding ACPI 1.0 field. + * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the + * corresponding "X" fields in the internal FADT. + * + * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded + * to the corresponding 64-bit X fields. For compatibility with other ACPI + * implementations, we ignore the 64-bit field if the 32-bit field is valid, + * regardless of whether the host OS is 32-bit or 64-bit. * ******************************************************************************/ static void acpi_tb_convert_fadt(void) { - struct acpi_generic_address *target64; + struct acpi_generic_address *address64; + u32 address32; u32 i; /* Update the local FADT table header length */ @@ -391,29 +397,51 @@ static void acpi_tb_convert_fadt(void) * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. Later code will always use * the 64-bit address structures. + * + * March 2009: + * We now always use the 32-bit address if it is valid (non-null). This + * is not in accordance with the ACPI specification which states that + * the 64-bit address supersedes the 32-bit version, but we do this for + * compatibility with other ACPI implementations. Most notably, in the + * case where both the 32 and 64 versions are non-null, we use the 32-bit + * version. This is the only address that is guaranteed to have been + * tested by the BIOS manufacturer. */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { - target64 = - ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, - fadt_info_table[i].address64); + address32 = *ACPI_ADD_PTR(u32, + &acpi_gbl_FADT, + fadt_info_table[i].address32); - /* Expand only if the 64-bit X target is null */ + address64 = ACPI_ADD_PTR(struct acpi_generic_address, + &acpi_gbl_FADT, + fadt_info_table[i].address64); - if (!target64->address) { + /* + * If both 32- and 64-bit addresses are valid (non-zero), + * they must match. + */ + if (address64->address && address32 && + (address64->address != (u64) address32)) { + ACPI_ERROR((AE_INFO, + "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 32", + fadt_info_table[i].name, address32, + ACPI_FORMAT_UINT64(address64->address))); + } - /* The space_id is always I/O for the 32-bit legacy address fields */ + /* Always use 32-bit address if it is valid (non-null) */ - acpi_tb_init_generic_address(target64, + if (address32) { + /* + * Copy the 32-bit address to the 64-bit GAS structure. The + * Space ID is always I/O for 32-bit legacy address fields + */ + acpi_tb_init_generic_address(address64, ACPI_ADR_SPACE_SYSTEM_IO, *ACPI_ADD_PTR(u8, &acpi_gbl_FADT, fadt_info_table [i].length), - (u64) * ACPI_ADD_PTR(u32, - &acpi_gbl_FADT, - fadt_info_table - [i]. - address32)); + address32); } } } @@ -530,18 +558,6 @@ static void acpi_tb_validate_fadt(void) length)); } } - - /* - * If both 32- and 64-bit addresses are valid (non-zero), - * they must match - */ - if (address64->address && *address32 && - (address64->address != (u64) * address32)) { - ACPI_ERROR((AE_INFO, - "32/64X address mismatch in %s: %8.8X/%8.8X%8.8X, using 64X", - name, *address32, - ACPI_FORMAT_UINT64(address64->address))); - } } } From f65563063375b05898a94ab71b52612cbe3a789b Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 10:13:40 +0800 Subject: [PATCH 051/140] ACPICA: FADT: Favor 32-bit FACS and DSDT addresses If both the 32-bit and 64-bit addresses are non-null, use the 32-bit address. Provides Windows compatibility. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/tbfadt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index f87bfb259ef6..71e655d14cb0 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -483,18 +483,22 @@ static void acpi_tb_validate_fadt(void) (acpi_gbl_FADT.Xfacs != (u64) acpi_gbl_FADT.facs)) { ACPI_WARNING((AE_INFO, "32/64X FACS address mismatch in FADT - " - "two FACS tables! %8.8X/%8.8X%8.8X", + "%8.8X/%8.8X%8.8X, using 32", acpi_gbl_FADT.facs, ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xfacs))); + + acpi_gbl_FADT.Xfacs = (u64) acpi_gbl_FADT.facs; } if (acpi_gbl_FADT.dsdt && (acpi_gbl_FADT.Xdsdt != (u64) acpi_gbl_FADT.dsdt)) { ACPI_WARNING((AE_INFO, "32/64X DSDT address mismatch in FADT - " - "two DSDT tables! %8.8X/%8.8X%8.8X", + "%8.8X/%8.8X%8.8X, using 32", acpi_gbl_FADT.dsdt, ACPI_FORMAT_UINT64(acpi_gbl_FADT.Xdsdt))); + + acpi_gbl_FADT.Xdsdt = (u64) acpi_gbl_FADT.dsdt; } /* Examine all of the 64-bit extended address fields (X fields) */ From 03ef132b7258bbea4858be4b1bd6cb6c3fdd3253 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 19 Mar 2009 10:14:45 +0800 Subject: [PATCH 052/140] ACPICA: Fix index value in package warning message For predefined method validation. Index value in warning message could be off by one. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- drivers/acpi/acpica/nspredef.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 0d0b4ee1358e..d9e8cbc6e679 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -79,7 +79,9 @@ acpi_ns_check_package(char *pathname, static acpi_status acpi_ns_check_package_elements(char *pathname, union acpi_operand_object **elements, - u8 type1, u32 count1, u8 type2, u32 count2); + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index); static acpi_status acpi_ns_check_object_type(char *pathname, @@ -473,7 +475,7 @@ acpi_ns_check_package(char *pathname, package->ret_info. object_type2, package->ret_info. - count2); + count2, 0); if (ACPI_FAILURE(status)) { return (status); } @@ -624,7 +626,7 @@ acpi_ns_check_package(char *pathname, object_type2, package-> ret_info. - count2); + count2, 0); if (ACPI_FAILURE(status)) { return (status); } @@ -673,7 +675,8 @@ acpi_ns_check_package(char *pathname, object_type1, sub_package-> package. - count, 0, 0); + count, 0, 0, + 0); if (ACPI_FAILURE(status)) { return (status); } @@ -711,7 +714,8 @@ acpi_ns_check_package(char *pathname, ret_info. object_type1, (expected_count - - 1), 0, 0); + - 1), 0, 0, + 1); if (ACPI_FAILURE(status)) { return (status); } @@ -759,6 +763,7 @@ acpi_ns_check_package(char *pathname, * Count1 - Count for first group * Type2 - Object type for second group * Count2 - Count for second group + * start_index - Start of the first group of elements * * RETURN: Status * @@ -770,7 +775,9 @@ acpi_ns_check_package(char *pathname, static acpi_status acpi_ns_check_package_elements(char *pathname, union acpi_operand_object **elements, - u8 type1, u32 count1, u8 type2, u32 count2) + u8 type1, + u32 count1, + u8 type2, u32 count2, u32 start_index) { union acpi_operand_object **this_element = elements; acpi_status status; @@ -783,7 +790,7 @@ acpi_ns_check_package_elements(char *pathname, */ for (i = 0; i < count1; i++) { status = acpi_ns_check_object_type(pathname, this_element, - type1, i); + type1, i + start_index); if (ACPI_FAILURE(status)) { return (status); } @@ -792,7 +799,8 @@ acpi_ns_check_package_elements(char *pathname, for (i = 0; i < count2; i++) { status = acpi_ns_check_object_type(pathname, this_element, - type2, (i + count1)); + type2, + (i + count1 + start_index)); if (ACPI_FAILURE(status)) { return (status); } From 14eecfc1195a9d16999157591ffce23acd6df8c1 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Mon, 23 Mar 2009 09:30:27 +0800 Subject: [PATCH 053/140] ACPICA: Update version to 20090320 Version 20090320. Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Len Brown --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 666182b5ca31..16826f15f01f 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -47,7 +47,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20090220 +#define ACPI_CA_VERSION 0x20090320 #include "actypes.h" #include "actbl.h" From badf26f00f2ed80615206d07bcfc2e3b78af5441 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 21:58:12 +0900 Subject: [PATCH 054/140] sony-laptop: Add support for new Sony platform API Newer Sony Vaios provide a new API for accessing platform functionality. It consists of a set of standardised methods for enabling events and performing queries. These are each identified by a unique handle. This patch adds support for calling functions based on their handle and ports the existing code for these machines over to it. Signed-off-by: Matthew Garrett Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 146 +++++++++++++---------------- 1 file changed, 65 insertions(+), 81 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 537959d07148..3c52ec9548ab 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -689,6 +689,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value, return -1; } +static int sony_find_snc_handle(int handle) +{ + int i; + int result; + + for (i = 0x20; i < 0x30; i++) { + acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result); + if (result == handle) + return i-0x20; + } + + return -1; +} + +static int sony_call_snc_handle(int handle, int argument, int *result) +{ + int offset = sony_find_snc_handle(handle); + + if (offset < 0) + return -1; + + return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument, + result); +} + /* * sony_nc_values input/output validate functions */ @@ -809,32 +834,6 @@ struct sony_nc_event { u8 event; }; -static struct sony_nc_event *sony_nc_events; - -/* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence - * for Fn keys - */ -static int sony_nc_C_enable(const struct dmi_system_id *id) -{ - int result = 0; - - printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); - - sony_nc_events = id->driver_data; - - if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 - || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 - || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 - || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 - || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 - || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { - printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " - "functionalities may be missing\n"); - return 1; - } - return 0; -} - static struct sony_nc_event sony_C_events[] = { { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, @@ -851,57 +850,17 @@ static struct sony_nc_event sony_C_events[] = { { 0, 0 }, }; -/* SNC-only model map */ -static const struct dmi_system_id sony_nc_ids[] = { - { - .ident = "Sony Vaio FE Series", - .callback = sony_nc_C_enable, - .driver_data = sony_C_events, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), - }, - }, - { - .ident = "Sony Vaio FZ Series", - .callback = sony_nc_C_enable, - .driver_data = sony_C_events, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"), - }, - }, - { - .ident = "Sony Vaio C Series", - .callback = sony_nc_C_enable, - .driver_data = sony_C_events, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), - }, - }, - { - .ident = "Sony Vaio N Series", - .callback = sony_nc_C_enable, - .driver_data = sony_C_events, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), - }, - }, - { } -}; - /* * ACPI callbacks */ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) { - struct sony_nc_event *evmap; + int i; u32 ev = event; int result; - if (ev == 0x92) { + if (ev == 0x92 || ev == 0x90) { + int origev = ev; /* read the key pressed from EC.GECR * A call to SN07 with 0x0202 will do it as well respecting * the current protocol on different OSes @@ -913,20 +872,23 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) * TODO: we may want to do the same for the older GHKE -need * dmi list- so this snippet may become one more callback. */ - if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) + if (sony_call_snc_handle(0x100, 0x200, &result)) dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); else ev = result & 0xFF; - } - if (sony_nc_events) - for (evmap = sony_nc_events; evmap->event; evmap++) { - if (evmap->data == ev) { - ev = evmap->event; + for (i = 0; sony_C_events[i].data; i++) { + if (sony_C_events[i].data == ev) { + ev = sony_C_events[i].event; break; } } + if (!sony_C_events[i].data) + printk(KERN_INFO DRV_PFX "Unknown event: %x %x\n", + origev, ev); + } + dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); sony_laptop_report_input_event(ev); acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); @@ -953,9 +915,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, /* * ACPI device */ +static int sony_nc_function_setup(struct acpi_device *device) +{ + int result; + + /* Enable all events */ + acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result); + + /* Setup hotkeys */ + sony_call_snc_handle(0x0100, 0, &result); + sony_call_snc_handle(0x0101, 0, &result); + sony_call_snc_handle(0x0102, 0x100, &result); + + return 0; +} + static int sony_nc_resume(struct acpi_device *device) { struct sony_nc_value *item; + acpi_handle handle; for (item = sony_nc_values; item->name; item++) { int ret; @@ -970,14 +948,17 @@ static int sony_nc_resume(struct acpi_device *device) } } + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", + &handle))) { + dprintk("Doing SNC setup\n"); + sony_nc_function_setup(device); + } + /* set the last requested brightness level */ if (sony_backlight_device && !sony_backlight_update_status(sony_backlight_device)) printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); - /* re-initialize models with specific requirements */ - dmi_check_system(sony_nc_ids); - return 0; } @@ -1024,6 +1005,12 @@ static int sony_nc_add(struct acpi_device *device) dprintk("_INI Method failed\n"); } + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", + &handle))) { + dprintk("Doing SNC setup\n"); + sony_nc_function_setup(device); + } + /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); if (result) { @@ -1063,9 +1050,6 @@ static int sony_nc_add(struct acpi_device *device) } - /* initialize models with specific requirements */ - dmi_check_system(sony_nc_ids); - result = sony_pf_add(); if (result) goto outbacklight; From 82734bfc8622f3e8f015a5783b739739f97f89f9 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 21:58:13 +0900 Subject: [PATCH 055/140] sony-laptop: Enable EC on newer hardware The latest Vaios can execute certain codepaths in two ways - either using system management mode or using pure ACPI methods. The latter is only used if the OS has called the ECON method. Ensure that this is done where the method is available. Signed-off-by: Matthew Garrett Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3c52ec9548ab..04deed826180 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -948,6 +948,12 @@ static int sony_nc_resume(struct acpi_device *device) } } + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", + &handle))) { + if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) + dprintk("ECON Method failed\n"); + } + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); @@ -1005,6 +1011,12 @@ static int sony_nc_add(struct acpi_device *device) dprintk("_INI Method failed\n"); } + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON", + &handle))) { + if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL)) + dprintk("ECON Method failed\n"); + } + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00", &handle))) { dprintk("Doing SNC setup\n"); From 9b57896e62bfa752ee7435e6cfe57fb210c0db8c Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 21:58:14 +0900 Subject: [PATCH 056/140] sony-laptop: Add support for extra keyboard events The current sony-laptop code assumes that the keyboard event method is always located at slot 2 in the platform code. Remove this assumption and add support for some additional hotkeys. Signed-off-by: Matthew Garrett Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 59 ++++++++++++++++-------------- include/linux/sonypi.h | 1 + 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 04deed826180..f6cdc8929fd7 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -211,6 +211,7 @@ static int sony_laptop_input_index[] = { 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ + 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */ }; static int sony_laptop_input_keycode_map[] = { @@ -264,7 +265,8 @@ static int sony_laptop_input_keycode_map[] = { KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ - KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ + KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ + KEY_EJECTCD /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ }; /* release buttons after a short delay if pressed */ @@ -834,7 +836,11 @@ struct sony_nc_event { u8 event; }; -static struct sony_nc_event sony_C_events[] = { +static struct sony_nc_event sony_nc_events[] = { + { 0x90, SONYPI_EVENT_PKEY_P1 }, + { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x91, SONYPI_EVENT_PKEY_P1 }, + { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, { 0x85, SONYPI_EVENT_FNKEY_F5 }, @@ -843,10 +849,14 @@ static struct sony_nc_event sony_C_events[] = { { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, { 0x87, SONYPI_EVENT_FNKEY_F7 }, { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, + { 0x89, SONYPI_EVENT_FNKEY_F9 }, + { 0x09, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8A, SONYPI_EVENT_FNKEY_F10 }, { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, { 0x8C, SONYPI_EVENT_FNKEY_F12 }, { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, + { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, + { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }, }; @@ -855,38 +865,33 @@ static struct sony_nc_event sony_C_events[] = { */ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) { - int i; u32 ev = event; int result; - if (ev == 0x92 || ev == 0x90) { + if (ev >= 0x90) { + /* New-style event */ int origev = ev; - /* read the key pressed from EC.GECR - * A call to SN07 with 0x0202 will do it as well respecting - * the current protocol on different OSes - * - * Note: the path for GECR may be - * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) - * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) - * - * TODO: we may want to do the same for the older GHKE -need - * dmi list- so this snippet may become one more callback. - */ - if (sony_call_snc_handle(0x100, 0x200, &result)) - dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); - else - ev = result & 0xFF; + ev -= 0x90; - for (i = 0; sony_C_events[i].data; i++) { - if (sony_C_events[i].data == ev) { - ev = sony_C_events[i].event; - break; + if (sony_find_snc_handle(0x100) == ev) { + int i; + + if (sony_call_snc_handle(0x100, 0x200, &result)) + dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); + else + ev = result & 0xFF; + + for (i = 0; sony_nc_events[i].event; i++) { + if (sony_nc_events[i].data == ev) { + ev = sony_nc_events[i].event; + break; + } } - } - if (!sony_C_events[i].data) - printk(KERN_INFO DRV_PFX "Unknown event: %x %x\n", - origev, ev); + if (!sony_nc_events[i].data) + printk(KERN_INFO DRV_PFX + "Unknown event: %x %x\n", origev, ev); + } } dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h index f41ffd7c2dd9..8458dbe95862 100644 --- a/include/linux/sonypi.h +++ b/include/linux/sonypi.h @@ -103,6 +103,7 @@ #define SONYPI_EVENT_WIRELESS_OFF 61 #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 +#define SONYPI_EVENT_CD_EJECT_PRESSED 64 /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) From 6cc056bc31ea9910afb01adc0848bb6ae68e0205 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 21:58:15 +0900 Subject: [PATCH 057/140] sony-laptop: Add rfkill support on new models Newer Vaios provide a full featured rfkill implementation via their platform methods. Add support for enumerating the available devices and providing rfkill access to them. Support for the physical kill switch is added, with the devices moving into the HARD_BLOCKED state when toggled. Signed-off-by: Matthew Garrett Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 186 +++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index f6cdc8929fd7..f458870c30b6 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -64,6 +64,7 @@ #include #include #include +#include #ifdef CONFIG_SONYPI_COMPAT #include #include @@ -123,6 +124,18 @@ MODULE_PARM_DESC(minor, "default is -1 (automatic)"); #endif +enum sony_nc_rfkill { + SONY_WIFI, + SONY_BLUETOOTH, + SONY_WWAN, + SONY_WIMAX, + SONY_RFKILL_MAX, +}; + +static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX]; +static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900}; +static void sony_nc_rfkill_update(void); + /*********** Input Devices ***********/ #define SONY_LAPTOP_BUF_SIZE 128 @@ -134,6 +147,7 @@ struct sony_laptop_input_s { spinlock_t fifo_lock; struct workqueue_struct *wq; }; + static struct sony_laptop_input_s sony_laptop_input = { .users = ATOMIC_INIT(0), }; @@ -891,6 +905,9 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) if (!sony_nc_events[i].data) printk(KERN_INFO DRV_PFX "Unknown event: %x %x\n", origev, ev); + } else if (sony_find_snc_handle(0x124) == ev) { + sony_nc_rfkill_update(); + return; } } @@ -973,6 +990,172 @@ static int sony_nc_resume(struct acpi_device *device) return 0; } +static void sony_nc_rfkill_cleanup(void) +{ + int i; + + for (i = 0; i < SONY_RFKILL_MAX; i++) { + if (sony_rfkill_devices[i]) + rfkill_unregister(sony_rfkill_devices[i]); + } +} + +static int sony_nc_rfkill_get(void *data, enum rfkill_state *state) +{ + int result; + int argument = sony_rfkill_address[(long) data]; + + sony_call_snc_handle(0x124, 0x200, &result); + if (result & 0x1) { + sony_call_snc_handle(0x124, argument, &result); + if (result & 0xf) + *state = RFKILL_STATE_UNBLOCKED; + else + *state = RFKILL_STATE_SOFT_BLOCKED; + } else { + *state = RFKILL_STATE_HARD_BLOCKED; + } + + return 0; +} + +static int sony_nc_rfkill_set(void *data, enum rfkill_state state) +{ + int result; + int argument = sony_rfkill_address[(long) data] + 0x100; + + if (state == RFKILL_STATE_UNBLOCKED) + argument |= 0xff0000; + + return sony_call_snc_handle(0x124, argument, &result); +} + +static int sony_nc_setup_wifi_rfkill(struct acpi_device *device) +{ + int err = 0; + struct rfkill *sony_wifi_rfkill; + + sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN); + if (!sony_wifi_rfkill) + return -1; + sony_wifi_rfkill->name = "sony-wifi"; + sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set; + sony_wifi_rfkill->get_state = sony_nc_rfkill_get; + sony_wifi_rfkill->user_claim_unsupported = 1; + sony_wifi_rfkill->data = (void *)SONY_WIFI; + err = rfkill_register(sony_wifi_rfkill); + if (err) + rfkill_free(sony_wifi_rfkill); + else + sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill; + return err; +} + +static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device) +{ + int err = 0; + struct rfkill *sony_bluetooth_rfkill; + + sony_bluetooth_rfkill = rfkill_allocate(&device->dev, + RFKILL_TYPE_BLUETOOTH); + if (!sony_bluetooth_rfkill) + return -1; + sony_bluetooth_rfkill->name = "sony-bluetooth"; + sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set; + sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get; + sony_bluetooth_rfkill->user_claim_unsupported = 1; + sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH; + err = rfkill_register(sony_bluetooth_rfkill); + if (err) + rfkill_free(sony_bluetooth_rfkill); + else + sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill; + return err; +} + +static int sony_nc_setup_wwan_rfkill(struct acpi_device *device) +{ + int err = 0; + struct rfkill *sony_wwan_rfkill; + + sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN); + if (!sony_wwan_rfkill) + return -1; + sony_wwan_rfkill->name = "sony-wwan"; + sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set; + sony_wwan_rfkill->get_state = sony_nc_rfkill_get; + sony_wwan_rfkill->user_claim_unsupported = 1; + sony_wwan_rfkill->data = (void *)SONY_WWAN; + err = rfkill_register(sony_wwan_rfkill); + if (err) + rfkill_free(sony_wwan_rfkill); + else + sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill; + return err; +} + +static int sony_nc_setup_wimax_rfkill(struct acpi_device *device) +{ + int err = 0; + struct rfkill *sony_wimax_rfkill; + + sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX); + if (!sony_wimax_rfkill) + return -1; + sony_wimax_rfkill->name = "sony-wimax"; + sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set; + sony_wimax_rfkill->get_state = sony_nc_rfkill_get; + sony_wimax_rfkill->user_claim_unsupported = 1; + sony_wimax_rfkill->data = (void *)SONY_WIMAX; + err = rfkill_register(sony_wimax_rfkill); + if (err) + rfkill_free(sony_wimax_rfkill); + else + sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill; + return err; +} + +static void sony_nc_rfkill_update() +{ + int i; + enum rfkill_state state; + + for (i = 0; i < SONY_RFKILL_MAX; i++) { + if (sony_rfkill_devices[i]) { + sony_rfkill_devices[i]-> + get_state(sony_rfkill_devices[i]->data, + &state); + rfkill_force_state(sony_rfkill_devices[i], state); + } + } +} + +static int sony_nc_rfkill_setup(struct acpi_device *device) +{ + int result, ret; + + if (sony_find_snc_handle(0x124) == -1) + return -1; + + ret = sony_call_snc_handle(0x124, 0xb00, &result); + if (ret) { + printk(KERN_INFO DRV_PFX + "Unable to enumerate rfkill devices: %x\n", ret); + return ret; + } + + if (result & 0x1) + sony_nc_setup_wifi_rfkill(device); + if (result & 0x2) + sony_nc_setup_bluetooth_rfkill(device); + if (result & 0x1c) + sony_nc_setup_wwan_rfkill(device); + if (result & 0x20) + sony_nc_setup_wimax_rfkill(device); + + return 0; +} + static int sony_nc_add(struct acpi_device *device) { acpi_status status; @@ -1026,6 +1209,7 @@ static int sony_nc_add(struct acpi_device *device) &handle))) { dprintk("Doing SNC setup\n"); sony_nc_function_setup(device); + sony_nc_rfkill_setup(device); } /* setup input devices and helper fifo */ @@ -1132,6 +1316,7 @@ static int sony_nc_add(struct acpi_device *device) sony_laptop_remove_input(); outwalk: + sony_nc_rfkill_cleanup(); return result; } @@ -1157,6 +1342,7 @@ static int sony_nc_remove(struct acpi_device *device, int type) sony_pf_remove(); sony_laptop_remove_input(); + sony_nc_rfkill_cleanup(); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); return 0; From 45c7942ba8f6b7d5d1147c10f84f0cbf5fa3a2b8 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Mar 2009 21:58:16 +0900 Subject: [PATCH 058/140] sony-laptop: Add support for extended hotkeys Recent Sony SR-series machines have an additional set of buttons accessed via the 0x127 method rather than the 0x100 method. Add support for these. Signed-off-by: Matthew Garrett Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 65 ++++++++++++++++++++++++------ include/linux/sonypi.h | 4 ++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index f458870c30b6..e000c9f6cdf5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -226,6 +226,10 @@ static int sony_laptop_input_index[] = { 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */ + 52, /* 65 SONYPI_EVENT_MODEKEY_PRESSED */ + 53, /* 66 SONYPI_EVENT_PKEY_P4 */ + 54, /* 67 SONYPI_EVENT_PKEY_P5 */ + 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */ }; static int sony_laptop_input_keycode_map[] = { @@ -280,7 +284,11 @@ static int sony_laptop_input_keycode_map[] = { KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ - KEY_EJECTCD /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ + KEY_EJECTCD, /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */ + KEY_F13, /* 52 SONYPI_EVENT_MODEKEY_PRESSED */ + KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */ + KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */ + KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ }; /* release buttons after a short delay if pressed */ @@ -850,7 +858,7 @@ struct sony_nc_event { u8 event; }; -static struct sony_nc_event sony_nc_events[] = { +static struct sony_nc_event sony_100_events[] = { { 0x90, SONYPI_EVENT_PKEY_P1 }, { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x91, SONYPI_EVENT_PKEY_P1 }, @@ -874,6 +882,25 @@ static struct sony_nc_event sony_nc_events[] = { { 0, 0 }, }; +static struct sony_nc_event sony_127_events[] = { + { 0x81, SONYPI_EVENT_MODEKEY_PRESSED }, + { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x82, SONYPI_EVENT_PKEY_P1 }, + { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x83, SONYPI_EVENT_PKEY_P2 }, + { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x84, SONYPI_EVENT_PKEY_P3 }, + { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x85, SONYPI_EVENT_PKEY_P4 }, + { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x86, SONYPI_EVENT_PKEY_P5 }, + { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED }, + { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0, 0 }, +}; + /* * ACPI callbacks */ @@ -884,27 +911,41 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) if (ev >= 0x90) { /* New-style event */ - int origev = ev; + int key_handle = 0; ev -= 0x90; - if (sony_find_snc_handle(0x100) == ev) { - int i; + if (sony_find_snc_handle(0x100) == ev) + key_handle = 0x100; + if (sony_find_snc_handle(0x127) == ev) + key_handle = 0x127; - if (sony_call_snc_handle(0x100, 0x200, &result)) - dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); + if (handle) { + struct sony_nc_event *key_event; + + if (sony_call_snc_handle(key_handle, 0x200, &result)) + dprintk("sony_acpi_notify, unable to decode" + " event 0x%.2x 0x%.2x\n", key_handle, + ev); else ev = result & 0xFF; - for (i = 0; sony_nc_events[i].event; i++) { - if (sony_nc_events[i].data == ev) { - ev = sony_nc_events[i].event; + if (key_handle == 0x100) + key_event = sony_100_events; + else + key_event = sony_127_events; + + for (; key_event->data; key_event++) { + if (key_event->data == ev) { + ev = key_event->event; break; } } - if (!sony_nc_events[i].data) + if (!key_event->data) { printk(KERN_INFO DRV_PFX - "Unknown event: %x %x\n", origev, ev); + "Unknown event: 0x%x 0x%x\n", key_handle, + ev); + } } else if (sony_find_snc_handle(0x124) == ev) { sony_nc_rfkill_update(); return; diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h index 8458dbe95862..bb835019ac7f 100644 --- a/include/linux/sonypi.h +++ b/include/linux/sonypi.h @@ -104,6 +104,10 @@ #define SONYPI_EVENT_ZOOM_IN_PRESSED 62 #define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 #define SONYPI_EVENT_CD_EJECT_PRESSED 64 +#define SONYPI_EVENT_MODEKEY_PRESSED 65 +#define SONYPI_EVENT_PKEY_P4 66 +#define SONYPI_EVENT_PKEY_P5 67 +#define SONYPI_EVENT_SETTINGKEY_PRESSED 68 /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) From e93c8a6819b217f4f4a490f67f26e02ff6b23b44 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 26 Mar 2009 21:58:17 +0900 Subject: [PATCH 059/140] sony-laptop: merge Type4 into Type3 Creating Type4 was a mistake in the first place. Some users report that also Type3 vaios require the same extra hotkey handling which the Type4 for was menat to guard from. Merging down Type4 into Type3 will just remove a useless distinction. Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index e000c9f6cdf5..3e45c65b8f81 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1423,7 +1423,6 @@ static struct acpi_driver sony_nc_driver = { #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE2_OFFSET 0x12 #define SONYPI_TYPE3_OFFSET 0x12 -#define SONYPI_TYPE4_OFFSET 0x12 struct sony_pic_ioport { struct acpi_resource_io io1; @@ -1666,14 +1665,6 @@ static struct sonypi_eventtypes type3_events[] = { { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, - { 0 }, -}; -static struct sonypi_eventtypes type4_events[] = { - { 0, 0xffffffff, sonypi_releaseev }, - { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, - { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, - { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, - { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, @@ -1739,11 +1730,11 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) /* * minidrivers for SPIC models */ -static int type4_handle_irq(const u8 data_mask, const u8 ev) +static int type3_handle_irq(const u8 data_mask, const u8 ev) { /* * 0x31 could mean we have to take some extra action and wait for - * the next irq for some Type4 models, it will generate a new + * the next irq for some Type3 models, it will generate a new * irq and we can read new data from the device: * - 0x5c and 0x5f requires 0xA0 * - 0x61 requires 0xB3 @@ -1773,16 +1764,10 @@ static struct device_ctrl spic_types[] = { }, { .model = SONYPI_DEVICE_TYPE3, - .handle_irq = NULL, + .handle_irq = type3_handle_irq, .evport_offset = SONYPI_TYPE3_OFFSET, .event_types = type3_events, }, - { - .model = SONYPI_DEVICE_TYPE4, - .handle_irq = type4_handle_irq, - .evport_offset = SONYPI_TYPE4_OFFSET, - .event_types = type4_events, - }, }; static void sony_pic_detect_device_type(struct sony_pic_dev *dev) @@ -1806,14 +1791,14 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev) pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, NULL); if (pcidev) { - dev->control = &spic_types[3]; + dev->control = &spic_types[2]; goto out; } pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, NULL); if (pcidev) { - dev->control = &spic_types[3]; + dev->control = &spic_types[2]; goto out; } @@ -1826,8 +1811,7 @@ out: printk(KERN_INFO DRV_PFX "detected Type%d model\n", dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : - dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : - dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); + dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3); } /* camera tests and poweron/poweroff */ From 1cae71032183776e833036fe828315dcd3444df1 Mon Sep 17 00:00:00 2001 From: Harald Jenny Date: Thu, 26 Mar 2009 21:58:18 +0900 Subject: [PATCH 060/140] sony-laptop: VGN-A317M hotkey support This laptop has 5 SPIC managed buttons above the keyboard: sound + and - as well as brightness, zoom and S1. Possibly the entire VGN-A serie behaves the same. Signed-off-by: Harald Jenny Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 22 ++++++++++++++++++++++ include/linux/sonypi.h | 3 +++ 2 files changed, 25 insertions(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3e45c65b8f81..4f932889569b 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -230,6 +230,9 @@ static int sony_laptop_input_index[] = { 53, /* 66 SONYPI_EVENT_PKEY_P4 */ 54, /* 67 SONYPI_EVENT_PKEY_P5 */ 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */ + 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ + 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ + -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ }; static int sony_laptop_input_keycode_map[] = { @@ -289,6 +292,8 @@ static int sony_laptop_input_keycode_map[] = { KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */ KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */ KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ + KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ + KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ }; /* release buttons after a short delay if pressed */ @@ -1555,6 +1560,7 @@ static struct sonypi_event sonypi_pkeyev[] = { { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, + { 0x20, SONYPI_EVENT_PKEY_P1 }, { 0, 0 } }; @@ -1598,6 +1604,7 @@ static struct sonypi_event sonypi_zoomev[] = { { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, + { 0x04, SONYPI_EVENT_ZOOM_PRESSED }, { 0, 0 } }; @@ -1628,6 +1635,19 @@ static struct sonypi_event sonypi_batteryev[] = { { 0, 0 } }; +/* The set of possible volume events */ +static struct sonypi_event sonypi_volumeev[] = { + { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED }, + { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED }, + { 0, 0 } +}; + +/* The set of possible brightness events */ +static struct sonypi_event sonypi_brightnessev[] = { + { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED }, + { 0, 0 } +}; + static struct sonypi_eventtypes type1_events[] = { { 0, 0xffffffff, sonypi_releaseev }, { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, @@ -1668,6 +1688,8 @@ static struct sonypi_eventtypes type3_events[] = { { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, + { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev }, + { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev }, { 0 }, }; diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h index bb835019ac7f..34c4475ac4a2 100644 --- a/include/linux/sonypi.h +++ b/include/linux/sonypi.h @@ -108,6 +108,9 @@ #define SONYPI_EVENT_PKEY_P4 66 #define SONYPI_EVENT_PKEY_P5 67 #define SONYPI_EVENT_SETTINGKEY_PRESSED 68 +#define SONYPI_EVENT_VOLUME_INC_PRESSED 69 +#define SONYPI_EVENT_VOLUME_DEC_PRESSED 70 +#define SONYPI_EVENT_BRIGHTNESS_PRESSED 71 /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) From 2b24ef093aec6d7b9c18af75644ec22b4069b283 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 26 Mar 2009 21:58:19 +0900 Subject: [PATCH 061/140] sony-laptop: Eliminate BKL in ioctls Signed-off-by: Alan Cox Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 4f932889569b..813d0e03d9c5 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2224,8 +2224,8 @@ static int ec_read16(u8 addr, u16 *value) return 0; } -static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, - unsigned int cmd, unsigned long arg) +static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd, + unsigned long arg) { int ret = 0; void __user *argp = (void __user *)arg; @@ -2359,7 +2359,7 @@ static const struct file_operations sonypi_misc_fops = { .open = sonypi_misc_open, .release = sonypi_misc_release, .fasync = sonypi_misc_fasync, - .ioctl = sonypi_misc_ioctl, + .unlocked_ioctl = sonypi_misc_ioctl, }; static struct miscdevice sonypi_misc_device = { From d5b02695d5471b38064efeba2b102bd5ead55297 Mon Sep 17 00:00:00 2001 From: ISHIKAWA Mutsumi Date: Thu, 26 Mar 2009 21:58:20 +0900 Subject: [PATCH 062/140] sony-laptop: detect the ICH9 chipset as Type3 Signed-off-by: ISHIKAWA Mutsumi Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 813d0e03d9c5..5030f991906a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1824,6 +1824,13 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev) goto out; } + pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_ICH9_1, NULL); + if (pcidev) { + dev->control = &spic_types[2]; + goto out; + } + /* default */ dev->control = &spic_types[1]; From 3ad1b7619959c0387a30e05c6f36537190b6da7b Mon Sep 17 00:00:00 2001 From: Sergey Yanovich Date: Thu, 26 Mar 2009 21:58:21 +0900 Subject: [PATCH 063/140] sony-laptop: notify the hardware of a state change in wwanpower Signed-off-by: Sergey Yanovich Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5030f991906a..74df72321aeb 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2004,6 +2004,7 @@ static void sony_pic_set_wwanpower(u8 state) return; } sony_pic_call2(0xB0, state); + sony_pic_call1(0x82); spic_dev.wwan_power = state; mutex_unlock(&spic_dev.lock); } From f5acf5e898618295895b61d81681ae3115d94b96 Mon Sep 17 00:00:00 2001 From: Anton Veretenenko Date: Thu, 26 Mar 2009 22:44:26 +0900 Subject: [PATCH 064/140] sony-laptop: Add FW specific hotkey events Signed-off-by: Anton Veretenenko Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 74df72321aeb..3575a2d8f1ce 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -870,6 +870,12 @@ static struct sony_nc_event sony_100_events[] = { { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, + { 0x82, SONYPI_EVENT_FNKEY_F2 }, + { 0x02, SONYPI_EVENT_FNKEY_RELEASED }, + { 0x83, SONYPI_EVENT_FNKEY_F3 }, + { 0x03, SONYPI_EVENT_FNKEY_RELEASED }, + { 0x84, SONYPI_EVENT_FNKEY_F4 }, + { 0x04, SONYPI_EVENT_FNKEY_RELEASED }, { 0x85, SONYPI_EVENT_FNKEY_F5 }, { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, { 0x86, SONYPI_EVENT_FNKEY_F6 }, From c9f1e6f67ad6d16c11586a4550fd054d7538eb92 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 26 Mar 2009 21:58:23 +0900 Subject: [PATCH 065/140] sony-laptop: Make sony_pic_set_wwanpower not take mutexes For consistency with __sony_pic_set_bluetoothpower, this is also needed later to allow setting the wwanpower attribute from the resume path and only lock the mutex once. Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 3575a2d8f1ce..8796dc69950e 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2001,18 +2001,14 @@ int sony_pic_camera_command(int command, u8 value) EXPORT_SYMBOL(sony_pic_camera_command); /* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ -static void sony_pic_set_wwanpower(u8 state) +static void __sony_pic_set_wwanpower(u8 state) { state = !!state; - mutex_lock(&spic_dev.lock); - if (spic_dev.wwan_power == state) { - mutex_unlock(&spic_dev.lock); + if (spic_dev.wwan_power == state) return; - } sony_pic_call2(0xB0, state); sony_pic_call1(0x82); spic_dev.wwan_power = state; - mutex_unlock(&spic_dev.lock); } static ssize_t sony_pic_wwanpower_store(struct device *dev, @@ -2024,7 +2020,9 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev, return -EINVAL; value = simple_strtoul(buffer, NULL, 10); - sony_pic_set_wwanpower(value); + mutex_lock(&spic_dev.lock); + __sony_pic_set_wwanpower(value); + mutex_unlock(&spic_dev.lock); return count; } From 3741834775de035bdf0cd1ce44862bb8c775a4fa Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 26 Mar 2009 21:58:24 +0900 Subject: [PATCH 066/140] sony-laptop: update copyright Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 8796dc69950e..fc0dd63e672d 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2,7 +2,7 @@ * ACPI Sony Notebook Control Driver (SNC and SPIC) * * Copyright (C) 2004-2005 Stelian Pop - * Copyright (C) 2007 Mattia Dongili + * Copyright (C) 2007-2009 Mattia Dongili * * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c * which are copyrighted by their respective authors. From 4ef4cbb3686f9265da87bc6e482162c96f415427 Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Thu, 26 Mar 2009 21:58:25 +0900 Subject: [PATCH 067/140] sony-laptop: Kill the BKL Signed-off-by: Alessio Igor Bogani Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index fc0dd63e672d..0f710317a94e 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include @@ -2180,10 +2179,15 @@ static int sonypi_misc_release(struct inode *inode, struct file *file) static int sonypi_misc_open(struct inode *inode, struct file *file) { /* Flush input queue on first open */ - lock_kernel(); + unsigned long flags; + + spin_lock_irqsave(sonypi_compat.fifo->lock, flags); + if (atomic_inc_return(&sonypi_compat.open_count) == 1) - kfifo_reset(sonypi_compat.fifo); - unlock_kernel(); + __kfifo_reset(sonypi_compat.fifo); + + spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); + return 0; } From 81d0273df20edff275e2eefe6b50436af3bdf9e8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:49:38 -0600 Subject: [PATCH 068/140] ACPI: skip DMI power state check when ACPI disabled This patch makes acpi_init() exit early when ACPI is disabled. This skips a DMI check that affects ACPI power management. The DMI check prints a notice that is misleading when ACPI is disabled. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 2e90410a3035..bdeed39c3d38 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -869,6 +869,10 @@ static int __init acpi_init(void) } } else disable_acpi(); + + if (acpi_disabled) + return result; + /* * If the laptop falls into the DMI check table, the power state check * will be disabled in the course of device power transistion. From e747f274951507b5a0850155c3d709e26d20de5b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:49:43 -0600 Subject: [PATCH 069/140] ACPI: call acpi_scan_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_scan_init() directly. Previously, both acpi_init() and acpi_scan_init() were subsys_initcalls, and acpi_init() was called first based on the link order from the makefile (bus.o before scan.o). acpi_scan_init() registers the ACPI bus type, creates the root device, and enumerates fixed-feature and namespace devices. All of this must be done after acpi_init(), and it's better to call acpi_scan_init() explicitly rather than rely on the link ordering. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 2 ++ drivers/acpi/internal.h | 2 ++ drivers/acpi/scan.c | 9 +-------- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index bdeed39c3d38..cdd11fda5036 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -878,6 +878,8 @@ static int __init acpi_init(void) * will be disabled in the course of device power transistion. */ dmi_check_system(power_nocheck_dmi_table); + + acpi_scan_init(); return result; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 4aee4a236fc9..28042c0f2fff 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -1,5 +1,7 @@ /* For use by Linux/ACPI infrastructure, not drivers */ +int acpi_scan_init(void); + /* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2f04cd1147e9..c548231965ef 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1526,16 +1526,11 @@ static int acpi_bus_scan_fixed(struct acpi_device *root) return result; } - -static int __init acpi_scan_init(void) +int __init acpi_scan_init(void) { int result; struct acpi_bus_ops ops; - - if (acpi_disabled) - return 0; - memset(&ops, 0, sizeof(ops)); ops.acpi_op_add = 1; ops.acpi_op_start = 1; @@ -1568,5 +1563,3 @@ static int __init acpi_scan_init(void) Done: return result; } - -subsys_initcall(acpi_scan_init); From a5f820feb54a59fcdaf4a67a6381ea1ddb36cc6e Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:49:48 -0600 Subject: [PATCH 070/140] ACPI: call acpi_ec_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_ec_init() directly. Previously, both were subsys_initcalls. acpi_ec_init() must happen after acpi_init(), and it's better to call it explicitly rather than rely on link ordering. Signed-off-by: Bjorn Helgaas CC: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/ec.c | 7 +------ drivers/acpi/internal.h | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cdd11fda5036..9ca683794370 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -880,6 +880,7 @@ static int __init acpi_init(void) dmi_check_system(power_nocheck_dmi_table); acpi_scan_init(); + acpi_ec_init(); return result; } diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2fe15060dcdc..bf88f1803801 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -1069,13 +1069,10 @@ static struct acpi_driver acpi_ec_driver = { }, }; -static int __init acpi_ec_init(void) +int __init acpi_ec_init(void) { int result = 0; - if (acpi_disabled) - return 0; - acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir); if (!acpi_ec_dir) return -ENODEV; @@ -1090,8 +1087,6 @@ static int __init acpi_ec_init(void) return result; } -subsys_initcall(acpi_ec_init); - /* EC driver currently not unloadable */ #if 0 static void __exit acpi_ec_exit(void) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 28042c0f2fff..fad8e38ed271 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -17,6 +17,7 @@ extern int acpi_power_nocheck; /* -------------------------------------------------------------------------- Embedded Controller -------------------------------------------------------------------------- */ +int acpi_ec_init(void); int acpi_ec_ecdt_probe(void); int acpi_boot_ec_enable(void); From 44515374cba9e46d5622256b43eb06b9c349cee1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:49:53 -0600 Subject: [PATCH 071/140] ACPI: call acpi_power_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_power_init() directly. Previously, both were subsys_initcalls. acpi_power_init() must happen after acpi_init(), and it's better to call it explicitly rather than rely on link ordering. Signed-off-by: Bjorn Helgaas CC: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/internal.h | 2 +- drivers/acpi/power.c | 8 +------- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9ca683794370..946610f00aa1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -881,6 +881,7 @@ static int __init acpi_init(void) acpi_scan_init(); acpi_ec_init(); + acpi_power_init(); return result; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index fad8e38ed271..a8178add7fd1 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -5,7 +5,7 @@ int acpi_scan_init(void); /* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ - +int acpi_power_init(void); int acpi_device_sleep_wake(struct acpi_device *dev, int enable, int sleep_state, int dev_state); int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state); diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index c926e7d4a0d6..11968ba28feb 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -773,14 +773,10 @@ static int acpi_power_resume(struct acpi_device *device) return 0; } -static int __init acpi_power_init(void) +int __init acpi_power_init(void) { int result = 0; - - if (acpi_disabled) - return 0; - INIT_LIST_HEAD(&acpi_power_resource_list); acpi_power_dir = proc_mkdir(ACPI_POWER_CLASS, acpi_root_dir); @@ -795,5 +791,3 @@ static int __init acpi_power_init(void) return 0; } - -subsys_initcall(acpi_power_init); From 141a0af3cab7de690816b17aad1682050219f774 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:49:58 -0600 Subject: [PATCH 072/140] ACPI: call acpi_system_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_system_init() directly. Previously, both were subsys_initcalls. acpi_system_init() must happen after acpi_init(), and it's better to call it explicitly rather than rely on link ordering. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/internal.h | 1 + drivers/acpi/system.c | 9 ++------- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 946610f00aa1..c13307279f7e 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -882,6 +882,7 @@ static int __init acpi_init(void) acpi_scan_init(); acpi_ec_init(); acpi_power_init(); + acpi_system_init(); return result; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a8178add7fd1..4a35f6e819d3 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -1,6 +1,7 @@ /* For use by Linux/ACPI infrastructure, not drivers */ int acpi_scan_init(void); +int acpi_system_init(void); /* -------------------------------------------------------------------------- Power Resource diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 391d0358a592..3b88981dd215 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -571,12 +571,9 @@ static int acpi_system_procfs_init(void) } #endif -static int __init acpi_system_init(void) +int __init acpi_system_init(void) { - int result = 0; - - if (acpi_disabled) - return 0; + int result; result = acpi_system_procfs_init(); if (result) @@ -586,5 +583,3 @@ static int __init acpi_system_init(void) return result; } - -subsys_initcall(acpi_system_init); From 84f810c33f695e020776ce66c903e0b41872f1b2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:50:03 -0600 Subject: [PATCH 073/140] ACPI: call acpi_debug_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_debug_init() directly. Previously, both were subsys_initcalls. acpi_debug_init() must happen after acpi_init(), and it's better to call it explicitly rather than rely on link ordering. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/debug.c | 14 ++++++-------- drivers/acpi/internal.h | 6 ++++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index c13307279f7e..f32cfd64c999 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -883,6 +883,7 @@ static int __init acpi_init(void) acpi_ec_init(); acpi_power_init(); acpi_system_init(); + acpi_debug_init(); return result; } diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 20223cbd0d1c..9cb189f3c77c 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -297,17 +297,15 @@ acpi_system_write_debug(struct file *file, return count; } +#endif -static int __init acpi_debug_init(void) +int __init acpi_debug_init(void) { +#ifdef CONFIG_ACPI_PROCFS struct proc_dir_entry *entry; int error = 0; char *name; - - if (acpi_disabled) - return 0; - /* 'debug_layer' [R/W] */ name = ACPI_SYSTEM_FILE_DEBUG_LAYER; entry = @@ -338,7 +336,7 @@ static int __init acpi_debug_init(void) remove_proc_entry(ACPI_SYSTEM_FILE_DEBUG_LAYER, acpi_root_dir); error = -ENODEV; goto Done; -} - -subsys_initcall(acpi_debug_init); +#else + return 0; #endif +} diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 4a35f6e819d3..44b84021d84d 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -3,6 +3,12 @@ int acpi_scan_init(void); int acpi_system_init(void); +#ifdef CONFIG_ACPI_DEBUG +int acpi_debug_init(void); +#else +static inline int acpi_debug_init(void) { return 0; } +#endif + /* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ From 0e46517d9660ee6ae0a0c5d8a4e50451bc84d61d Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:50:09 -0600 Subject: [PATCH 074/140] ACPI: call init_acpi_device_notify() explicitly rather than as initcall This patch makes acpi_init() call init_acpi_device_notify() directly. Previously, init_acpi_device_notify() was an arch_initcall (sequence 3), so it was called before acpi_init() (a subsys_initcall at sequence 4). init_acpi_device_notify() sets the platform_notify and platform_notify_remove function pointers. These pointers are not used until acpi_init() enumerates ACPI devices in this path: acpi_init() acpi_scan_init() acpi_bus_scan() acpi_add_single_object() acpi_device_register() device_add() So it is sufficient to have acpi_init() call init_acpi_device_notify() directly before it enumerates devices. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/glue.c | 6 +----- drivers/acpi/internal.h | 1 + 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index f32cfd64c999..db9eca8d3cf2 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -855,6 +855,7 @@ static int __init acpi_init(void) acpi_kobj = NULL; } + init_acpi_device_notify(); result = acpi_bus_init(); if (!result) { diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 5479b9f42513..8bd2c2a6884d 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -286,10 +286,8 @@ static int acpi_platform_notify_remove(struct device *dev) return 0; } -static int __init init_acpi_device_notify(void) +int __init init_acpi_device_notify(void) { - if (acpi_disabled) - return 0; if (platform_notify || platform_notify_remove) { printk(KERN_ERR PREFIX "Can't use platform_notify\n"); return 0; @@ -298,5 +296,3 @@ static int __init init_acpi_device_notify(void) platform_notify_remove = acpi_platform_notify_remove; return 0; } - -arch_initcall(init_acpi_device_notify); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 44b84021d84d..8a45dd8e03b5 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -1,5 +1,6 @@ /* For use by Linux/ACPI infrastructure, not drivers */ +int init_acpi_device_notify(void); int acpi_scan_init(void); int acpi_system_init(void); From 9cee43e07940bee13462e63bd75ce4430b155886 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:50:14 -0600 Subject: [PATCH 075/140] ACPI: call acpi_sleep_proc_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_sleep_proc_init() directly. Previously, acpi_sleep_proc_init() was a late_initcall (sequence 7), apparently to make sure that the /proc hierarchy already exists: 2003/02/13 12:38:03-06:00 mochel acpi sleep: demote sleep proc file creation. - Make acpi_sleep_proc_init() a late_initcall(), and not called from acpi_sleep_init(). This guarantees that the acpi proc hierarchy is at least there when we create the dang file. This should no longer be an issue because acpi_bus_init() (called early in acpi_init()) creates acpi_root_dir (/proc/acpi). Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/internal.h | 6 ++++++ drivers/acpi/proc.c | 7 +------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index db9eca8d3cf2..a812e841cb64 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -885,6 +885,7 @@ static int __init acpi_init(void) acpi_power_init(); acpi_system_init(); acpi_debug_init(); + acpi_sleep_proc_init(); return result; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8a45dd8e03b5..8870e5fd8494 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -33,3 +33,9 @@ int acpi_boot_ec_enable(void); Suspend/Resume -------------------------------------------------------------------------- */ extern int acpi_sleep_init(void); + +#ifdef CONFIG_ACPI_SLEEP +int acpi_sleep_proc_init(void); +#else +static inline int acpi_sleep_proc_init(void) { return 0; } +#endif diff --git a/drivers/acpi/proc.c b/drivers/acpi/proc.c index 428c911dba08..05dfdc96802e 100644 --- a/drivers/acpi/proc.c +++ b/drivers/acpi/proc.c @@ -496,11 +496,8 @@ static u32 rtc_handler(void *context) } #endif /* HAVE_ACPI_LEGACY_ALARM */ -static int __init acpi_sleep_proc_init(void) +int __init acpi_sleep_proc_init(void) { - if (acpi_disabled) - return 0; - #ifdef CONFIG_ACPI_PROCFS /* 'sleep' [R/W] */ proc_create("sleep", S_IFREG | S_IRUGO | S_IWUSR, @@ -527,5 +524,3 @@ static int __init acpi_sleep_proc_init(void) return 0; } - -late_initcall(acpi_sleep_proc_init); From 201b8c655f7a48563f6a0b66f9e388460a1ea611 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:50:19 -0600 Subject: [PATCH 076/140] ACPI: call acpi_wakeup_device_init() explicitly rather than as initcall This patch makes acpi_init() call acpi_wakeup_device_init() directly. Previously, acpi_wakeup_device_init() was a late_initcall (sequence 7). acpi_wakeup_device_init() depends on acpi_wakeup_device_list, which is populated when ACPI devices are enumerated by acpi_init() -> acpi_scan_init(). Using late_initcall is certainly enough to make sure acpi_wakeup_device_list is populated, but it is more than necessary. We can just as easily call acpi_wakeup_device_init() directly from acpi_init(), which avoids the initcall magic. Signed-off-by: Bjorn Helgaas CC: Li Shaohua Signed-off-by: Len Brown --- drivers/acpi/bus.c | 1 + drivers/acpi/internal.h | 2 ++ drivers/acpi/wakeup.c | 7 +------ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a812e841cb64..7fe0945f7bcf 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -886,6 +886,7 @@ static int __init acpi_init(void) acpi_system_init(); acpi_debug_init(); acpi_sleep_proc_init(); + acpi_wakeup_device_init(); return result; } diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 8870e5fd8494..11a69b53004e 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -22,6 +22,8 @@ int acpi_power_get_inferred_state(struct acpi_device *device); int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; +int acpi_wakeup_device_init(void); + /* -------------------------------------------------------------------------- Embedded Controller -------------------------------------------------------------------------- */ diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c index 3f29fd53e9a6..5aee8c26cc9f 100644 --- a/drivers/acpi/wakeup.c +++ b/drivers/acpi/wakeup.c @@ -138,13 +138,10 @@ void acpi_disable_wakeup_device(u8 sleep_state) spin_unlock(&acpi_device_lock); } -static int __init acpi_wakeup_device_init(void) +int __init acpi_wakeup_device_init(void) { struct list_head *node, *next; - if (acpi_disabled) - return 0; - spin_lock(&acpi_device_lock); list_for_each_safe(node, next, &acpi_wakeup_device_list) { struct acpi_device *dev = container_of(node, @@ -165,5 +162,3 @@ static int __init acpi_wakeup_device_init(void) spin_unlock(&acpi_device_lock); return 0; } - -late_initcall(acpi_wakeup_device_init); From 018f452e9d9d0cb5c3e8d33fd94dc6cd3c520a8f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 16:50:24 -0600 Subject: [PATCH 077/140] ACPI: tidy up makefile This patch removes the suggestion that ec.o link order is important, because it doesn't matter since acpi_ec_init() is no longer an initcall. And it puts together most of the core modules that are not configurable. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/Makefile | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b130ea0d0759..61675e21fba2 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -32,10 +32,8 @@ ifdef CONFIG_CPU_FREQ processor-objs += processor_perflib.o endif -obj-y += bus.o glue.o -obj-y += scan.o -# Keep EC driver first. Initialization of others depend on it. -obj-y += ec.o +obj-y += bus.o glue.o scan.o ec.o \ + power.o system.o event.o obj-$(CONFIG_ACPI_AC) += ac.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o @@ -51,8 +49,6 @@ obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o obj-$(CONFIG_ACPI_CONTAINER) += container.o obj-$(CONFIG_ACPI_THERMAL) += thermal.o -obj-y += power.o -obj-y += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o From fb318cbff40964999f303d50bcf541dd9ead6780 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Wed, 18 Mar 2009 09:09:01 +0800 Subject: [PATCH 078/140] ACPI: cpufreq: use new bit register access function > arch/x86/kernel/cpu/cpufreq/longhaul.c: In function 'longhaul_setstate': > arch/x86/kernel/cpu/cpufreq/longhaul.c:308: error: implicit declaration of function 'acpi_set_register' Signed-off-by: Lin Ming Compile-tested-by: Stephen Rothwell Signed-off-by: Len Brown --- arch/x86/kernel/cpu/cpufreq/longhaul.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c index a4cff5d6e380..4e18d5119828 100644 --- a/arch/x86/kernel/cpu/cpufreq/longhaul.c +++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c @@ -303,7 +303,7 @@ retry_loop: outb(3, 0x22); } else if ((pr != NULL) && pr->flags.bm_control) { /* Disable bus master arbitration */ - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); + acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); } switch (longhaul_version) { @@ -326,7 +326,7 @@ retry_loop: case TYPE_POWERSAVER: if (longhaul_flags & USE_ACPI_C3) { /* Don't allow wakeup */ - acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); + acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 0); do_powersaver(cx->address, clock_ratio_index, dir); } else { do_powersaver(0, clock_ratio_index, dir); @@ -339,7 +339,7 @@ retry_loop: outb(0, 0x22); } else if ((pr != NULL) && pr->flags.bm_control) { /* Enable bus master arbitration */ - acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); + acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); } outb(pic2_mask,0xA1); /* restore mask */ outb(pic1_mask,0x21); From f6f5c45e06e86d94621cd5c1c4508bdee1952fc8 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Tue, 3 Mar 2009 12:47:17 +1100 Subject: [PATCH 079/140] ACPI: update thermal for bus_id removal > drivers/acpi/thermal.c: In function 'thermal_notify': > drivers/acpi/thermal.c:768: error: 'struct device' has no member named 'bus_id' > > Caused by commit b1569e99c795bf83b4ddf41c4f1c42761ab7f75e ("ACPI: move > thermal trip handling to generic thermal layer") interacting with commit > d4a078fca590911cdf87a8eaffee1b6e643c2558 ("driver core: get rid of struct > device's bus_id string array"). > Signed-off-by: Stephen Rothwell Signed-off-by: Len Brown --- drivers/acpi/thermal.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 0ec48d2f85c5..6b959976b7a4 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -765,7 +766,7 @@ static int thermal_notify(struct thermal_zone_device *thermal, int trip, acpi_bus_generate_proc_event(tz->device, type, 1); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, - tz->device->dev.bus_id, type, 1); + dev_name(&tz->device->dev), type, 1); if (trip_type == THERMAL_TRIP_CRITICAL && nocrt) return 1; From 03a971a2899886006f19f3495973bbd646d8bdae Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 3 Dec 2008 18:00:38 +0000 Subject: [PATCH 080/140] thermal: support forcing support for passive cooling Due to poor thermal design or Linux driving hardware outside its thermal envelope, some systems will reach critical temperature and shut down under high load. This patch adds support for forcing a polling-based passive trip point if the firmware doesn't provide one. The assumption is made that the processor is the most practical means to reduce the dynamic heat generation, so hitting the passive thermal limit will cause the CPU to be throttled until the temperature stabalises around the defined value. UI is provided via a "passive" sysfs entry in the thermal zone directory. It accepts a decimal value in millidegrees celsius, or "0" to disable the functionality. Default behaviour is for this functionality to be disabled. Signed-off-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/thermal/thermal_sys.c | 77 +++++++++++++++++++++++++++++++++++ include/linux/thermal.h | 1 + 2 files changed, 78 insertions(+) diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 6378741882f3..d0b093b66adc 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -214,9 +214,69 @@ trip_point_temp_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%ld\n", temperature); } +static ssize_t +passive_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + struct thermal_cooling_device *cdev = NULL; + int state; + + if (!sscanf(buf, "%d\n", &state)) + return -EINVAL; + + if (state && !tz->forced_passive) { + mutex_lock(&thermal_list_lock); + list_for_each_entry(cdev, &thermal_cdev_list, node) { + if (!strncmp("Processor", cdev->type, + sizeof("Processor"))) + thermal_zone_bind_cooling_device(tz, + THERMAL_TRIPS_NONE, + cdev); + } + mutex_unlock(&thermal_list_lock); + } else if (!state && tz->forced_passive) { + mutex_lock(&thermal_list_lock); + list_for_each_entry(cdev, &thermal_cdev_list, node) { + if (!strncmp("Processor", cdev->type, + sizeof("Processor"))) + thermal_zone_unbind_cooling_device(tz, + THERMAL_TRIPS_NONE, + cdev); + } + mutex_unlock(&thermal_list_lock); + } + + tz->tc1 = 1; + tz->tc2 = 1; + + if (!tz->passive_delay) + tz->passive_delay = 1000; + + if (!tz->polling_delay) + tz->polling_delay = 10000; + + tz->forced_passive = state; + + thermal_zone_device_update(tz); + + return count; +} + +static ssize_t +passive_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct thermal_zone_device *tz = to_thermal_zone(dev); + + return sprintf(buf, "%d\n", tz->forced_passive); +} + static DEVICE_ATTR(type, 0444, type_show, NULL); static DEVICE_ATTR(temp, 0444, temp_show, NULL); static DEVICE_ATTR(mode, 0644, mode_show, mode_store); +static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \ + passive_store); static struct device_attribute trip_point_attrs[] = { __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), @@ -939,6 +999,11 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) break; } } + + if (tz->forced_passive) + thermal_zone_device_passive(tz, temp, tz->forced_passive, + THERMAL_TRIPS_NONE); + tz->last_temperature = temp; if (tz->passive) thermal_zone_device_set_polling(tz, tz->passive_delay); @@ -977,8 +1042,10 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, { struct thermal_zone_device *tz; struct thermal_cooling_device *pos; + enum thermal_trip_type trip_type; int result; int count; + int passive = 0; if (strlen(type) >= THERMAL_NAME_LENGTH) return ERR_PTR(-EINVAL); @@ -1041,8 +1108,18 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, TRIP_POINT_ATTR_ADD(&tz->device, count, result); if (result) goto unregister; + tz->ops->get_trip_type(tz, count, &trip_type); + if (trip_type == THERMAL_TRIP_PASSIVE) + passive = 1; } + if (!passive) + result = device_create_file(&tz->device, + &dev_attr_passive); + + if (result) + goto unregister; + result = thermal_add_hwmon_sysfs(tz); if (result) goto unregister; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index a81c61521ba4..1de8b9eb841b 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -113,6 +113,7 @@ struct thermal_zone_device { int polling_delay; int last_temperature; bool passive; + unsigned int forced_passive; struct thermal_zone_device_ops *ops; struct list_head cooling_devices; struct idr idr; From 93b3e78a93a2f49415608929f9ffeb60adc8a4a8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 10:55:22 -0600 Subject: [PATCH 081/140] ACPI: remove unused acpi_device_ops .lock and .scan methods No drivers use the .lock and .scan methods, and the Linux/ACPI code doesn't even provide a way to invoke them, so remove them. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- include/acpi/acpi_bus.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e9f6574930ef..e3c5a4e81262 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -88,13 +88,11 @@ struct acpi_device; typedef int (*acpi_op_add) (struct acpi_device * device); typedef int (*acpi_op_remove) (struct acpi_device * device, int type); -typedef int (*acpi_op_lock) (struct acpi_device * device, int type); typedef int (*acpi_op_start) (struct acpi_device * device); typedef int (*acpi_op_stop) (struct acpi_device * device, int type); typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state); typedef int (*acpi_op_resume) (struct acpi_device * device); -typedef int (*acpi_op_scan) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device); typedef int (*acpi_op_shutdown) (struct acpi_device * device); @@ -117,12 +115,10 @@ struct acpi_bus_ops { struct acpi_device_ops { acpi_op_add add; acpi_op_remove remove; - acpi_op_lock lock; acpi_op_start start; acpi_op_stop stop; acpi_op_suspend suspend; acpi_op_resume resume; - acpi_op_scan scan; acpi_op_bind bind; acpi_op_unbind unbind; acpi_op_shutdown shutdown; From c0ce093f5b8bc3262c51bd0b5900424a67909831 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 10:55:27 -0600 Subject: [PATCH 082/140] ACPI: remove unused acpi_device_ops .shutdown method No drivers use the .shutdown method, so remove it. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- drivers/acpi/scan.c | 12 ------------ include/acpi/acpi_bus.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index c54d7b6c4066..4a6c7ee834ff 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -395,22 +395,10 @@ static int acpi_device_remove(struct device * dev) return 0; } -static void acpi_device_shutdown(struct device *dev) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_driver *acpi_drv = acpi_dev->driver; - - if (acpi_drv && acpi_drv->ops.shutdown) - acpi_drv->ops.shutdown(acpi_dev); - - return ; -} - struct bus_type acpi_bus_type = { .name = "acpi", .suspend = acpi_device_suspend, .resume = acpi_device_resume, - .shutdown = acpi_device_shutdown, .match = acpi_bus_match, .probe = acpi_device_probe, .remove = acpi_device_remove, diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index e3c5a4e81262..fb91bc213781 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -95,7 +95,6 @@ typedef int (*acpi_op_suspend) (struct acpi_device * device, typedef int (*acpi_op_resume) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device); -typedef int (*acpi_op_shutdown) (struct acpi_device * device); struct acpi_bus_ops { u32 acpi_op_add:1; @@ -121,7 +120,6 @@ struct acpi_device_ops { acpi_op_resume resume; acpi_op_bind bind; acpi_op_unbind unbind; - acpi_op_shutdown shutdown; }; struct acpi_driver { From 8308e8ab70fd5d7b78afb133c51c5079548ba84f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 24 Mar 2009 10:55:33 -0600 Subject: [PATCH 083/140] ACPI: remove unused acpi_bus_ops flags In acpi_bus_ops, only the acpi_op_add and acpi_op_start flags are used, so remove all the rest. Signed-off-by: Bjorn Helgaas Signed-off-by: Len Brown --- include/acpi/acpi_bus.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index fb91bc213781..08ec60c8366a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -98,17 +98,7 @@ typedef int (*acpi_op_unbind) (struct acpi_device * device); struct acpi_bus_ops { u32 acpi_op_add:1; - u32 acpi_op_remove:1; - u32 acpi_op_lock:1; u32 acpi_op_start:1; - u32 acpi_op_stop:1; - u32 acpi_op_suspend:1; - u32 acpi_op_resume:1; - u32 acpi_op_scan:1; - u32 acpi_op_bind:1; - u32 acpi_op_unbind:1; - u32 acpi_op_shutdown:1; - u32 reserved:21; }; struct acpi_device_ops { From e1eb47797ac0773cb3efe7495e14fc26e18a23c2 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 24 Mar 2009 13:41:59 +0100 Subject: [PATCH 084/140] ACPI: Avoid wiping out pr->performance during preregistering When cpufreq driver call acpi_processor_preregister_performance() , function will clean up pr->performance even if there is possibly already registered other cpufreq driver. The patch fix this potential problem. It also remove double checks in P domain basic validity code and move these checks to function where _PSD data is captured. Signed-off-by: Stanislaw Gruszka Signed-off-by: Len Brown --- drivers/acpi/processor_perflib.c | 46 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 9cc769b587ff..215f1bf7d4c1 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -479,6 +479,13 @@ static int acpi_processor_get_psd(struct acpi_processor *pr) goto end; } + if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && + pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && + pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { + printk(KERN_ERR PREFIX "Invalid _PSD:coord_type\n"); + result = -EFAULT; + goto end; + } end: kfree(buffer.pointer); return result; @@ -501,9 +508,10 @@ int acpi_processor_preregister_performance( mutex_lock(&performance_mutex); - retval = 0; - - /* Call _PSD for all CPUs */ + /* + * Check if another driver has already registered, and abort before + * changing pr->performance if it has. Check input data as well. + */ for_each_possible_cpu(i) { pr = per_cpu(processors, i); if (!pr) { @@ -513,13 +521,20 @@ int acpi_processor_preregister_performance( if (pr->performance) { retval = -EBUSY; - continue; + goto err_out; } if (!performance || !percpu_ptr(performance, i)) { retval = -EINVAL; - continue; + goto err_out; } + } + + /* Call _PSD for all CPUs */ + for_each_possible_cpu(i) { + pr = per_cpu(processors, i); + if (!pr) + continue; pr->performance = percpu_ptr(performance, i); cpumask_set_cpu(i, pr->performance->shared_cpu_map); @@ -535,26 +550,6 @@ int acpi_processor_preregister_performance( * Now that we have _PSD data from all CPUs, lets setup P-state * domain info. */ - for_each_possible_cpu(i) { - pr = per_cpu(processors, i); - if (!pr) - continue; - - /* Basic validity check for domain info */ - pdomain = &(pr->performance->domain_info); - if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || - (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) { - retval = -EINVAL; - goto err_ret; - } - if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && - pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && - pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { - retval = -EINVAL; - goto err_ret; - } - } - cpumask_clear(covered_cpus); for_each_possible_cpu(i) { pr = per_cpu(processors, i); @@ -643,6 +638,7 @@ err_ret: pr->performance = NULL; /* Will be set for real in register */ } +err_out: mutex_unlock(&performance_mutex); free_cpumask_var(covered_cpus); return retval; From a59d1637eb0e0a37ee0e5c92800c60abe3624e24 Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" Date: Thu, 19 Mar 2009 14:41:40 -0700 Subject: [PATCH 085/140] ACPI: cap off P-state transition latency from buggy BIOSes Some BIOSes report very high frequency transition latency which are plainly wrong on CPus that can change frequency using native MSR interface. One such system is IBM T42 (2327-8ZU) as reported by Owen Taylor and Rik van Riel. cpufreq_ondemand driver uses this transition latency to come up with a reasonable sampling interval to sample CPU usage and with such high latency value, ondemand sampling interval ends up being very high (0.5 sec, in this particular case), resulting in performance impact due to slow response to increasing frequency. Fix it by capping-off the transition latency to 20uS for native MSR based frequency transitions. mjg: We've confirmed that this also helps on the X31 Signed-off-by: Venkatesh Pallipadi Acked-by: Matthew Garrett Signed-off-by: Len Brown --- arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 4b1c319d30c3..89c676d6caf7 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -680,6 +680,18 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) perf->states[i].transition_latency * 1000; } + /* Check for high latency (>20uS) from buggy BIOSes, like on T42 */ + if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE && + policy->cpuinfo.transition_latency > 20 * 1000) { + static int print_once; + policy->cpuinfo.transition_latency = 20 * 1000; + if (!print_once) { + print_once = 1; + printk(KERN_INFO "Capping off P-state tranision latency" + " at 20 uS\n"); + } + } + data->max_freq = perf->states[0].core_frequency * 1000; /* table init */ for (i=0; istate_count; i++) { From c8890f903a6fdf5711726e8e8d65cb13423f8833 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 18 Mar 2009 16:27:08 +0800 Subject: [PATCH 086/140] ACPI video: check the return value of acpi_video_device_lcd_get_level_current Signed-off-by: Zhang Rui Acked-by: Matthew Garrett Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/video.c | 55 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bb5ed059114a..f0e6eb534161 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -294,7 +294,7 @@ static int acpi_video_device_lcd_get_level_current( unsigned long long *level); static int acpi_video_get_next_level(struct acpi_video_device *device, u32 level_current, u32 event); -static void acpi_video_switch_brightness(struct acpi_video_device *device, +static int acpi_video_switch_brightness(struct acpi_video_device *device, int event); static int acpi_video_device_get_state(struct acpi_video_device *device, unsigned long long *state); @@ -308,7 +308,9 @@ static int acpi_video_get_brightness(struct backlight_device *bd) int i; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - acpi_video_device_lcd_get_level_current(vd, &cur_level); + + if (acpi_video_device_lcd_get_level_current(vd, &cur_level)) + return -EINVAL; for (i = 2; i < vd->brightness->count; i++) { if (vd->brightness->levels[i] == cur_level) /* The first two entries are special - see page 575 @@ -373,7 +375,8 @@ static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) unsigned long long level; int state; - acpi_video_device_lcd_get_level_current(video, &level); + if (acpi_video_device_lcd_get_level_current(video, &level)) + return -EINVAL; for (state = 2; state < video->brightness->count; state++) if (level == video->brightness->levels[state]) return sprintf(buf, "%d\n", @@ -502,11 +505,29 @@ static int acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, unsigned long long *level) { - if (device->cap._BQC) - return acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, - level); + acpi_status status = AE_OK; + + if (device->cap._BQC) { + status = acpi_evaluate_integer(device->dev->handle, "_BQC", + NULL, level); + if (ACPI_SUCCESS(status)) { + device->brightness->curr = *level; + return 0; + } else { + /* Fixme: + * should we return an error or ignore this failure? + * dev->brightness->curr is a cached value which stores + * the correct current backlight level in most cases. + * ACPI video backlight still works w/ buggy _BQC. + * http://bugzilla.kernel.org/show_bug.cgi?id=12233 + */ + ACPI_WARNING((AE_INFO, "Evaluating _BQC failed")); + device->cap._BQC = 0; + } + } + *level = device->brightness->curr; - return AE_OK; + return 0; } static int @@ -1749,15 +1770,29 @@ acpi_video_get_next_level(struct acpi_video_device *device, } } -static void +static int acpi_video_switch_brightness(struct acpi_video_device *device, int event) { unsigned long long level_current, level_next; + int result = -EINVAL; + if (!device->brightness) - return; - acpi_video_device_lcd_get_level_current(device, &level_current); + goto out; + + result = acpi_video_device_lcd_get_level_current(device, + &level_current); + if (result) + goto out; + level_next = acpi_video_get_next_level(device, level_current, event); + acpi_video_device_lcd_set_level(device, level_next); + +out: + if (result) + printk(KERN_ERR PREFIX "Failed to switch the brightness\n"); + + return result; } static int From 24450c7add575cef53097738f16a4c1a720fa5cb Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 18 Mar 2009 16:27:10 +0800 Subject: [PATCH 087/140] ACPI video: check the return value of acpi_video_device_lcd_set_level Signed-off-by: Zhang Rui Acked-by: Matthew Garrett Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/video.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f0e6eb534161..52f52b32b63f 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -322,12 +322,12 @@ static int acpi_video_get_brightness(struct backlight_device *bd) static int acpi_video_set_brightness(struct backlight_device *bd) { - int request_level = bd->props.brightness+2; + int request_level = bd->props.brightness + 2; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - acpi_video_device_lcd_set_level(vd, - vd->brightness->levels[request_level]); - return 0; + + return acpi_video_device_lcd_set_level(vd, + vd->brightness->levels[request_level]); } static struct backlight_ops acpi_backlight_ops = { @@ -482,23 +482,29 @@ acpi_video_device_lcd_query_levels(struct acpi_video_device *device, static int acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) { - int status = AE_OK; + int status; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; int state; - arg0.integer.value = level; - if (device->cap._BCM) - status = acpi_evaluate_object(device->dev->handle, "_BCM", - &args, NULL); + status = acpi_evaluate_object(device->dev->handle, "_BCM", + &args, NULL); + if (ACPI_FAILURE(status)) { + ACPI_ERROR((AE_INFO, "Evaluating _BCM failed")); + return -EIO; + } + device->brightness->curr = level; for (state = 2; state < device->brightness->count; state++) - if (level == device->brightness->levels[state]) + if (level == device->brightness->levels[state]) { device->backlight->props.brightness = state - 2; + return 0; + } - return status; + ACPI_ERROR((AE_INFO, "Current brightness invalid")); + return -EINVAL; } static int @@ -1082,13 +1088,12 @@ acpi_video_device_write_brightness(struct file *file, /* validate through the list of available levels */ for (i = 2; i < dev->brightness->count; i++) if (level == dev->brightness->levels[i]) { - if (ACPI_SUCCESS - (acpi_video_device_lcd_set_level(dev, level))) - dev->brightness->curr = level; + if (!acpi_video_device_lcd_set_level(dev, level)) + return count; break; } - return count; + return -EINVAL; } static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset) @@ -1786,7 +1791,7 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event) level_next = acpi_video_get_next_level(device, level_current, event); - acpi_video_device_lcd_set_level(device, level_next); + result = acpi_video_device_lcd_set_level(device, level_next); out: if (result) From d32f69470c2081ffdfd82740ac19f940790f9e93 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 18 Mar 2009 16:27:12 +0800 Subject: [PATCH 088/140] ACPI video: support _BCL packages that don't export brightness levels when machine is on AC/Battery Many buggy BIOSes don't export the brightness levels when machine is on AC/Battery in the _BCL method. Reformat the _BCL package for these laptops: now the elements in device->brightness->levels[] are like: levels[0]: brightness level when on AC power. levels[1]: brightness level when on Battery power. levels[2]: supported brightness level 1. levels[3]: supported brightness level 2. ... levels[n]: supported brightness level n-1. levels[n + 1]: supported brightness level n. So if there are n supported brightness levels on this laptop, we will have n+2 entries in device->brightnes->levels[]. level[0] and level[1] are invalid on the laptops that don't export the brightness levels on AC/Battery. Fortunately, we never use these two values at all, even for the valid ones. http://bugzilla.kernel.org/show_bug.cgi?id=12249 Signed-off-by: Zhang Rui Acked-by: Matthew Garrett Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/video.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 52f52b32b63f..398b3eee37fb 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -168,10 +168,15 @@ struct acpi_video_device_cap { u8 _DSS:1; /*Device state set */ }; +struct acpi_video_brightness_flags { + u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */ +}; + struct acpi_video_device_brightness { int curr; int count; int *levels; + struct acpi_video_brightness_flags flags; }; struct acpi_video_device { @@ -682,7 +687,7 @@ static int acpi_video_init_brightness(struct acpi_video_device *device) { union acpi_object *obj = NULL; - int i, max_level = 0, count = 0; + int i, max_level = 0, count = 0, level_ac_battery = 0; union acpi_object *o; struct acpi_video_device_brightness *br = NULL; @@ -701,7 +706,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) goto out; } - br->levels = kmalloc(obj->package.count * sizeof *(br->levels), + br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels), GFP_KERNEL); if (!br->levels) goto out_free; @@ -719,16 +724,34 @@ acpi_video_init_brightness(struct acpi_video_device *device) count++; } - /* don't sort the first two brightness levels */ + /* + * some buggy BIOS don't export the levels + * when machine is on AC/Battery in _BCL package. + * In this case, the first two elements in _BCL packages + * are also supported brightness levels that OS should take care of. + */ + for (i = 2; i < count; i++) + if (br->levels[i] == br->levels[0] || + br->levels[i] == br->levels[1]) + level_ac_battery++; + + if (level_ac_battery < 2) { + level_ac_battery = 2 - level_ac_battery; + br->flags._BCL_no_ac_battery_levels = 1; + for (i = (count - 1 + level_ac_battery); i >= 2; i--) + br->levels[i] = br->levels[i - level_ac_battery]; + count += level_ac_battery; + } else if (level_ac_battery > 2) + ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n")); + + /* sort all the supported brightness levels */ sort(&br->levels[2], count - 2, sizeof(br->levels[2]), acpi_video_cmp_level, NULL); - if (count < 2) - goto out_free_levels; - br->count = count; device->brightness = br; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count)); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "found %d brightness levels\n", count - 2)); kfree(obj); return max_level; From d80fb99fdcd56f4934f11cc44ca016463842dc8b Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 18 Mar 2009 16:27:14 +0800 Subject: [PATCH 089/140] ACPI video: support reversed _BCL method in ACPI video driver The brightness levels returned by _BCL package are in a reversed order on some laptops. http://bugzilla.kernel.org/show_bug.cgi?id=12037 http://bugzilla.kernel.org/show_bug.cgi?id=12302 http://bugzilla.kernel.org/show_bug.cgi?id=12235 sort the _BCL packge in case it's reversed. Signed-off-by: Zhang Rui Acked-by: Matthew Garrett Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/video.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 398b3eee37fb..dc84970ce1e9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -170,6 +170,7 @@ struct acpi_video_device_cap { struct acpi_video_brightness_flags { u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */ + u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/ }; struct acpi_video_device_brightness { @@ -744,9 +745,14 @@ acpi_video_init_brightness(struct acpi_video_device *device) } else if (level_ac_battery > 2) ACPI_ERROR((AE_INFO, "Too many duplicates in _BCL package\n")); - /* sort all the supported brightness levels */ - sort(&br->levels[2], count - 2, sizeof(br->levels[2]), - acpi_video_cmp_level, NULL); + /* Check if the _BCL package is in a reversed order */ + if (max_level == br->levels[2]) { + br->flags._BCL_reversed = 1; + sort(&br->levels[2], count - 2, sizeof(br->levels[2]), + acpi_video_cmp_level, NULL); + } else if (max_level != br->levels[count - 1]) + ACPI_ERROR((AE_INFO, + "Found unordered _BCL package\n")); br->count = count; device->brightness = br; From 1a7c618a3f7bef1a20ae740df512eeba21397fa5 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 18 Mar 2009 16:27:16 +0800 Subject: [PATCH 090/140] ACPI video: support _BQC/_BCL/_BCM methods that use index values The input/output of _BQC/_BCL/_BCM control methods should be represented by a number between 0 and 100, and can be thought of as a percentage. But some buggy _BQC/_BCL/_BCM methods use the index values instead. http://bugzilla.kernel.org/show_bug.cgi?id=12302 http://bugzilla.kernel.org/show_bug.cgi?id=12249 http://bugzilla.kernel.org/show_bug.cgi?id=12037 Add the functionality to support such kind of BIOSes in ACPI video driver. Signed-off-by: Zhang Rui Acked-by: Matthew Garrett Acked-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/acpi/video.c | 91 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index dc84970ce1e9..1f1625c51003 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -171,6 +171,9 @@ struct acpi_video_device_cap { struct acpi_video_brightness_flags { u8 _BCL_no_ac_battery_levels:1; /* no AC/Battery levels in _BCL */ u8 _BCL_reversed:1; /* _BCL package is in a reversed order*/ + u8 _BCL_use_index:1; /* levels in _BCL are index values */ + u8 _BCM_use_index:1; /* input of _BCM is an index value */ + u8 _BQC_use_index:1; /* _BQC returns an index value */ }; struct acpi_video_device_brightness { @@ -505,7 +508,8 @@ acpi_video_device_lcd_set_level(struct acpi_video_device *device, int level) device->brightness->curr = level; for (state = 2; state < device->brightness->count; state++) if (level == device->brightness->levels[state]) { - device->backlight->props.brightness = state - 2; + if (device->backlight) + device->backlight->props.brightness = state - 2; return 0; } @@ -523,6 +527,13 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, status = acpi_evaluate_integer(device->dev->handle, "_BQC", NULL, level); if (ACPI_SUCCESS(status)) { + if (device->brightness->flags._BQC_use_index) { + if (device->brightness->flags._BCL_reversed) + *level = device->brightness->count + - 3 - (*level); + *level = device->brightness->levels[*level + 2]; + + } device->brightness->curr = *level; return 0; } else { @@ -689,8 +700,10 @@ acpi_video_init_brightness(struct acpi_video_device *device) { union acpi_object *obj = NULL; int i, max_level = 0, count = 0, level_ac_battery = 0; + unsigned long long level, level_old; union acpi_object *o; struct acpi_video_device_brightness *br = NULL; + int result = -EINVAL; if (!ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available " @@ -704,13 +717,16 @@ acpi_video_init_brightness(struct acpi_video_device *device) br = kzalloc(sizeof(*br), GFP_KERNEL); if (!br) { printk(KERN_ERR "can't allocate memory\n"); + result = -ENOMEM; goto out; } br->levels = kmalloc((obj->package.count + 2) * sizeof *(br->levels), GFP_KERNEL); - if (!br->levels) + if (!br->levels) { + result = -ENOMEM; goto out_free; + } for (i = 0; i < obj->package.count; i++) { o = (union acpi_object *)&obj->package.elements[i]; @@ -756,10 +772,55 @@ acpi_video_init_brightness(struct acpi_video_device *device) br->count = count; device->brightness = br; + + /* Check the input/output of _BQC/_BCL/_BCM */ + if ((max_level < 100) && (max_level <= (count - 2))) + br->flags._BCL_use_index = 1; + + /* + * _BCM is always consistent with _BCL, + * at least for all the laptops we have ever seen. + */ + br->flags._BCM_use_index = br->flags._BCL_use_index; + + /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ + br->curr = max_level; + result = acpi_video_device_lcd_get_level_current(device, &level_old); + if (result) + goto out_free_levels; + + result = acpi_video_device_lcd_set_level(device, br->curr); + if (result) + goto out_free_levels; + + result = acpi_video_device_lcd_get_level_current(device, &level); + if (result) + goto out_free_levels; + + if ((level != level_old) && !br->flags._BCM_use_index) { + /* Note: + * This piece of code does not work correctly if the current + * brightness levels is 0. + * But I guess boxes that boot with such a dark screen are rare + * and no more code is needed to cover this specifial case. + */ + + if (level_ac_battery != 2) { + /* + * For now, we don't support the _BCL like this: + * 16, 15, 0, 1, 2, 3, ..., 14, 15, 16 + * because we may mess up the index returned by _BQC. + * Plus: we have not got a box like this. + */ + ACPI_ERROR((AE_INFO, "_BCL not supported\n")); + } + br->flags._BQC_use_index = 1; + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "found %d brightness levels\n", count - 2)); kfree(obj); - return max_level; + return result; out_free_levels: kfree(br->levels); @@ -768,7 +829,7 @@ out_free: out: device->brightness = NULL; kfree(obj); - return 0; + return result; } /* @@ -785,7 +846,6 @@ out: static void acpi_video_device_find_cap(struct acpi_video_device *device) { acpi_handle h_dummy1; - u32 max_level = 0; memset(&device->cap, 0, sizeof(device->cap)); @@ -814,13 +874,14 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->cap._DSS = 1; } - if (acpi_video_backlight_support()) - max_level = acpi_video_init_brightness(device); - - if (device->cap._BCL && device->cap._BCM && max_level > 0) { + if (acpi_video_backlight_support()) { int result; static int count = 0; char *name; + + result = acpi_video_init_brightness(device); + if (result) + return; name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); if (!name) return; @@ -829,18 +890,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); device->backlight->props.max_brightness = device->brightness->count-3; - /* - * If there exists the _BQC object, the _BQC object will be - * called to get the current backlight brightness. Otherwise - * the brightness will be set to the maximum. - */ - if (device->cap._BQC) - device->backlight->props.brightness = - acpi_video_get_brightness(device->backlight); - else - device->backlight->props.brightness = - device->backlight->props.max_brightness; - backlight_update_status(device->backlight); kfree(name); device->cdev = thermal_cooling_device_register("LCD", From c60d638e29c780b75b648283a197d0226e3576c3 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 18 Mar 2009 16:27:18 +0800 Subject: [PATCH 091/140] ACPI video: support buggy BIOSes with _BCQ implemented Some buggy BIOSes implements _BCQ instead of _BQC. Male ACPI video driver support these buggy BIOS. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 1f1625c51003..9730ec167590 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -162,6 +162,7 @@ struct acpi_video_device_cap { u8 _BCL:1; /*Query list of brightness control levels supported */ u8 _BCM:1; /*Set the brightness level */ u8 _BQC:1; /* Get current brightness level */ + u8 _BCQ:1; /* Some buggy BIOS uses _BCQ instead of _BQC */ u8 _DDC:1; /*Return the EDID for this device */ u8 _DCS:1; /*Return status of output device */ u8 _DGS:1; /*Query graphics state */ @@ -523,8 +524,10 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, { acpi_status status = AE_OK; - if (device->cap._BQC) { - status = acpi_evaluate_integer(device->dev->handle, "_BQC", + if (device->cap._BQC || device->cap._BCQ) { + char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; + + status = acpi_evaluate_integer(device->dev->handle, buf, NULL, level); if (ACPI_SUCCESS(status)) { if (device->brightness->flags._BQC_use_index) { @@ -544,8 +547,8 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, * ACPI video backlight still works w/ buggy _BQC. * http://bugzilla.kernel.org/show_bug.cgi?id=12233 */ - ACPI_WARNING((AE_INFO, "Evaluating _BQC failed")); - device->cap._BQC = 0; + ACPI_WARNING((AE_INFO, "Evaluating %s failed", buf)); + device->cap._BQC = device->cap._BCQ = 0; } } @@ -861,6 +864,12 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) } if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle,"_BQC",&h_dummy1))) device->cap._BQC = 1; + else if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_BCQ", + &h_dummy1))) { + printk(KERN_WARNING FW_BUG "_BCQ is used instead of _BQC\n"); + device->cap._BCQ = 1; + } + if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_DDC", &h_dummy1))) { device->cap._DDC = 1; } From 74a365b3f354fafc537efa5867deb7a9fadbfe27 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 19 Mar 2009 21:35:39 +0000 Subject: [PATCH 092/140] ACPI: Populate DIDL before registering ACPI video device on Intel Intel graphics hardware that implements the ACPI IGD OpRegion spec requires that the list of display devices be populated before any ACPI video methods are called. Detect when this is the case and defer registration until the opregion code calls it. Fixes crashes on HP laptops. http://bugzilla.kernel.org/show_bug.cgi?id=11259 Signed-off-by: Matthew Garrett Acked-by: Eric Anholt Signed-off-by: Len Brown --- drivers/acpi/video.c | 40 ++++++++++++++++- drivers/gpu/drm/i915/i915_dma.c | 5 ++- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_opregion.c | 65 +++++++++++++++++++++++++++- include/acpi/video.h | 11 +++++ 6 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 include/acpi/video.h diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 9730ec167590..ae427100a1ef 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -2251,7 +2253,27 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) return 0; } -static int __init acpi_video_init(void) +static int __init intel_opregion_present(void) +{ +#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) + struct pci_dev *dev = NULL; + u32 address; + + for_each_pci_dev(dev) { + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + continue; + if (dev->vendor != PCI_VENDOR_ID_INTEL) + continue; + pci_read_config_dword(dev, 0xfc, &address); + if (!address) + continue; + return 1; + } +#endif + return 0; +} + +int acpi_video_register(void) { int result = 0; @@ -2268,6 +2290,22 @@ static int __init acpi_video_init(void) return 0; } +EXPORT_SYMBOL(acpi_video_register); + +/* + * This is kind of nasty. Hardware using Intel chipsets may require + * the video opregion code to be run first in order to initialise + * state before any ACPI video calls are made. To handle this we defer + * registration of the video class until the opregion code has run. + */ + +static int __init acpi_video_init(void) +{ + if (intel_opregion_present()) + return 0; + + return acpi_video_register(); +} static void __exit acpi_video_exit(void) { diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 6d21b9e48b89..638686904e06 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1144,8 +1144,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) if (!IS_I945G(dev) && !IS_I945GM(dev)) pci_enable_msi(dev->pdev); - intel_opregion_init(dev); - spin_lock_init(&dev_priv->user_irq_lock); dev_priv->user_irq_refcount = 0; @@ -1164,6 +1162,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } } + /* Must be done after probing outputs */ + intel_opregion_init(dev, 0); + return 0; out_iomapfree: diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b293ef0bae71..209592fdb7e7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -99,7 +99,7 @@ static int i915_resume(struct drm_device *dev) i915_restore_state(dev); - intel_opregion_init(dev); + intel_opregion_init(dev, 1); /* KMS EnterVT equivalent */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d6cc9861e0a1..1679a951aa7e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -659,7 +659,7 @@ extern int i915_restore_state(struct drm_device *dev); #ifdef CONFIG_ACPI /* i915_opregion.c */ -extern int intel_opregion_init(struct drm_device *dev); +extern int intel_opregion_init(struct drm_device *dev, int resume); extern void intel_opregion_free(struct drm_device *dev); extern void opregion_asle_intr(struct drm_device *dev); extern void opregion_enable_asle(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index ff012835a386..69427722d20e 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c @@ -26,6 +26,7 @@ */ #include +#include #include "drmP.h" #include "i915_drm.h" @@ -136,6 +137,12 @@ struct opregion_asle { #define ASLE_CBLV_VALID (1<<31) +#define ACPI_OTHER_OUTPUT (0<<8) +#define ACPI_VGA_OUTPUT (1<<8) +#define ACPI_TV_OUTPUT (2<<8) +#define ACPI_DIGITAL_OUTPUT (3<<8) +#define ACPI_LVDS_OUTPUT (4<<8) + static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -282,7 +289,58 @@ static struct notifier_block intel_opregion_notifier = { .notifier_call = intel_opregion_video_event, }; -int intel_opregion_init(struct drm_device *dev) +/* + * Initialise the DIDL field in opregion. This passes a list of devices to + * the firmware. Values are defined by section B.4.2 of the ACPI specification + * (version 3) + */ + +static void intel_didl_outputs(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_opregion *opregion = &dev_priv->opregion; + struct drm_connector *connector; + int i = 0; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + int output_type = ACPI_OTHER_OUTPUT; + if (i >= 8) { + dev_printk (KERN_ERR, &dev->pdev->dev, + "More than 8 outputs detected\n"); + return; + } + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_DVIA: + output_type = ACPI_VGA_OUTPUT; + break; + case DRM_MODE_CONNECTOR_Composite: + case DRM_MODE_CONNECTOR_SVIDEO: + case DRM_MODE_CONNECTOR_Component: + case DRM_MODE_CONNECTOR_9PinDIN: + output_type = ACPI_TV_OUTPUT; + break; + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_DisplayPort: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + output_type = ACPI_DIGITAL_OUTPUT; + break; + case DRM_MODE_CONNECTOR_LVDS: + output_type = ACPI_LVDS_OUTPUT; + break; + } + opregion->acpi->didl[i] |= (1<<31) | output_type | i; + i++; + } + + /* If fewer than 8 outputs, the list must be null terminated */ + if (i < 8) + opregion->acpi->didl[i] = 0; +} + +int intel_opregion_init(struct drm_device *dev, int resume) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_opregion *opregion = &dev_priv->opregion; @@ -312,6 +370,11 @@ int intel_opregion_init(struct drm_device *dev) if (mboxes & MBOX_ACPI) { DRM_DEBUG("Public ACPI methods supported\n"); opregion->acpi = base + OPREGION_ACPI_OFFSET; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + intel_didl_outputs(dev); + if (!resume) + acpi_video_register(); + } } else { DRM_DEBUG("Public ACPI methods not supported\n"); err = -ENOTSUPP; diff --git a/include/acpi/video.h b/include/acpi/video.h new file mode 100644 index 000000000000..f0275bb79ce4 --- /dev/null +++ b/include/acpi/video.h @@ -0,0 +1,11 @@ +#ifndef __ACPI_VIDEO_H +#define __ACPI_VIDEO_H + +#if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) +extern int acpi_video_register(void); +#else +static inline int acpi_video_register(void) { return 0; } +#endif + +#endif + From 7faa144a518c456e2057918f030f50100144ccc6 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 27 Mar 2009 22:23:52 -0400 Subject: [PATCH 093/140] ACPI: battery: add power_{now,avg} properties to power_class ACPI has smart batteries, which work in units of energy and measure rate of (dis)charge as power, thus it is not appropriate to export it as a current_now. Current_now will still be exported to allow for userland applications to match. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/battery.c | 12 +++++++----- drivers/acpi/sbs.c | 27 ++++++++++++++++----------- drivers/power/power_supply_sysfs.c | 2 ++ include/linux/power_supply.h | 2 ++ 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 69cbc57c2d1c..09a2240d5605 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -92,7 +92,7 @@ struct acpi_battery { #endif struct acpi_device *device; unsigned long update_time; - int current_now; + int rate_now; int capacity_now; int voltage_now; int design_capacity; @@ -196,7 +196,8 @@ static int acpi_battery_get_property(struct power_supply *psy, val->intval = battery->voltage_now * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = battery->current_now * 1000; + case POWER_SUPPLY_PROP_POWER_NOW: + val->intval = battery->rate_now * 1000; break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: @@ -247,6 +248,7 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, POWER_SUPPLY_PROP_ENERGY_NOW, @@ -273,7 +275,7 @@ struct acpi_offsets { static struct acpi_offsets state_offsets[] = { {offsetof(struct acpi_battery, state), 0}, - {offsetof(struct acpi_battery, current_now), 0}, + {offsetof(struct acpi_battery, rate_now), 0}, {offsetof(struct acpi_battery, capacity_now), 0}, {offsetof(struct acpi_battery, voltage_now), 0}, }; @@ -605,11 +607,11 @@ static int acpi_battery_print_state(struct seq_file *seq, int result) else seq_printf(seq, "charging state: charged\n"); - if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present rate: unknown\n"); else seq_printf(seq, "present rate: %d %s\n", - battery->current_now, acpi_battery_units(battery)); + battery->rate_now, acpi_battery_units(battery)); if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "remaining capacity: unknown\n"); diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 6050ce481873..3963cb6e0f19 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -102,8 +102,8 @@ struct acpi_battery { u16 cycle_count; u16 temp_now; u16 voltage_now; - s16 current_now; - s16 current_avg; + s16 rate_now; + s16 rate_avg; u16 capacity_now; u16 state_of_charge; u16 state; @@ -202,9 +202,9 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy, return -ENODEV; switch (psp) { case POWER_SUPPLY_PROP_STATUS: - if (battery->current_now < 0) + if (battery->rate_now < 0) val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - else if (battery->current_now > 0) + else if (battery->rate_now > 0) val->intval = POWER_SUPPLY_STATUS_CHARGING; else val->intval = POWER_SUPPLY_STATUS_FULL; @@ -224,11 +224,13 @@ static int acpi_sbs_battery_get_property(struct power_supply *psy, acpi_battery_vscale(battery) * 1000; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = abs(battery->current_now) * + case POWER_SUPPLY_PROP_POWER_NOW: + val->intval = abs(battery->rate_now) * acpi_battery_ipscale(battery) * 1000; break; case POWER_SUPPLY_PROP_CURRENT_AVG: - val->intval = abs(battery->current_avg) * + case POWER_SUPPLY_PROP_POWER_AVG: + val->intval = abs(battery->rate_avg) * acpi_battery_ipscale(battery) * 1000; break; case POWER_SUPPLY_PROP_CAPACITY: @@ -293,6 +295,8 @@ static enum power_supply_property sbs_energy_battery_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_POWER_NOW, + POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, POWER_SUPPLY_PROP_ENERGY_FULL, @@ -301,6 +305,7 @@ static enum power_supply_property sbs_energy_battery_props[] = { POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, }; + #endif /* -------------------------------------------------------------------------- @@ -330,8 +335,8 @@ static struct acpi_battery_reader info_readers[] = { static struct acpi_battery_reader state_readers[] = { {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)}, {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)}, - {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)}, - {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)}, + {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_now)}, + {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, rate_avg)}, {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)}, {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)}, {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)}, @@ -589,9 +594,9 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) seq_printf(seq, "capacity state: %s\n", (battery->state & 0x0010) ? "critical" : "ok"); seq_printf(seq, "charging state: %s\n", - (battery->current_now < 0) ? "discharging" : - ((battery->current_now > 0) ? "charging" : "charged")); - rate = abs(battery->current_now) * acpi_battery_ipscale(battery); + (battery->rate_now < 0) ? "discharging" : + ((battery->rate_now > 0) ? "charging" : "charged")); + rate = abs(battery->rate_now) * acpi_battery_ipscale(battery); rate *= (acpi_battery_mode(battery))?(battery->voltage_now * acpi_battery_vscale(battery)/1000):1; seq_printf(seq, "present rate: %d%s\n", rate, diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index ac01e06817fb..da73591017f9 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -93,6 +93,8 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(voltage_avg), POWER_SUPPLY_ATTR(current_now), POWER_SUPPLY_ATTR(current_avg), + POWER_SUPPLY_ATTR(power_now), + POWER_SUPPLY_ATTR(power_avg), POWER_SUPPLY_ATTR(charge_full_design), POWER_SUPPLY_ATTR(charge_empty_design), POWER_SUPPLY_ATTR(charge_full), diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 8ff25e0e7f7a..594c494ac3f0 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -73,6 +73,8 @@ enum power_supply_property { POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_POWER_NOW, + POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN, POWER_SUPPLY_PROP_CHARGE_FULL, From 98758faffc86ee6fe9504eeab75481ee7c1aa860 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Thu, 12 Mar 2009 16:57:11 +0800 Subject: [PATCH 094/140] ACPI video: add a warning message if _BQC is not found ACPI backlight control w/o _BQC support is kinda firmware bug. Add a warning if _BQC is not implemented. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/video_detect.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 50e3d2dbf3af..09737275e25f 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -55,6 +55,9 @@ acpi_backlight_cap_match(acpi_handle handle, u32 level, void *context, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight " "support\n")); *cap |= ACPI_VIDEO_BACKLIGHT; + if (ACPI_FAILURE(acpi_get_handle(handle, "_BQC", &h_dummy))) + printk(KERN_WARNING FW_BUG PREFIX "ACPI brightness " + "control misses _BQC function\n"); /* We have backlight support, no need to scan further */ return AE_CTRL_TERMINATE; } From 03ae61dd5701092aabb60a8cae9929dbf8dc25c6 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 28 Mar 2009 01:41:14 -0400 Subject: [PATCH 095/140] ACPI: fix CONFIG_ACPI=n build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/i915/i915_drv.c:102: error: too many arguments to function ‘intel_opregion_init’ Signed-off-by: Len Brown --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1679a951aa7e..b9a92c250b91 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -664,7 +664,7 @@ extern void intel_opregion_free(struct drm_device *dev); extern void opregion_asle_intr(struct drm_device *dev); extern void opregion_enable_asle(struct drm_device *dev); #else -static inline int intel_opregion_init(struct drm_device *dev) { return 0; } +static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } static inline void intel_opregion_free(struct drm_device *dev) { return; } static inline void opregion_asle_intr(struct drm_device *dev) { return; } static inline void opregion_enable_asle(struct drm_device *dev) { return; } From 34ff4dbccccce54c83b1234d39b7ad9e548a75dd Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 1 Apr 2009 00:25:10 -0400 Subject: [PATCH 096/140] ACPI: EC: Separate delays for MSI hardware MSI notebooks require very strict delays, while all others are happy with msleep(). References: http://bugzilla.kernel.org/show_bug.cgi?id=9998 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2fe15060dcdc..ac9dd3b386b1 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -67,7 +67,7 @@ enum ec_command { #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ -#define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ +#define ACPI_EC_CDELAY 10 /* Wait 10us before polling EC */ #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts per one transaction */ @@ -236,13 +236,23 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) return 0; } +static void ec_delay(void) +{ + /* EC in MSI notebooks don't tolerate delays other than 550 usec */ + if (EC_FLAGS_MSI) + udelay(ACPI_EC_DELAY); + else + /* Use shortest sleep available */ + msleep(1); +} + static int ec_poll(struct acpi_ec *ec) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); - udelay(ACPI_EC_UDELAY); + udelay(ACPI_EC_CDELAY); while (time_before(jiffies, delay)) { gpe_transaction(ec, acpi_ec_read_status(ec)); - udelay(ACPI_EC_UDELAY); + ec_delay(); if (ec_transaction_done(ec)) return 0; } From a5032bfdd9c80e0231a6324661e123818eb46ecd Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 1 Apr 2009 01:33:15 -0400 Subject: [PATCH 097/140] ACPI: EC: Always parse EC device If ECDT info is not valid, we have last chance to configure EC driver properly at this point, don't miss it. http://bugzilla.kernel.org/show_bug.cgi?id=12461 Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2fe15060dcdc..5a2d5372ea39 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -755,6 +755,10 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) unsigned long long tmp = 0; struct acpi_ec *ec = context; + + /* clear addr values, ec_parse_io_ports depend on it */ + ec->command_addr = ec->data_addr = 0; + status = acpi_walk_resources(handle, METHOD_NAME__CRS, ec_parse_io_ports, ec); if (ACPI_FAILURE(status)) @@ -804,11 +808,11 @@ static int acpi_ec_add(struct acpi_device *device) ec = make_acpi_ec(); if (!ec) return -ENOMEM; - if (ec_parse_device(device->handle, 0, ec, NULL) != - AE_CTRL_TERMINATE) { + } + if (ec_parse_device(device->handle, 0, ec, NULL) != + AE_CTRL_TERMINATE) { kfree(ec); return -EINVAL; - } } ec->handle = device->handle; @@ -986,12 +990,12 @@ int __init acpi_ec_ecdt_probe(void) boot_ec->handle = ACPI_ROOT_OBJECT; acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); /* Don't trust ECDT, which comes from ASUSTek */ - if (!dmi_name_in_vendors("ASUS")) + if (!dmi_name_in_vendors("ASUS") && EC_FLAGS_MSI == 0) goto install; saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); if (!saved_ec) return -ENOMEM; - memcpy(saved_ec, boot_ec, sizeof(*saved_ec)); + memcpy(saved_ec, boot_ec, sizeof(struct acpi_ec)); /* fall through */ } /* This workaround is needed only on some broken machines, From 5b5d9117407e790ade594687010343c5d559a1f4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 12 Mar 2009 09:07:19 +1030 Subject: [PATCH 098/140] ACPI: simplify module_param namespace Impact: cleanup Rather than overriding MODULE_PARAM_PREFIX, build via acpi.o so KBUILD_MODNAME is set to "acpi". This is the logical way to do it, even though acpi cannot be a module due to these config options being bool. Those parts of ACPI which can be modular are not built into the acpi "module". Signed-off-by: Rusty Russell Signed-off-by: Len Brown --- drivers/acpi/Makefile | 68 +++++++++++++++++++++++-------------------- drivers/acpi/debug.c | 5 ---- drivers/acpi/power.c | 4 --- drivers/acpi/system.c | 4 --- 4 files changed, 36 insertions(+), 45 deletions(-) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b130ea0d0759..13b611e7eade 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -14,48 +14,52 @@ obj-$(CONFIG_X86) += blacklist.o # # ACPI Core Subsystem (Interpreter) # -obj-y += osl.o utils.o reboot.o\ +obj-y += acpi.o \ acpica/ +# All the builtin files are in the "acpi." module_param namespace. +acpi-y += osl.o utils.o reboot.o + # sleep related files -obj-y += wakeup.o -obj-y += sleep.o -obj-$(CONFIG_ACPI_SLEEP) += proc.o +acpi-y += wakeup.o +acpi-y += sleep.o +acpi-$(CONFIG_ACPI_SLEEP) += proc.o # # ACPI Bus and Device Drivers # +acpi-y += bus.o glue.o +acpi-y += scan.o +# Keep EC driver first. Initialization of others depend on it. +acpi-y += ec.o +acpi-$(CONFIG_ACPI_DOCK) += dock.o +acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o +acpi-y += power.o +acpi-y += system.o event.o +acpi-$(CONFIG_ACPI_DEBUG) += debug.o +acpi-$(CONFIG_ACPI_NUMA) += numa.o +acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o +ifdef CONFIG_ACPI_VIDEO +acpi-y += video_detect.o +endif + +# These are (potentially) separate modules +obj-$(CONFIG_ACPI_AC) += ac.o +obj-$(CONFIG_ACPI_BATTERY) += battery.o +obj-$(CONFIG_ACPI_BUTTON) += button.o +obj-$(CONFIG_ACPI_FAN) += fan.o +obj-$(CONFIG_ACPI_VIDEO) += video.o +obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o +obj-$(CONFIG_ACPI_PROCESSOR) += processor.o +obj-$(CONFIG_ACPI_CONTAINER) += container.o +obj-$(CONFIG_ACPI_THERMAL) += thermal.o +obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o +obj-$(CONFIG_ACPI_SBS) += sbshc.o +obj-$(CONFIG_ACPI_SBS) += sbs.o + processor-objs += processor_core.o processor_throttling.o \ processor_idle.o processor_thermal.o ifdef CONFIG_CPU_FREQ processor-objs += processor_perflib.o endif - -obj-y += bus.o glue.o -obj-y += scan.o -# Keep EC driver first. Initialization of others depend on it. -obj-y += ec.o -obj-$(CONFIG_ACPI_AC) += ac.o -obj-$(CONFIG_ACPI_BATTERY) += battery.o -obj-$(CONFIG_ACPI_BUTTON) += button.o -obj-$(CONFIG_ACPI_FAN) += fan.o -obj-$(CONFIG_ACPI_DOCK) += dock.o -obj-$(CONFIG_ACPI_VIDEO) += video.o -ifdef CONFIG_ACPI_VIDEO -obj-y += video_detect.o -endif - -obj-y += pci_root.o pci_link.o pci_irq.o pci_bind.o -obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o -obj-$(CONFIG_ACPI_PROCESSOR) += processor.o -obj-$(CONFIG_ACPI_CONTAINER) += container.o -obj-$(CONFIG_ACPI_THERMAL) += thermal.o -obj-y += power.o -obj-y += system.o event.o -obj-$(CONFIG_ACPI_DEBUG) += debug.o -obj-$(CONFIG_ACPI_NUMA) += numa.o -obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o -obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o -obj-$(CONFIG_ACPI_SBS) += sbshc.o -obj-$(CONFIG_ACPI_SBS) += sbs.o diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c index 20223cbd0d1c..25f9c38531bd 100644 --- a/drivers/acpi/debug.c +++ b/drivers/acpi/debug.c @@ -13,11 +13,6 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("debug"); -#ifdef MODULE_PARAM_PREFIX -#undef MODULE_PARAM_PREFIX -#endif -#define MODULE_PARAM_PREFIX "acpi." - struct acpi_dlayer { const char *name; unsigned long value; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index c926e7d4a0d6..87361c1592d3 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -54,10 +54,6 @@ ACPI_MODULE_NAME("power"); #define ACPI_POWER_RESOURCE_STATE_ON 0x01 #define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF -#ifdef MODULE_PARAM_PREFIX -#undef MODULE_PARAM_PREFIX -#endif -#define MODULE_PARAM_PREFIX "acpi." int acpi_power_nocheck; module_param_named(power_nocheck, acpi_power_nocheck, bool, 000); diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 391d0358a592..a0499d00020c 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c @@ -33,10 +33,6 @@ #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("system"); -#ifdef MODULE_PARAM_PREFIX -#undef MODULE_PARAM_PREFIX -#endif -#define MODULE_PARAM_PREFIX "acpi." #define ACPI_SYSTEM_CLASS "system" #define ACPI_SYSTEM_DEVICE_NAME "System" From 7e90560c50f754d65884e251e94c1efa2a4b5784 Mon Sep 17 00:00:00 2001 From: Luca Tettamanti Date: Mon, 30 Mar 2009 00:01:27 +0200 Subject: [PATCH 099/140] ACPI: acpi_enforce_resource=strict by default Enforce strict resource checking - disallowing access by native drivers to IO ports and memory regions claimed by ACPI firmware. The patch is mainly aimed to block native hwmon drivers from touching monitoring chips that ACPI thinks it own. If this causes a regression, boot with "acpi_enforce_resources=lax" which was the previous default. http://bugzilla.kernel.org/show_bug.cgi?id=12376 http://bugzilla.kernel.org/show_bug.cgi?id=12541 Signed-off-by: Luca Tettamanti Acked-by: Pavel Machek Acked-by: Jean Delvare Signed-off-by: Len Brown --- Documentation/kernel-parameters.txt | 16 ++++++++++++++++ drivers/acpi/osl.c | 6 +++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 54f21a5c262b..7068d0bc47c5 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -258,6 +258,22 @@ and is between 256 and 4096 characters. It is defined in the file to assume that this machine's pmtimer latches its value and always returns good values. + acpi_enforce_resources= [ACPI] + { strict | lax | no } + Check for resource conflicts between native drivers + and ACPI OperationRegions (SystemIO and SystemMemory + only). IO ports and memory declared in ACPI might be + used by the ACPI subsystem in arbitrary AML code and + can interfere with legacy drivers. + strict (default): access to resources claimed by ACPI + is denied; legacy drivers trying to access reserved + resources will fail to bind to device using them. + lax: access to resources claimed by ACPI is allowed; + legacy drivers trying to access reserved resources + will bind successfully but a warning message is logged. + no: ACPI OperationRegions are not marked as reserved, + no further checks are performed. + agp= [AGP] { off | try_unsupported } off: disable AGP support diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 1e35f342957c..f50ca1ea80c3 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1063,9 +1063,9 @@ __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); * in arbitrary AML code and can interfere with legacy drivers. * acpi_enforce_resources= can be set to: * - * - strict (2) + * - strict (default) (2) * -> further driver trying to access the resources will not load - * - lax (default) (1) + * - lax (1) * -> further driver trying to access the resources will load, but you * get a system message that something might go wrong... * @@ -1077,7 +1077,7 @@ __setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); #define ENFORCE_RESOURCES_LAX 1 #define ENFORCE_RESOURCES_NO 0 -static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX; +static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_STRICT; static int __init acpi_enforce_resources_setup(char *str) { From ae7d51517bc3b0fe10c6af38234ef0f92bbae6a4 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Thu, 2 Apr 2009 22:49:43 -0400 Subject: [PATCH 100/140] ACPI: simplify processor lines in Makefile Suggested-by: Sam Ravnborg Signed-off-by: Len Brown --- drivers/acpi/Makefile | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 13b611e7eade..1f5c7a5d55c6 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -58,8 +58,7 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbs.o -processor-objs += processor_core.o processor_throttling.o \ - processor_idle.o processor_thermal.o -ifdef CONFIG_CPU_FREQ -processor-objs += processor_perflib.o -endif +# processor has its own "processor." module_param namespace +processor-y := processor_core.o processor_throttling.o +processor-y += processor_idle.o processor_thermal.o +processor-$(CONFIG_CPU_FREQ) += processor_perflib.o From 07de5bdb7bad607e29dc17c345717403a76a334c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Kosi=C5=84ski?= Date: Thu, 19 Mar 2009 23:22:31 +0100 Subject: [PATCH 101/140] tc1100-wmi: Fix state reporting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tc1100-wmi driver should print the current states of wireless LAN and jogdial brightness control when "cat /sys/devices/platform/tc1100-wmi/wireless" and "cat /sys/devices/platform/tc1100-wmi/jogdial" are executed, respectively. What actually happens is that both of those commands print 0 regardless of the hardware state. The cause is that wmi_query_block returns an ACPI_TYPE_INTEGER rather than ACPI_TYPE_BUFFER as the driver assumes. Additionally, the driver intends to return a jogdial state that is inverted with respect to the commands required to set it (e.g. it intends to return 1 after the jogdial file was written with 0). This patch fixes both of those issues - the commands to query the state now work, and should return the same state that was written. http://bugzilla.kernel.org/show_bug.cgi?id=12286 Signed-off-by: Krzysztof KosiÅ„ski Acked-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index b4a4aa9ee482..44166003d4ef 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -94,9 +94,8 @@ static int get_state(u32 *out, u8 instance) return -ENODEV; obj = (union acpi_object *) result.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(u32)) { - tmp = *((u32 *) obj->buffer.pointer); + if (obj && obj->type == ACPI_TYPE_INTEGER) { + tmp = obj->integer.value; } else { tmp = 0; } @@ -109,7 +108,7 @@ static int get_state(u32 *out, u8 instance) *out = (tmp == 3) ? 1 : 0; return 0; case TC1100_INSTANCE_JOGDIAL: - *out = (tmp == 1) ? 1 : 0; + *out = (tmp == 1) ? 0 : 1; return 0; default: return -ENODEV; From 2a9ef8e1a856be8e526bb9b10fb98c5012f6e3f8 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 18 Mar 2009 16:36:25 +0800 Subject: [PATCH 102/140] ACPI: suspend: Add the Pansonic CF51 box to the dmi check table The Pansonic CF51-2L requires "acpi_sleep=old_ordering", so invoke it automatically via DMI. http://bugzilla.kernel.org/show_bug.cgi?id=12561 Signed-off-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 00456fccfa38..31ff2a9a03d7 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -394,6 +394,15 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "Panasonic CF51-2L", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, + "Matsushita Electric Industrial Co.,Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ From 53af9cfb37af5e03ee2b24c5d5c4963c34e5b765 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sun, 15 Mar 2009 23:36:38 -0400 Subject: [PATCH 103/140] ACPI: get_throttling_state() cannot be larger than state_count Reported-by: Roel Kluin Acked-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/acpi/processor_throttling.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index d27838171f4a..5f099012f471 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -783,11 +783,9 @@ static int acpi_get_throttling_state(struct acpi_processor *pr, (struct acpi_processor_tx_tss *)&(pr->throttling. states_tss[i]); if (tx->control == value) - break; + return i; } - if (i > pr->throttling.state_count) - i = -1; - return i; + return -1; } static int acpi_get_throttling_value(struct acpi_processor *pr, From 5b4c0b6fffb91b07a6f85dabbdfbd5abab61d9db Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 1 Apr 2009 01:49:42 -0400 Subject: [PATCH 104/140] ACPI: update comment update ACPI Development Discussion List Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- arch/x86/kernel/acpi/boot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7678f10c4568..2481ec3e83b1 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1493,7 +1493,7 @@ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) /* * If your system is blacklisted here, but you find that acpi=force - * works for you, please contact acpi-devel@sourceforge.net + * works for you, please contact linux-acpi@vger.kernel.org */ static struct dmi_system_id __initdata acpi_dmi_table[] = { /* From 67dc092187626ac55a60877485f78bc291cbfa81 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Thu, 2 Apr 2009 14:11:20 +0200 Subject: [PATCH 105/140] ACPI: Remove R40e c-state blacklist The recent ACPICA patch (ACPICA: FADT: Favor 32-bit register addresses for compatibility) makes machine to use the right FADT HW addresses and C-states now work fine. http://bugzilla.kernel.org/show_bug.cgi?id=8246 Signed-off-by: Thomas Renninger Tested-by: Mark Doughty Signed-off-by: Len Brown --- drivers/acpi/processor_idle.c | 51 ----------------------------------- 1 file changed, 51 deletions(-) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 5c69e85c1e4d..397f2a7fee48 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -101,57 +101,6 @@ static int set_max_cstate(const struct dmi_system_id *id) /* Actually this shouldn't be __cpuinitdata, would be better to fix the callers to only run once -AK */ static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET70WW")}, (void *)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW")}, (void *)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET43WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET45WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET47WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET50WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET52WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET55WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET56WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET59WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET61WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET62WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET64WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET65WW") }, (void*)1}, - { set_max_cstate, "IBM ThinkPad R40e", { - DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), - DMI_MATCH(DMI_BIOS_VERSION,"1SET68WW") }, (void*)1}, - { set_max_cstate, "Medion 41700", { - DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), - DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J")}, (void *)1}, { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, From f240729832dff3785104d950dad2d3ced4387f6d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 2 Apr 2009 08:29:56 +0300 Subject: [PATCH 106/140] dock: fix dereference after kfree() dock_remove() calls kfree() on dock_station so we should use list_for_each_entry_safe() to avoid dereferencing freed memory. Found by smatch (http://repo.or.cz/w/smatch.git/). Compile tested. Signed-off-by: Dan Carpenter Signed-off-by: Len Brown --- drivers/acpi/dock.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 35094f230b1e..8f62fa01a9c7 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -1146,9 +1146,10 @@ static int __init dock_init(void) static void __exit dock_exit(void) { struct dock_station *dock_station; + struct dock_station *tmp; unregister_acpi_bus_notifier(&dock_acpi_notifier); - list_for_each_entry(dock_station, &dock_stations, sibiling) + list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibiling) dock_remove(dock_station); } From ff07a53a33cff2733c2c20fc75e84e75c2572889 Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Wed, 1 Apr 2009 22:10:44 +0900 Subject: [PATCH 107/140] sony-laptop: Fix some typos in log messages (Unabe/Unable) Signed-off-by: Alessio Igor Bogani Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 0f710317a94e..5837156f09fd 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -397,7 +397,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); if (!sony_laptop_input.wq) { printk(KERN_ERR DRV_PFX - "Unabe to create workqueue.\n"); + "Unable to create workqueue.\n"); error = -ENXIO; goto err_free_kfifo; } @@ -1267,7 +1267,7 @@ static int sony_nc_add(struct acpi_device *device) result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX - "Unabe to create input devices.\n"); + "Unable to create input devices.\n"); goto outwalk; } @@ -2816,7 +2816,7 @@ static int sony_pic_add(struct acpi_device *device) result = sony_pic_possible_resources(device); if (result) { printk(KERN_ERR DRV_PFX - "Unabe to read possible resources.\n"); + "Unable to read possible resources.\n"); goto err_free_resources; } @@ -2824,7 +2824,7 @@ static int sony_pic_add(struct acpi_device *device) result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX - "Unabe to create input devices.\n"); + "Unable to create input devices.\n"); goto err_free_resources; } From 6479efb68dce48fa52aed6ff876d8d102f200527 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 1 Apr 2009 22:10:45 +0900 Subject: [PATCH 108/140] sony-laptop: new style events typo fixes Signed-off-by: Matthias Welwarsky Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5837156f09fd..011c03596b2c 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -865,7 +865,7 @@ struct sony_nc_event { static struct sony_nc_event sony_100_events[] = { { 0x90, SONYPI_EVENT_PKEY_P1 }, { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED }, - { 0x91, SONYPI_EVENT_PKEY_P1 }, + { 0x91, SONYPI_EVENT_PKEY_P2 }, { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0x81, SONYPI_EVENT_FNKEY_F1 }, { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, @@ -929,7 +929,7 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) if (sony_find_snc_handle(0x127) == ev) key_handle = 0x127; - if (handle) { + if (key_handle) { struct sony_nc_event *key_event; if (sony_call_snc_handle(key_handle, 0x200, &result)) From 14bd31365fbeeccee72b0aead3baa4e5da208281 Mon Sep 17 00:00:00 2001 From: Alexander Beregalov Date: Wed, 1 Apr 2009 22:10:46 +0900 Subject: [PATCH 109/140] sony-laptop should depend on RFKILL Fixes this build error when RFKILL is not set: drivers/platform/x86/sony-laptop.c:1050: undefined reference to `rfkill_unregister' and so on.. Signed-off-by: Alexander Beregalov Acked-by: Matthew Garrett Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3608081bc3e0..36b1628d19c6 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -165,6 +165,7 @@ config SONY_LAPTOP depends on ACPI select BACKLIGHT_CLASS_DEVICE depends on INPUT + depends on RFKILL ---help--- This mini-driver drives the SNC and SPIC devices present in the ACPI BIOS of the Sony Vaio laptops. From 16dd55f309cf69a648ca3b1fc04b3b6f079c8be0 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 1 Apr 2009 22:10:47 +0900 Subject: [PATCH 110/140] sony-laptop: fix event reporting for new style events In short Fn key events are always reported through acpi. The input layer gets all the old style events and only those new style events that, after being decoded, are mapped to an locally represented events. rfkill only update the rfkill device status. Signed-off-by: Matthias Welwarsky Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 41 +++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 011c03596b2c..e02edf68a68e 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -917,10 +917,10 @@ static struct sony_nc_event sony_127_events[] = { static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) { u32 ev = event; - int result; if (ev >= 0x90) { /* New-style event */ + int result; int key_handle = 0; ev -= 0x90; @@ -932,38 +932,43 @@ static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) if (key_handle) { struct sony_nc_event *key_event; - if (sony_call_snc_handle(key_handle, 0x200, &result)) + if (sony_call_snc_handle(key_handle, 0x200, &result)) { dprintk("sony_acpi_notify, unable to decode" " event 0x%.2x 0x%.2x\n", key_handle, ev); - else + /* restore the original event */ + ev = event; + } else { ev = result & 0xFF; - if (key_handle == 0x100) - key_event = sony_100_events; - else - key_event = sony_127_events; + if (key_handle == 0x100) + key_event = sony_100_events; + else + key_event = sony_127_events; - for (; key_event->data; key_event++) { - if (key_event->data == ev) { - ev = key_event->event; - break; + for (; key_event->data; key_event++) { + if (key_event->data == ev) { + ev = key_event->event; + break; + } } - } - if (!key_event->data) { - printk(KERN_INFO DRV_PFX - "Unknown event: 0x%x 0x%x\n", key_handle, - ev); + if (!key_event->data) + printk(KERN_INFO DRV_PFX + "Unknown event: 0x%x 0x%x\n", + key_handle, + ev); + else + sony_laptop_report_input_event(ev); } } else if (sony_find_snc_handle(0x124) == ev) { sony_nc_rfkill_update(); return; } - } + } else + sony_laptop_report_input_event(ev); dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); - sony_laptop_report_input_event(ev); acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); } From 7237d3de78ff89ec2e18eae5fe962d063024fef5 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 30 Mar 2009 13:55:30 -0800 Subject: [PATCH 111/140] x86, ACPI: add support for x2apic ACPI extensions All logical processors with APIC ID values of 255 and greater will have their APIC reported through Processor X2APIC structure (type-9 entry type) and all logical processors with APIC ID less than 255 will have their APIC reported through legacy Processor Local APIC (type-0 entry type) only. This is the same case even for NMI structure reporting. The Processor X2APIC Affinity structure provides the association between the X2APIC ID of a logical processor and the proximity domain to which the logical processor belongs. For OSPM, Procssor IDs outside the 0-254 range are to be declared as Device() objects in the ACPI namespace. Signed-off-by: Suresh Siddha Signed-off-by: Len Brown --- arch/x86/kernel/acpi/boot.c | 63 ++++++++++++++++++++++++++++++++--- arch/x86/mm/srat_64.c | 30 +++++++++++++++++ drivers/acpi/numa.c | 46 ++++++++++++++++++++++++- drivers/acpi/processor_core.c | 26 +++++++++++++++ drivers/acpi/tables.c | 30 +++++++++++++++++ include/linux/acpi.h | 1 + 6 files changed, 191 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7678f10c4568..565e70c7ca93 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -259,6 +259,35 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled) generic_processor_info(id, ver); } +static int __init +acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) +{ + struct acpi_madt_local_x2apic *processor = NULL; + + processor = (struct acpi_madt_local_x2apic *)header; + + if (BAD_MADT_ENTRY(processor, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + +#ifdef CONFIG_X86_X2APIC + /* + * We need to register disabled CPU as well to permit + * counting disabled CPUs. This allows us to size + * cpus_possible_map more accurately, to permit + * to not preallocating memory for all NR_CPUS + * when we use CPU hotplug. + */ + acpi_register_lapic(processor->local_apic_id, /* APIC ID */ + processor->lapic_flags & ACPI_MADT_ENABLED); +#else + printk(KERN_WARNING PREFIX "x2apic entry ignored\n"); +#endif + + return 0; +} + static int __init acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) { @@ -318,6 +347,25 @@ acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, return 0; } +static int __init +acpi_parse_x2apic_nmi(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL; + + x2apic_nmi = (struct acpi_madt_local_x2apic_nmi *)header; + + if (BAD_MADT_ENTRY(x2apic_nmi, end)) + return -EINVAL; + + acpi_table_print_madt_entry(header); + + if (x2apic_nmi->lint != 1) + printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); + + return 0; +} + static int __init acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) { @@ -823,6 +871,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void) static int __init acpi_parse_madt_lapic_entries(void) { int count; + int x2count = 0; if (!cpu_has_apic) return -ENODEV; @@ -846,22 +895,28 @@ static int __init acpi_parse_madt_lapic_entries(void) count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, acpi_parse_sapic, MAX_APICS); - if (!count) + if (!count) { + x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, + acpi_parse_x2apic, MAX_APICS); count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, acpi_parse_lapic, MAX_APICS); - if (!count) { + } + if (!count && !x2count) { printk(KERN_ERR PREFIX "No LAPIC entries present\n"); /* TBD: Cleanup to allow fallback to MPS */ return -ENODEV; - } else if (count < 0) { + } else if (count < 0 || x2count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return count; } + x2count = + acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI, + acpi_parse_x2apic_nmi, 0); count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0); - if (count < 0) { + if (count < 0 || x2count < 0) { printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); /* TBD: Cleanup to allow fallback to MPS */ return count; diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 09737c8af074..13d56f5b1349 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -115,6 +115,36 @@ void __init acpi_numa_slit_init(struct acpi_table_slit *slit) reserve_early(phys, phys + length, "ACPI SLIT"); } +/* Callback for Proximity Domain -> x2APIC mapping */ +void __init +acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) +{ + int pxm, node; + int apic_id; + + if (srat_disabled()) + return; + if (pa->header.length < sizeof(struct acpi_srat_x2apic_cpu_affinity)) { + bad_srat(); + return; + } + if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0) + return; + pxm = pa->proximity_domain; + node = setup_node(pxm); + if (node < 0) { + printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm); + bad_srat(); + return; + } + + apic_id = pa->apic_id; + apicid_to_node[apic_id] = node; + acpi_numa = 1; + printk(KERN_INFO "SRAT: PXM %u -> APIC %u -> Node %u\n", + pxm, apic_id, node); +} + /* Callback for Proximity Domain -> LAPIC mapping */ void __init acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 3a0d8ef25c75..d440ccd27d91 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -131,6 +131,21 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header) #endif /* ACPI_DEBUG_OUTPUT */ break; + case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: +#ifdef ACPI_DEBUG_OUTPUT + { + struct acpi_srat_x2apic_cpu_affinity *p = + (struct acpi_srat_x2apic_cpu_affinity *)header; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "SRAT Processor (x2apicid[0x%08x]) in" + " proximity domain %d %s\n", + p->apic_id, + p->proximity_domain, + (p->flags & ACPI_SRAT_CPU_ENABLED) ? + "enabled" : "disabled")); + } +#endif /* ACPI_DEBUG_OUTPUT */ + break; default: printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = 0x%x)\n", @@ -180,8 +195,35 @@ static int __init acpi_parse_slit(struct acpi_table_header *table) return 0; } +void __init __attribute__ ((weak)) +acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) +{ + printk(KERN_WARNING PREFIX + "Found unsupported x2apic [0x%08x] SRAT entry\n", pa->apic_id); + return; +} + + static int __init -acpi_parse_processor_affinity(struct acpi_subtable_header * header, +acpi_parse_x2apic_affinity(struct acpi_subtable_header *header, + const unsigned long end) +{ + struct acpi_srat_x2apic_cpu_affinity *processor_affinity; + + processor_affinity = (struct acpi_srat_x2apic_cpu_affinity *)header; + if (!processor_affinity) + return -EINVAL; + + acpi_table_print_srat_entry(header); + + /* let architecture-dependent part to do it */ + acpi_numa_x2apic_affinity_init(processor_affinity); + + return 0; +} + +static int __init +acpi_parse_processor_affinity(struct acpi_subtable_header *header, const unsigned long end) { struct acpi_srat_cpu_affinity *processor_affinity; @@ -241,6 +283,8 @@ int __init acpi_numa_init(void) { /* SRAT: Static Resource Affinity Table */ if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) { + acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY, + acpi_parse_x2apic_affinity, NR_CPUS); acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY, acpi_parse_processor_affinity, NR_CPUS); acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY, diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 0cc2fd31e376..775324e34ffa 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -427,6 +427,29 @@ static int map_lapic_id(struct acpi_subtable_header *entry, return 0; } +static int map_x2apic_id(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, int *apic_id) +{ + struct acpi_madt_local_x2apic *apic = + (struct acpi_madt_local_x2apic *)entry; + u32 tmp = apic->local_apic_id; + + /* Only check enabled APICs*/ + if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) + return 0; + + /* Device statement declaration type */ + if (device_declaration) { + if (apic->uid == acpi_id) + goto found; + } + + return 0; +found: + *apic_id = tmp; + return 1; +} + static int map_lsapic_id(struct acpi_subtable_header *entry, int device_declaration, u32 acpi_id, int *apic_id) { @@ -476,6 +499,9 @@ static int map_madt_entry(int type, u32 acpi_id) if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { if (map_lapic_id(header, acpi_id, &apic_id)) break; + } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { + if (map_x2apic_id(header, type, acpi_id, &apic_id)) + break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (map_lsapic_id(header, type, acpi_id, &apic_id)) break; diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index a8852952fac4..991c006a301b 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -62,6 +62,18 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break; + case ACPI_MADT_TYPE_LOCAL_X2APIC: + { + struct acpi_madt_local_x2apic *p = + (struct acpi_madt_local_x2apic *)header; + printk(KERN_INFO PREFIX + "X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n", + p->local_apic_id, p->uid, + (p->lapic_flags & ACPI_MADT_ENABLED) ? + "enabled" : "disabled"); + } + break; + case ACPI_MADT_TYPE_IO_APIC: { struct acpi_madt_io_apic *p = @@ -116,6 +128,24 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header) } break; + case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI: + { + u16 polarity, trigger; + struct acpi_madt_local_x2apic_nmi *p = + (struct acpi_madt_local_x2apic_nmi *)header; + + polarity = p->inti_flags & ACPI_MADT_POLARITY_MASK; + trigger = (p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2; + + printk(KERN_INFO PREFIX + "X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n", + p->uid, + mps_inti_flags_polarity[polarity], + mps_inti_flags_trigger[trigger], + p->lint); + } + break; + case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: { struct acpi_madt_local_apic_override *p = diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 6fce2fc2d124..a6989e517549 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -96,6 +96,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); /* the following four functions are architecture-dependent */ void acpi_numa_slit_init (struct acpi_table_slit *slit); void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); +void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); void acpi_numa_arch_fixup(void); From 786c221a37d3931189d9c9421f63dec92f4d698b Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Mon, 30 Mar 2009 14:05:50 -0800 Subject: [PATCH 112/140] ACPI: update x2apic comments Signed-off-by: Suresh Siddha Signed-off-by: Len Brown --- include/acpi/actbl1.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 18963b968114..59ade0752473 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -1016,9 +1016,9 @@ struct acpi_madt_interrupt_source { struct acpi_madt_local_x2apic { struct acpi_subtable_header header; u16 reserved; /* Reserved - must be zero */ - u32 local_apic_id; /* Processor X2_APIC ID */ + u32 local_apic_id; /* Processor x2APIC ID */ u32 lapic_flags; - u32 uid; /* Extended X2_APIC processor ID */ + u32 uid; /* ACPI processor UID */ }; /* 10: Local X2APIC NMI (07/2008) */ @@ -1026,7 +1026,7 @@ struct acpi_madt_local_x2apic { struct acpi_madt_local_x2apic_nmi { struct acpi_subtable_header header; u16 inti_flags; - u32 uid; /* Processor X2_APIC ID */ + u32 uid; /* ACPI processor UID */ u8 lint; /* LINTn to which NMI is connected */ u8 reserved[3]; }; From 6328a57401dc5f5cf9931738eb7268fcd8058c49 Mon Sep 17 00:00:00 2001 From: Witold Szczeponik Date: Mon, 30 Mar 2009 19:31:06 +0200 Subject: [PATCH 113/140] Enable PNPACPI _PSx Support, v3 (This is an update to the patch presented earlier in http://lkml.org/lkml/2008/12/8/284, with new error handling.) This patch sets the power of PnP ACPI devices to D0 when they are activated and to D3 when they are disabled. The latter is in correspondence with the ACPI 3.0 specification, whereas the former is added in order to be able to power up a device after it has been previously disabled (or when booting up a system). (As a consequence, the patch makes the PnP ACPI code more ACPI compliant.) Section 6.2.2 of the ACPI Specification (at least versions 1.0b and 3.0a) states: "Prior to running this control method [_DIS], the OS[PM] will have already put the device in the D3 state." Unfortunately, there is no clear statement as to when to put a device in the D0 state. :-( Therefore, the patch executes the method calls as _PS3/_DIS and _SRS/_PS0. What is clear: "If the device is disabled, _SRS enables the device at the specified resources." (From the ACPI 3.0a Specification.) The patch fixes a problem with some IBM ThinkPads (at least the 600E and the 600X) where the serial ports have a dedicated power source that needs to be brought up before the serial port can be used. Without this patch, the serial port is enabled but has no power. (In the past, the tpctl utility had to be utilized to turn on the power, but support for this feature stopped with version 5.9 as it did not support the more recent kernel versions.) The error handlers that handle any errors that can occur during the power up/power down phases return the error codes to the caller directly. Comments welcome! :-) No regressions were observed on hardware that does not require this patch. The patch is applied against 2.6.27.x. Signed-off-by: Witold Szczeponik Acked-by: Zhao Yakui Signed-off-by: Len Brown --- drivers/pnp/pnpacpi/core.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 2834846a185d..9a3a682c6981 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -83,7 +83,6 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) acpi_handle handle = dev->data; struct acpi_buffer buffer; int ret; - acpi_status status; pnp_dbg(&dev->dev, "set resources\n"); ret = pnpacpi_build_resource_template(dev, &buffer); @@ -94,21 +93,31 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) kfree(buffer.pointer); return ret; } - status = acpi_set_current_resources(handle, &buffer); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(acpi_set_current_resources(handle, &buffer))) ret = -EINVAL; + else if (acpi_bus_power_manageable(handle)) + ret = acpi_bus_set_power(handle, ACPI_STATE_D0); kfree(buffer.pointer); return ret; } static int pnpacpi_disable_resources(struct pnp_dev *dev) { - acpi_status status; + acpi_handle handle = dev->data; + int ret; + + dev_dbg(&dev->dev, "disable resources\n"); /* acpi_unregister_gsi(pnp_irq(dev, 0)); */ - status = acpi_evaluate_object((acpi_handle) dev->data, - "_DIS", NULL, NULL); - return ACPI_FAILURE(status) ? -ENODEV : 0; + ret = 0; + if (acpi_bus_power_manageable(handle)) { + ret = acpi_bus_set_power(handle, ACPI_STATE_D3); + if (ret) + return ret; + } + if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DIS", NULL, NULL))) + ret = -ENODEV; + return ret; } #ifdef CONFIG_ACPI_SLEEP From 609d4bc949a9175a6c8ba9dc1b6fdb4d9dab0427 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 12 Mar 2009 11:58:25 +0000 Subject: [PATCH 114/140] ACPI: constify tables in pci_irq.c Signed-off-by: Jan Beulich Signed-off-by: Len Brown --- drivers/acpi/pci_irq.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 891bdf6679f3..f93667ee43dc 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -86,7 +86,7 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(struct pci_dev *dev, } /* http://bugzilla.kernel.org/show_bug.cgi?id=4773 */ -static struct dmi_system_id medion_md9580[] = { +static const struct dmi_system_id medion_md9580[] = { { .ident = "Medion MD9580-F laptop", .matches = { @@ -98,7 +98,7 @@ static struct dmi_system_id medion_md9580[] = { }; /* http://bugzilla.kernel.org/show_bug.cgi?id=5044 */ -static struct dmi_system_id dell_optiplex[] = { +static const struct dmi_system_id dell_optiplex[] = { { .ident = "Dell Optiplex GX1", .matches = { @@ -110,7 +110,7 @@ static struct dmi_system_id dell_optiplex[] = { }; /* http://bugzilla.kernel.org/show_bug.cgi?id=10138 */ -static struct dmi_system_id hp_t5710[] = { +static const struct dmi_system_id hp_t5710[] = { { .ident = "HP t5710", .matches = { @@ -123,13 +123,13 @@ static struct dmi_system_id hp_t5710[] = { }; struct prt_quirk { - struct dmi_system_id *system; + const struct dmi_system_id *system; unsigned int segment; unsigned int bus; unsigned int device; unsigned char pin; - char *source; /* according to BIOS */ - char *actual_source; + const char *source; /* according to BIOS */ + const char *actual_source; }; #define PCI_INTX_PIN(c) (c - 'A' + 1) @@ -139,7 +139,7 @@ struct prt_quirk { * interrupt at the listed segment/bus/device/pin is connected to the first * link device, but it is actually connected to the second. */ -static struct prt_quirk prt_quirks[] = { +static const struct prt_quirk prt_quirks[] = { { medion_md9580, 0, 0, 9, PCI_INTX_PIN('A'), "\\_SB_.PCI0.ISA_.LNKA", "\\_SB_.PCI0.ISA_.LNKB"}, @@ -155,7 +155,7 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, struct acpi_pci_routing_table *prt) { int i; - struct prt_quirk *quirk; + const struct prt_quirk *quirk; for (i = 0; i < ARRAY_SIZE(prt_quirks); i++) { quirk = &prt_quirks[i]; From 0b3f6109f0c9ff926b5ffc80dc1cebb24f192b35 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 9 Jan 2009 20:17:11 +0000 Subject: [PATCH 115/140] dell-wmi: new driver for hotkey control Add a WMI driver for Dell laptops. Currently it does nothing but send a generic input event when a button with a picture of a battery on it is pressed, but maybe other uses will appear over time. Signed-off-by: Matthew Garrett Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- MAINTAINERS | 5 + drivers/platform/x86/Kconfig | 10 ++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/dell-wmi.c | 210 ++++++++++++++++++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 drivers/platform/x86/dell-wmi.c diff --git a/MAINTAINERS b/MAINTAINERS index 5d460c9d1c2c..4ee59641c16c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1393,6 +1393,11 @@ P: Doug Warzecha M: Douglas_Warzecha@dell.com S: Maintained +DELL WMI EXTRAS DRIVER +P: Matthew Garrett +M: mjg59@srcf.ucam.org +S: Maintained + DEVICE NUMBER REGISTRY P: Torben Mathiasen M: device@lanana.org diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3608081bc3e0..a27bff3007c8 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -67,6 +67,16 @@ config DELL_LAPTOP This driver adds support for rfkill and backlight control to Dell laptops. +config DELL_WMI + tristate "Dell WMI extras" + depends on ACPI_WMI + depends on INPUT + ---help--- + Say Y here if you want to support WMI-based hotkeys on Dell laptops. + + To compile this driver as a module, choose M here: the module will + be called dell-wmi. + config FUJITSU_LAPTOP tristate "Fujitsu Laptop Extras" depends on ACPI diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index e29065120be9..e40c7bd1b87e 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o +obj-$(CONFIG_DELL_WMI) += dell-wmi.o obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_HP_WMI) += hp-wmi.o obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c new file mode 100644 index 000000000000..2fab94162147 --- /dev/null +++ b/drivers/platform/x86/dell-wmi.c @@ -0,0 +1,210 @@ +/* + * Dell WMI hotkeys + * + * Copyright (C) 2008 Red Hat + * + * Portions based on wistron_btns.c: + * Copyright (C) 2005 Miloslav Trmac + * Copyright (C) 2005 Bernhard Rosenkraenzer + * Copyright (C) 2005 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Matthew Garrett "); +MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver"); +MODULE_LICENSE("GPL"); + +#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" + +MODULE_ALIAS("wmi:"DELL_EVENT_GUID); + +struct key_entry { + char type; /* See KE_* below */ + u16 code; + u16 keycode; +}; + +enum { KE_KEY, KE_SW, KE_END }; + +static struct key_entry dell_wmi_keymap[] = { + {KE_KEY, 0xe045, KEY_PROG1}, + {KE_END, 0} +}; + +static struct input_dev *dell_wmi_input_dev; + +static struct key_entry *dell_wmi_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = dell_wmi_keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) +{ + struct key_entry *key; + + for (key = dell_wmi_keymap; key->type != KE_END; key++) + if (key->type == KE_KEY && keycode == key->keycode) + return key; + + return NULL; +} + +static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, + int *keycode) +{ + struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = dell_wmi_get_entry_by_scancode(scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!dell_wmi_get_entry_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + return -EINVAL; +} + +static void dell_wmi_notify(u32 value, void *context) +{ + struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; + static struct key_entry *key; + union acpi_object *obj; + + wmi_get_event_data(value, &response); + + obj = (union acpi_object *)response.pointer; + + if (obj && obj->type == ACPI_TYPE_BUFFER) { + int *buffer = (int *)obj->buffer.pointer; + key = dell_wmi_get_entry_by_scancode(buffer[1]); + if (key) { + input_report_key(dell_wmi_input_dev, key->keycode, 1); + input_sync(dell_wmi_input_dev); + input_report_key(dell_wmi_input_dev, key->keycode, 0); + input_sync(dell_wmi_input_dev); + } else + printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", + buffer[1]); + } +} + +static int __init dell_wmi_input_setup(void) +{ + struct key_entry *key; + int err; + + dell_wmi_input_dev = input_allocate_device(); + + if (!dell_wmi_input_dev) + return -ENOMEM; + + dell_wmi_input_dev->name = "Dell WMI hotkeys"; + dell_wmi_input_dev->phys = "wmi/input0"; + dell_wmi_input_dev->id.bustype = BUS_HOST; + dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode; + dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode; + + for (key = dell_wmi_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, dell_wmi_input_dev->evbit); + set_bit(key->keycode, dell_wmi_input_dev->keybit); + break; + case KE_SW: + set_bit(EV_SW, dell_wmi_input_dev->evbit); + set_bit(key->keycode, dell_wmi_input_dev->swbit); + break; + } + } + + err = input_register_device(dell_wmi_input_dev); + + if (err) { + input_free_device(dell_wmi_input_dev); + return err; + } + + return 0; +} + +static int __init dell_wmi_init(void) +{ + int err; + + if (wmi_has_guid(DELL_EVENT_GUID)) { + err = dell_wmi_input_setup(); + + if (err) + return err; + + err = wmi_install_notify_handler(DELL_EVENT_GUID, + dell_wmi_notify, NULL); + if (err) { + input_unregister_device(dell_wmi_input_dev); + printk(KERN_ERR "dell-wmi: Unable to register" + " notify handler - %d\n", err); + return err; + } + + } else + printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); + + return 0; +} + +static void __exit dell_wmi_exit(void) +{ + if (wmi_has_guid(DELL_EVENT_GUID)) { + wmi_remove_notify_handler(DELL_EVENT_GUID); + input_unregister_device(dell_wmi_input_dev); + } +} + +module_init(dell_wmi_init); +module_exit(dell_wmi_exit); From 070d8eb1f6b789206486ea6a4a1bb7745d86d314 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 12 Jan 2009 00:07:55 +0100 Subject: [PATCH 116/140] ACPI: constify VFTs (1/2) Signed-off-by: Jan Engelhardt Signed-off-by: Len Brown --- drivers/acpi/battery.c | 2 +- drivers/acpi/ec.c | 2 +- drivers/acpi/processor_thermal.c | 2 +- drivers/acpi/processor_throttling.c | 2 +- drivers/acpi/sbs.c | 14 +++++++------- drivers/acpi/video.c | 10 +++++----- include/acpi/processor.h | 4 ++-- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 69cbc57c2d1c..4d11b0704d5f 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -740,7 +740,7 @@ DECLARE_FILE_FUNCTIONS(alarm); static struct battery_file { struct file_operations ops; mode_t mode; - char *name; + const char *name; } acpi_battery_file[] = { FILE_DESCRIPTION_RO(info), FILE_DESCRIPTION_RO(state), diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 2fe15060dcdc..1ec61e52b390 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -672,7 +672,7 @@ static int acpi_ec_info_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_ec_read_info, PDE(inode)->data); } -static struct file_operations acpi_ec_info_ops = { +static const struct file_operations acpi_ec_info_ops = { .open = acpi_ec_info_open_fs, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index b1eb376fae45..1f31699359ba 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -507,7 +507,7 @@ static ssize_t acpi_processor_write_limit(struct file * file, return count; } -struct file_operations acpi_processor_limit_fops = { +const struct file_operations acpi_processor_limit_fops = { .owner = THIS_MODULE, .open = acpi_processor_limit_open_fs, .read = seq_read, diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index d27838171f4a..73aed5f5b973 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c @@ -1291,7 +1291,7 @@ static ssize_t acpi_processor_write_throttling(struct file *file, return count; } -struct file_operations acpi_processor_throttling_fops = { +const struct file_operations acpi_processor_throttling_fops = { .owner = THIS_MODULE, .open = acpi_processor_throttling_open_fs, .read = seq_read, diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 6050ce481873..1e3cf989196b 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -479,9 +479,9 @@ static int acpi_sbs_add_fs(struct proc_dir_entry **dir, struct proc_dir_entry *parent_dir, char *dir_name, - struct file_operations *info_fops, - struct file_operations *state_fops, - struct file_operations *alarm_fops, void *data) + const struct file_operations *info_fops, + const struct file_operations *state_fops, + const struct file_operations *alarm_fops, void *data) { if (!*dir) { *dir = proc_mkdir(dir_name, parent_dir); @@ -677,7 +677,7 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); } -static struct file_operations acpi_battery_info_fops = { +static const struct file_operations acpi_battery_info_fops = { .open = acpi_battery_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -685,7 +685,7 @@ static struct file_operations acpi_battery_info_fops = { .owner = THIS_MODULE, }; -static struct file_operations acpi_battery_state_fops = { +static const struct file_operations acpi_battery_state_fops = { .open = acpi_battery_state_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -693,7 +693,7 @@ static struct file_operations acpi_battery_state_fops = { .owner = THIS_MODULE, }; -static struct file_operations acpi_battery_alarm_fops = { +static const struct file_operations acpi_battery_alarm_fops = { .open = acpi_battery_alarm_open_fs, .read = seq_read, .write = acpi_battery_write_alarm, @@ -725,7 +725,7 @@ static int acpi_ac_state_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_ac_read_state, PDE(inode)->data); } -static struct file_operations acpi_ac_state_fops = { +static const struct file_operations acpi_ac_state_fops = { .open = acpi_ac_state_open_fs, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bb5ed059114a..65c3073a1dcb 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -189,7 +189,7 @@ struct acpi_video_device { /* bus */ static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_bus_info_fops = { +static const struct file_operations acpi_video_bus_info_fops = { .owner = THIS_MODULE, .open = acpi_video_bus_info_open_fs, .read = seq_read, @@ -198,7 +198,7 @@ static struct file_operations acpi_video_bus_info_fops = { }; static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_bus_ROM_fops = { +static const struct file_operations acpi_video_bus_ROM_fops = { .owner = THIS_MODULE, .open = acpi_video_bus_ROM_open_fs, .read = seq_read, @@ -208,7 +208,7 @@ static struct file_operations acpi_video_bus_ROM_fops = { static int acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_bus_POST_info_fops = { +static const struct file_operations acpi_video_bus_POST_info_fops = { .owner = THIS_MODULE, .open = acpi_video_bus_POST_info_open_fs, .read = seq_read, @@ -237,7 +237,7 @@ static struct file_operations acpi_video_bus_DOS_fops = { /* device */ static int acpi_video_device_info_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_device_info_fops = { +static const struct file_operations acpi_video_device_info_fops = { .owner = THIS_MODULE, .open = acpi_video_device_info_open_fs, .read = seq_read, @@ -267,7 +267,7 @@ static struct file_operations acpi_video_device_brightness_fops = { static int acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_device_EDID_fops = { +static const struct file_operations acpi_video_device_EDID_fops = { .owner = THIS_MODULE, .open = acpi_video_device_EDID_open_fs, .read = seq_read, diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 0574add2a1e3..b09c4fde9725 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -322,7 +322,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) int acpi_processor_tstate_has_changed(struct acpi_processor *pr); int acpi_processor_get_throttling_info(struct acpi_processor *pr); extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); -extern struct file_operations acpi_processor_throttling_fops; +extern const struct file_operations acpi_processor_throttling_fops; extern void acpi_processor_throttling_init(void); /* in processor_idle.c */ int acpi_processor_power_init(struct acpi_processor *pr, @@ -336,7 +336,7 @@ extern struct cpuidle_driver acpi_idle_driver; /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); -extern struct file_operations acpi_processor_limit_fops; +extern const struct file_operations acpi_processor_limit_fops; extern struct thermal_cooling_device_ops processor_cooling_ops; #ifdef CONFIG_CPU_FREQ void acpi_thermal_cpufreq_init(void); From b7171ae74b1741245835444bd98a7217958cf929 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 12 Jan 2009 00:08:19 +0100 Subject: [PATCH 117/140] ACPI: constify VFTs (2/2) Signed-off-by: Jan Engelhardt Signed-off-by: Len Brown --- drivers/acpi/video.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 65c3073a1dcb..52779549d367 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -217,19 +217,25 @@ static const struct file_operations acpi_video_bus_POST_info_fops = { }; static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_bus_POST_fops = { +static int acpi_video_bus_write_POST(struct file *file, + const char __user *buffer, size_t count, loff_t *data); +static const struct file_operations acpi_video_bus_POST_fops = { .owner = THIS_MODULE, .open = acpi_video_bus_POST_open_fs, .read = seq_read, + .write = acpi_video_bus_write_POST, .llseek = seq_lseek, .release = single_release, }; static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_bus_DOS_fops = { +static int acpi_video_bus_write_DOS(struct file *file, + const char __user *buffer, size_t count, loff_t *data); +static const struct file_operations acpi_video_bus_DOS_fops = { .owner = THIS_MODULE, .open = acpi_video_bus_DOS_open_fs, .read = seq_read, + .write = acpi_video_bus_write_DOS, .llseek = seq_lseek, .release = single_release, }; @@ -247,20 +253,26 @@ static const struct file_operations acpi_video_device_info_fops = { static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file); -static struct file_operations acpi_video_device_state_fops = { +static int acpi_video_device_write_state(struct file *file, + const char __user *buffer, size_t count, loff_t *data); +static const struct file_operations acpi_video_device_state_fops = { .owner = THIS_MODULE, .open = acpi_video_device_state_open_fs, .read = seq_read, + .write = acpi_video_device_write_state, .llseek = seq_lseek, .release = single_release, }; static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file); +static int acpi_video_device_write_brightness(struct file *file, + const char __user *buffer, size_t count, loff_t *data); static struct file_operations acpi_video_device_brightness_fops = { .owner = THIS_MODULE, .open = acpi_video_device_brightness_open_fs, .read = seq_read, + .write = acpi_video_device_write_brightness, .llseek = seq_lseek, .release = single_release, }; @@ -275,7 +287,7 @@ static const struct file_operations acpi_video_device_EDID_fops = { .release = single_release, }; -static char device_decode[][30] = { +static const char device_decode[][30] = { "motherboard VGA device", "PCI VGA device", "AGP VGA device", @@ -1134,7 +1146,6 @@ static int acpi_video_device_add_fs(struct acpi_device *device) goto err_remove_dir; /* 'state' [R/W] */ - acpi_video_device_state_fops.write = acpi_video_device_write_state; entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR, device_dir, &acpi_video_device_state_fops, @@ -1143,8 +1154,6 @@ static int acpi_video_device_add_fs(struct acpi_device *device) goto err_remove_info; /* 'brightness' [R/W] */ - acpi_video_device_brightness_fops.write = - acpi_video_device_write_brightness; entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR, device_dir, &acpi_video_device_brightness_fops, @@ -1427,7 +1436,6 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) goto err_remove_rom; /* 'POST' [R/W] */ - acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, device_dir, &acpi_video_bus_POST_fops, @@ -1436,7 +1444,6 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) goto err_remove_post_info; /* 'DOS' [R/W] */ - acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, device_dir, &acpi_video_bus_DOS_fops, From c542aadeb4700bc316834d862d52ba3d2664f13a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 14 Jan 2009 13:59:50 +0800 Subject: [PATCH 118/140] panasonic-laptop: Fix autoloading This patch adds MODULE_DEVICE_TABLE() to panasonic-laptop.c in order to ensure automatic loading of the module on systems with the respective "MAT*" ACPI devices. Signed-off-by: Martin Lucina Signed-off-by: Harald Welte Signed-off-by: Len Brown --- drivers/platform/x86/panasonic-laptop.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index c47a44dcb702..ecaca412a2a1 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -184,6 +184,7 @@ static const struct acpi_device_id pcc_device_ids[] = { { "MAT0019", 0}, { "", 0}, }; +MODULE_DEVICE_TABLE(acpi, pcc_device_ids); static struct acpi_driver acpi_pcc_driver = { .name = ACPI_PCC_DRIVER_NAME, From ba256b41bd58f0821c9c0e203982fb260f09bdeb Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 14 Jan 2009 14:01:17 +0800 Subject: [PATCH 119/140] panasonic-laptop: use snprintf with PAGE_SIZE in sysfs attributes Instead of just sprintf() into the page-sized buffer provided by the sysfs/device_attribute API, we use snprintf with PAGE_SIZE as an additional safeguard. Signed-off-by: Martin Lucina Signed-off-by: Harald Welte Signed-off-by: Len Brown --- drivers/platform/x86/panasonic-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index ecaca412a2a1..a5ce4bc202e3 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -367,7 +367,7 @@ static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr, if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) return -EIO; - return sprintf(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); + return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); } static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr, @@ -379,7 +379,7 @@ static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr, if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) return -EIO; - return sprintf(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]); + return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]); } static ssize_t show_mute(struct device *dev, struct device_attribute *attr, @@ -391,7 +391,7 @@ static ssize_t show_mute(struct device *dev, struct device_attribute *attr, if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) return -EIO; - return sprintf(buf, "%u\n", pcc->sinf[SINF_MUTE]); + return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]); } static ssize_t show_sticky(struct device *dev, struct device_attribute *attr, @@ -403,7 +403,7 @@ static ssize_t show_sticky(struct device *dev, struct device_attribute *attr, if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) return -EIO; - return sprintf(buf, "%u\n", pcc->sinf[SINF_STICKY_KEY]); + return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]); } static ssize_t set_sticky(struct device *dev, struct device_attribute *attr, From 1c762ca438447fa3525d84f4a0784a2021a66200 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:42 +0000 Subject: [PATCH 120/140] thinkpad-acpi: update copyright notices It is that time of the year again... Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d2433204a40c..792d22e958cb 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3,7 +3,7 @@ * * * Copyright (C) 2004-2005 Borislav Deianov - * Copyright (C) 2006-2008 Henrique de Moraes Holschuh + * Copyright (C) 2006-2009 Henrique de Moraes Holschuh * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 257bc1cb3e29c8da62b9c9e0a4505011776c7040 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:43 +0000 Subject: [PATCH 121/140] thinkpad-acpi: drop ibm-acpi alias The driver was renamed two years ago, on 2.6.21. Drop the old compatibility alias, we have given everybody quite enough time to update their configs to the new name. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 792d22e958cb..c83ec94eb8d9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -7517,9 +7517,6 @@ static int __init thinkpad_acpi_module_init(void) return 0; } -/* Please remove this in year 2009 */ -MODULE_ALIAS("ibm_acpi"); - MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); /* From 078ac19ed8f476a7c2d729712e15f5ab516ff491 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:44 +0000 Subject: [PATCH 122/140] thinkpad-acpi: documentation cleanup Some cleanups to the documentation of the driver. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 76 +++++++++++++++++-------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 41bc99fa1884..f6e6bc66eed3 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -20,7 +20,8 @@ moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel kernel 2.6.29 and release 0.22. The driver is named "thinkpad-acpi". In some places, like module -names, "thinkpad_acpi" is used because of userspace issues. +names and log messages, "thinkpad_acpi" is used because of userspace +issues. "tpacpi" is used as a shorthand where "thinkpad-acpi" would be too long due to length limitations on some Linux kernel versions. @@ -37,7 +38,7 @@ detailed description): - ThinkLight on and off - limited docking and undocking - UltraBay eject - - CMOS control + - CMOS/UCMS control - LED control - ACPI sounds - temperature sensors @@ -46,6 +47,7 @@ detailed description): - Volume control - Fan control and monitoring: fan speed, fan enable/disable - WAN enable and disable + - UWB enable and disable A compatibility table by model and feature is maintained on the web site, http://ibm-acpi.sf.net/. I appreciate any success or failure @@ -53,7 +55,7 @@ reports, especially if they add to or correct the compatibility table. Please include the following information in your report: - ThinkPad model name - - a copy of your DSDT, from /proc/acpi/dsdt + - a copy of your ACPI tables, using the "acpidump" utility - a copy of the output of dmidecode, with serial numbers and UUIDs masked off - which driver features work and which don't @@ -66,17 +68,18 @@ Installation ------------ If you are compiling this driver as included in the Linux kernel -sources, simply enable the CONFIG_THINKPAD_ACPI option, and optionally -enable the CONFIG_THINKPAD_ACPI_BAY option if you want the -thinkpad-specific bay functionality. +sources, look for the CONFIG_THINKPAD_ACPI Kconfig option. +It is located on the menu path: "Device Drivers" -> "X86 Platform +Specific Device Drivers" -> "ThinkPad ACPI Laptop Extras". + Features -------- The driver exports two different interfaces to userspace, which can be used to access the features it provides. One is a legacy procfs-based -interface, which will be removed at some time in the distant future. -The other is a new sysfs-based interface which is not complete yet. +interface, which will be removed at some time in the future. The other +is a new sysfs-based interface which is not complete yet. The procfs interface creates the /proc/acpi/ibm directory. There is a file under that directory for each feature it supports. The procfs @@ -111,15 +114,17 @@ The version of thinkpad-acpi's sysfs interface is exported by the driver as a driver attribute (see below). Sysfs driver attributes are on the driver's sysfs attribute space, -for 2.6.23 this is /sys/bus/platform/drivers/thinkpad_acpi/ and +for 2.6.23+ this is /sys/bus/platform/drivers/thinkpad_acpi/ and /sys/bus/platform/drivers/thinkpad_hwmon/ Sysfs device attributes are on the thinkpad_acpi device sysfs attribute -space, for 2.6.23 this is /sys/devices/platform/thinkpad_acpi/. +space, for 2.6.23+ this is /sys/devices/platform/thinkpad_acpi/. Sysfs device attributes for the sensors and fan are on the thinkpad_hwmon device's sysfs attribute space, but you should locate it -looking for a hwmon device with the name attribute of "thinkpad". +looking for a hwmon device with the name attribute of "thinkpad", or +better yet, through libsensors. + Driver version -------------- @@ -129,6 +134,7 @@ sysfs driver attribute: version The driver name and version. No commands can be written to this file. + Sysfs interface version ----------------------- @@ -160,6 +166,7 @@ expect that an attribute might not be there, and deal with it properly (an attribute not being there *is* a valid way to make it clear that a feature is not available in sysfs). + Hot keys -------- @@ -618,6 +625,7 @@ For Lenovo models *with* ACPI backlight control: and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process these keys on userspace somehow (e.g. by calling xbacklight). + Bluetooth --------- @@ -628,6 +636,9 @@ sysfs rfkill class: switch "tpacpi_bluetooth_sw" This feature shows the presence and current state of a ThinkPad Bluetooth device in the internal ThinkPad CDC slot. +If the ThinkPad supports it, the Bluetooth state is stored in NVRAM, +so it is kept across reboots and power-off. + Procfs notes: If Bluetooth is installed, the following commands can be used: @@ -652,6 +663,7 @@ Sysfs notes: rfkill controller switch "tpacpi_bluetooth_sw": refer to Documentation/rfkill.txt for details. + Video output control -- /proc/acpi/ibm/video -------------------------------------------- @@ -693,11 +705,8 @@ Fn-F7 from working. This also disables the video output switching features of this driver, as it uses the same ACPI methods as Fn-F7. Video switching on the console should still work. -UPDATE: There's now a patch for the X.org Radeon driver which -addresses this issue. Some people are reporting success with the patch -while others are still having problems. For more information: +UPDATE: refer to https://bugs.freedesktop.org/show_bug.cgi?id=2000 -https://bugs.freedesktop.org/show_bug.cgi?id=2000 ThinkLight control ------------------ @@ -720,10 +729,11 @@ The ThinkLight sysfs interface is documented by the LED class documentation, in Documentation/leds-class.txt. The ThinkLight LED name is "tpacpi::thinklight". -Due to limitations in the sysfs LED class, if the status of the thinklight +Due to limitations in the sysfs LED class, if the status of the ThinkLight cannot be read or if it is unknown, thinkpad-acpi will report it as "off". It is impossible to know if the status returned through sysfs is valid. + Docking / undocking -- /proc/acpi/ibm/dock ------------------------------------------ @@ -784,6 +794,7 @@ the only docking stations currently supported are the X-series UltraBase docks and "dumb" port replicators like the Mini Dock (the latter don't need any ACPI support, actually). + UltraBay eject -- /proc/acpi/ibm/bay ------------------------------------ @@ -847,8 +858,9 @@ supported. Use "eject2" instead of "eject" for the second bay. Note: the UltraBay eject support on the 600e/x, A22p and A3x is EXPERIMENTAL and may not work as expected. USE WITH CAUTION! -CMOS control ------------- + +CMOS/UCMS control +----------------- procfs: /proc/acpi/ibm/cmos sysfs device attribute: cmos_command @@ -882,6 +894,7 @@ The cmos command interface is prone to firmware split-brain problems, as in newer ThinkPads it is just a compatibility layer. Do not use it, it is exported just as a debug tool. + LED control ----------- @@ -939,6 +952,7 @@ ThinkPad indicator LED should blink in hardware accelerated mode, use the "timer" trigger, and leave the delay_on and delay_off parameters set to zero (to request hardware acceleration autodetection). + ACPI sounds -- /proc/acpi/ibm/beep ---------------------------------- @@ -968,6 +982,7 @@ X40: 16 - one medium-pitched beep repeating constantly, stop with 17 17 - stop 16 + Temperature sensors ------------------- @@ -1115,6 +1130,7 @@ registers contain the current battery capacity, etc. If you experiment with this, do send me your results (including some complete dumps with a description of the conditions when they were taken.) + LCD brightness control ---------------------- @@ -1124,10 +1140,9 @@ sysfs backlight device "thinkpad_screen" This feature allows software control of the LCD brightness on ThinkPad models which don't have a hardware brightness slider. -It has some limitations: the LCD backlight cannot be actually turned on or -off by this interface, and in many ThinkPad models, the "dim while on -battery" functionality will be enabled by the BIOS when this interface is -used, and cannot be controlled. +It has some limitations: the LCD backlight cannot be actually turned +on or off by this interface, it just controls the backlight brightness +level. On IBM (and some of the earlier Lenovo) ThinkPads, the backlight control has eight brightness levels, ranging from 0 to 7. Some of the levels @@ -1201,6 +1216,7 @@ WARNING: and maybe reduce the life of the backlight lamps by needlessly kicking its level up and down at every change. + Volume control -- /proc/acpi/ibm/volume --------------------------------------- @@ -1217,6 +1233,11 @@ distinct. The unmute the volume after the mute command, use either the up or down command (the level command will not unmute the volume). The current volume level and mute state is shown in the file. +The ALSA mixer interface to this feature is still missing, but patches +to add it exist. That problem should be addressed in the not so +distant future. + + Fan control and monitoring: fan speed, fan enable/disable --------------------------------------------------------- @@ -1383,8 +1404,11 @@ procfs: /proc/acpi/ibm/wan sysfs device attribute: wwan_enable (deprecated) sysfs rfkill class: switch "tpacpi_wwan_sw" -This feature shows the presence and current state of a W-WAN (Sierra -Wireless EV-DO) device. +This feature shows the presence and current state of the built-in +Wireless WAN device. + +If the ThinkPad supports it, the WWAN state is stored in NVRAM, +so it is kept across reboots and power-off. It was tested on a Lenovo ThinkPad X60. It should probably work on other ThinkPad models which come with this module installed. @@ -1413,6 +1437,7 @@ Sysfs notes: rfkill controller switch "tpacpi_wwan_sw": refer to Documentation/rfkill.txt for details. + EXPERIMENTAL: UWB ----------------- @@ -1431,6 +1456,7 @@ Sysfs notes: rfkill controller switch "tpacpi_uwb_sw": refer to Documentation/rfkill.txt for details. + Multiple Commands, Module Parameters ------------------------------------ @@ -1445,6 +1471,7 @@ for example: modprobe thinkpad_acpi hotkey=enable,0xffff video=auto_disable + Enabling debugging output ------------------------- @@ -1467,6 +1494,7 @@ The level of debugging information output by the driver can be changed at runtime through sysfs, using the driver attribute debug_level. The attribute takes the same bitmask as the debug module parameter above. + Force loading of module ----------------------- From 3dcc2c3b00cad01a0e3667607f8644e891e4dc8b Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:45 +0000 Subject: [PATCH 123/140] thinkpad-acpi: cleanup debug helpers Fix the vdbg_printk macro definition to be sane when CONFIG_THINKPAD_ACPI_DEBUG is undefined, and move the mess into a file section of its own. This doesn't change anything in the current code, but future code will need the proper behaviour. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 29 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index c83ec94eb8d9..3367df9d4f99 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -184,17 +184,6 @@ enum { #define TPACPI_DBG_ALL 0xffff #define TPACPI_DBG_INIT 0x0001 #define TPACPI_DBG_EXIT 0x0002 -#define dbg_printk(a_dbg_level, format, arg...) \ - do { if (dbg_level & a_dbg_level) \ - printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ - } while (0) -#ifdef CONFIG_THINKPAD_ACPI_DEBUG -#define vdbg_printk(a_dbg_level, format, arg...) \ - dbg_printk(a_dbg_level, format, ## arg) -static const char *str_supported(int is_supported); -#else -#define vdbg_printk(a_dbg_level, format, arg...) -#endif #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -326,6 +315,24 @@ static int tpacpi_uwb_emulstate; #endif +/************************************************************************* + * Debugging helpers + */ + +#define dbg_printk(a_dbg_level, format, arg...) \ + do { if (dbg_level & (a_dbg_level)) \ + printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ + } while (0) + +#ifdef CONFIG_THINKPAD_ACPI_DEBUG +#define vdbg_printk dbg_printk +static const char *str_supported(int is_supported); +#else +#define vdbg_printk(a_dbg_level, format, arg...) \ + do { } while (0) +#endif + + /**************************************************************************** **************************************************************************** * From 7ff8d62f7f055aaffbeb493863136c1b876bbe2e Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:46 +0000 Subject: [PATCH 124/140] thinkpad-acpi: add missing log levels Add missing log levels in a standalone commit, to avoid dependencies in future unrelated changes, just because they wanted to use one of the missing log levels. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 3367df9d4f99..6331b88d77d9 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -172,15 +172,18 @@ enum { TPACPI_RFK_UWB_SW_ID, }; -/* Debugging */ +/* printk headers */ #define TPACPI_LOG TPACPI_FILE ": " -#define TPACPI_ALERT KERN_ALERT TPACPI_LOG -#define TPACPI_CRIT KERN_CRIT TPACPI_LOG -#define TPACPI_ERR KERN_ERR TPACPI_LOG -#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG -#define TPACPI_INFO KERN_INFO TPACPI_LOG -#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG +#define TPACPI_EMERG KERN_EMERG TPACPI_LOG +#define TPACPI_ALERT KERN_ALERT TPACPI_LOG +#define TPACPI_CRIT KERN_CRIT TPACPI_LOG +#define TPACPI_ERR KERN_ERR TPACPI_LOG +#define TPACPI_WARN KERN_WARNING TPACPI_LOG +#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG +#define TPACPI_INFO KERN_INFO TPACPI_LOG +#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG +/* Debugging printk groups */ #define TPACPI_DBG_ALL 0xffff #define TPACPI_DBG_INIT 0x0001 #define TPACPI_DBG_EXIT 0x0002 From 73a94d86a8625371f76de0ee12dc5bacd3ed42c0 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:47 +0000 Subject: [PATCH 125/140] thinkpad-acpi: add new debug helpers and warn of deprecated atts Add a debug helper that discloses the TGID of the userspace task attempting to access the driver. This is highly useful when dealing with bug reports, since often the user has no idea that some userspace application is accessing thinkpad-acpi... Also add a helper to log warnings about sysfs attributes that are deprecated. Use the new helpers to issue deprecation warnings for bluetooth_enable and wwan_enabled, that have been deprecated for a while, now. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 2 ++ drivers/platform/x86/thinkpad_acpi.c | 40 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index f6e6bc66eed3..e8f52fbadfe0 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1484,6 +1484,8 @@ will enable all debugging output classes. It takes a bitmask, so to enable more than one output class, just add their values. Debug bitmask Description + 0x8000 Disclose PID of userspace programs + accessing some functions of the driver 0x0001 Initialization and probing 0x0002 Removal diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 6331b88d77d9..852be7c1a172 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -185,6 +186,7 @@ enum { /* Debugging printk groups */ #define TPACPI_DBG_ALL 0xffff +#define TPACPI_DBG_DISCLOSETASK 0x8000 #define TPACPI_DBG_INIT 0x0001 #define TPACPI_DBG_EXIT 0x0002 @@ -335,6 +337,21 @@ static const char *str_supported(int is_supported); do { } while (0) #endif +static void tpacpi_log_usertask(const char * const what) +{ + printk(TPACPI_DEBUG "%s: access by process with PID %d\n", + what, task_tgid_vnr(current)); +} + +#define tpacpi_disclose_usertask(what, format, arg...) \ + do { \ + if (unlikely( \ + (dbg_level & TPACPI_DBG_DISCLOSETASK) && \ + (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \ + printk(TPACPI_DEBUG "%s: PID %d: " format, \ + what, task_tgid_vnr(current), ## arg); \ + } \ + } while (0) /**************************************************************************** **************************************************************************** @@ -1030,6 +1047,21 @@ static int __init tpacpi_new_rfkill(const unsigned int id, return 0; } +static void printk_deprecated_attribute(const char * const what, + const char * const details) +{ + tpacpi_log_usertask("deprecated sysfs attribute"); + printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and " + "will be removed. %s\n", + what, details); +} + +static void printk_deprecated_rfkill_attribute(const char * const what) +{ + printk_deprecated_attribute(what, + "Please switch to generic rfkill before year 2010"); +} + /************************************************************************* * thinkpad-acpi driver attributes */ @@ -3070,6 +3102,8 @@ static ssize_t bluetooth_enable_show(struct device *dev, { int status; + printk_deprecated_rfkill_attribute("bluetooth_enable"); + status = bluetooth_get_radiosw(); if (status < 0) return status; @@ -3085,6 +3119,8 @@ static ssize_t bluetooth_enable_store(struct device *dev, unsigned long t; int res; + printk_deprecated_rfkill_attribute("bluetooth_enable"); + if (parse_strtoul(buf, 1, &t)) return -EINVAL; @@ -3347,6 +3383,8 @@ static ssize_t wan_enable_show(struct device *dev, { int status; + printk_deprecated_rfkill_attribute("wwan_enable"); + status = wan_get_radiosw(); if (status < 0) return status; @@ -3362,6 +3400,8 @@ static ssize_t wan_enable_store(struct device *dev, unsigned long t; int res; + printk_deprecated_rfkill_attribute("wwan_enable"); + if (parse_strtoul(buf, 1, &t)) return -EINVAL; From 2586d5663d0a17d69383acf6110f16a979a07c4e Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:48 +0000 Subject: [PATCH 126/140] thinkpad-acpi: remove HKEY disable functionality The HKEY disable functionality basically cripples the entire event model of the ThinkPad firmware and of the thinkpad-acpi driver. Remove this functionality from the driver. HKEY must be enabled at all times while thinkpad-acpi is loaded, and disabled otherwise. For sysfs, according to the sysfs ABI and the thinkpad-acpi sysfs rules of engagement, we will just remove the attributes. This will be done in two stages: disable their function now, after two kernel releases, remove the attributes. For procfs, we call WARN(). If nothing triggers it, I will simply remove the enable/disable commands entirely in the future along with the sysfs attributes. I don't expect much, if any fallout from this. There really isn't any reason to mess with hotkey_enable or with the enable/disable commands to /proc/acpi/ibm/hotkey, and this has been true for years... Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 39 ++++++++++---------- drivers/platform/x86/thinkpad_acpi.c | 49 ++++++++++++++----------- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index e8f52fbadfe0..de6f14c79070 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -179,17 +179,14 @@ system. Enabling the hotkey functionality of thinkpad-acpi signals the firmware that such a driver is present, and modifies how the ThinkPad firmware will behave in many situations. -The driver enables the hot key feature automatically when loaded. The -feature can later be disabled and enabled back at runtime. The driver -will also restore the hot key feature to its previous state and mask -when it is unloaded. +The driver enables the HKEY ("hot key") event reporting automatically +when loaded, and disables it when it is removed. -When the hotkey feature is enabled and the hot key mask is set (see -below), the driver will report HKEY events in the following format: +The driver will report HKEY events in the following format: ibm/hotkey HKEY 00000080 0000xxxx -Some of these events refer to hot key presses, but not all. +Some of these events refer to hot key presses, but not all of them. The driver will generate events over the input layer for hot keys and radio switches, and over the ACPI netlink layer for other events. The @@ -221,13 +218,17 @@ procfs notes: The following commands can be written to the /proc/acpi/ibm/hotkey file: - echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature - echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys ... any other 8-hex-digit mask ... echo reset > /proc/acpi/ibm/hotkey -- restore the original mask +The following commands have been deprecated and will cause the kernel +to log a warning: + + echo enable > /proc/acpi/ibm/hotkey -- does nothing + echo disable > /proc/acpi/ibm/hotkey -- returns an error + The procfs interface does not support NVRAM polling control. So as to maintain maximum bug-to-bug compatibility, it does not report any masks, nor does it allow one to manipulate the hot key mask when the firmware @@ -236,12 +237,9 @@ does not support masks at all, even if NVRAM polling is in use. sysfs notes: hotkey_bios_enabled: - Returns the status of the hot keys feature when - thinkpad-acpi was loaded. Upon module unload, the hot - key feature status will be restored to this value. + DEPRECATED, WILL BE REMOVED SOON. - 0: hot keys were disabled - 1: hot keys were enabled (unusual) + Returns 0. hotkey_bios_mask: Returns the hot keys mask when thinkpad-acpi was loaded. @@ -249,13 +247,10 @@ sysfs notes: to this value. hotkey_enable: - Enables/disables the hot keys feature in the ACPI - firmware, and reports current status of the hot keys - feature. Has no effect on the NVRAM hot key polling - functionality. + DEPRECATED, WILL BE REMOVED SOON. - 0: disables the hot keys feature / feature disabled - 1: enables the hot keys feature / feature enabled + 0: returns -EPERM + 1: does nothing hotkey_mask: bit mask to enable driver-handling (and depending on @@ -1535,3 +1530,7 @@ Sysfs interface changelog: 0x020200: Add poll()/select() support to the following attributes: hotkey_radio_sw, wakeup_hotunplug_complete, wakeup_reason + +0x020300: hotkey enable/disable support removed, attributes + hotkey_bios_enabled and hotkey_enable deprecated and + marked for removal. diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 852be7c1a172..f003fb7c79ca 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -22,7 +22,7 @@ */ #define TPACPI_VERSION "0.22" -#define TPACPI_SYSFS_VERSION 0x020200 +#define TPACPI_SYSFS_VERSION 0x020300 /* * Changelog: @@ -1424,7 +1424,6 @@ static enum { /* Reasons for waking up */ static int hotkey_autosleep_ack; -static int hotkey_orig_status; static u32 hotkey_orig_mask; static u32 hotkey_all_mask; static u32 hotkey_reserved_mask; @@ -1571,9 +1570,9 @@ static int hotkey_status_get(int *status) return 0; } -static int hotkey_status_set(int status) +static int hotkey_status_set(bool enable) { - if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status)) + if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", enable ? 1 : 0)) return -EIO; return 0; @@ -1889,6 +1888,9 @@ static ssize_t hotkey_enable_show(struct device *dev, { int res, status; + printk_deprecated_attribute("hotkey_enable", + "Hotkey reporting is always enabled"); + res = hotkey_status_get(&status); if (res) return res; @@ -1901,14 +1903,17 @@ static ssize_t hotkey_enable_store(struct device *dev, const char *buf, size_t count) { unsigned long t; - int res; + + printk_deprecated_attribute("hotkey_enable", + "Hotkeys can be disabled through hotkey_mask"); if (parse_strtoul(buf, 1, &t)) return -EINVAL; - res = hotkey_status_set(t); + if (t == 0) + return -EPERM; - return (res) ? res : count; + return count; } static struct device_attribute dev_attr_hotkey_enable = @@ -1964,7 +1969,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status); + return sprintf(buf, "0\n"); } static struct device_attribute dev_attr_hotkey_bios_enabled = @@ -2243,7 +2248,7 @@ static void hotkey_exit(void) "restoring original hot key mask\n"); /* no short-circuit boolean operator below! */ if ((hotkey_mask_set(hotkey_orig_mask) | - hotkey_status_set(hotkey_orig_status)) != 0) + hotkey_status_set(false)) != 0) printk(TPACPI_ERR "failed to restore hot key mask " "to BIOS defaults\n"); @@ -2438,10 +2443,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* hotkey_source_mask *must* be zero for * the first hotkey_mask_get */ - res = hotkey_status_get(&hotkey_orig_status); - if (res) - goto err_exit; - if (tp_features.hotkey_mask) { res = hotkey_mask_get(); if (res) @@ -2581,7 +2582,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) } dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); - res = hotkey_status_set(1); + res = hotkey_status_set(true); if (res) { hotkey_exit(); return res; @@ -2926,9 +2927,17 @@ static int hotkey_read(char *p) return len; } +static void hotkey_enabledisable_warn(void) +{ + tpacpi_log_usertask("procfs hotkey enable/disable"); + WARN(1, TPACPI_WARN + "hotkey enable/disable functionality has been " + "removed from the driver. Hotkeys are always enabled.\n"); +} + static int hotkey_write(char *buf) { - int res, status; + int res; u32 mask; char *cmd; @@ -2938,17 +2947,16 @@ static int hotkey_write(char *buf) if (mutex_lock_killable(&hotkey_mutex)) return -ERESTARTSYS; - status = -1; mask = hotkey_mask; res = 0; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "enable") == 0) { - status = 1; + hotkey_enabledisable_warn(); } else if (strlencmp(cmd, "disable") == 0) { - status = 0; + hotkey_enabledisable_warn(); + res = -EPERM; } else if (strlencmp(cmd, "reset") == 0) { - status = hotkey_orig_status; mask = hotkey_orig_mask; } else if (sscanf(cmd, "0x%x", &mask) == 1) { /* mask set */ @@ -2959,9 +2967,6 @@ static int hotkey_write(char *buf) goto errexit; } } - if (status != -1) - res = hotkey_status_set(status); - if (!res && mask != hotkey_mask) res = hotkey_mask_set(mask); From a4d5effcc73749ee3ebbf578d162905e6fa4e07d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:49 +0000 Subject: [PATCH 127/140] thinkpad-acpi: restrict access to some firmware LEDs Some of the ThinkPad LEDs indicate critical conditions that can cause data loss or cause hardware damage when ignored (e.g. force-ejecting a powered up bay; ignoring a failing battery, or empty battery; force- undocking with the dock buses still active, etc). On almost all ThinkPads, LED access is write-only, and the firmware usually does fire-and-forget signaling on them, so you effectively lose whatever message the firmware was trying to convey to the user when you override the LED state, without any chance to restore it. Restrict access to all LEDs that can convey important alarms, or that could mislead the user into incorrectly operating the hardware. This will make the Lenovo engineers less unhappy about the whole issue. Allow users that really want it to still control all LEDs, it is the unaware user that we have to worry about. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 11 ++++ drivers/platform/x86/Kconfig | 24 ++++++++ drivers/platform/x86/thinkpad_acpi.c | 76 ++++++++++++++++++------- 3 files changed, 91 insertions(+), 20 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index de6f14c79070..bce1d959b703 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -901,6 +901,17 @@ some older ThinkPad models, it is possible to query the status of the LED indicators as well. Newer ThinkPads cannot query the real status of the LED indicators. +Because misuse of the LEDs could induce an unaware user to perform +dangerous actions (like undocking or ejecting a bay device while the +buses are still active), or mask an important alarm (such as a nearly +empty battery, or a broken battery), access to most LEDs is +restricted. + +Unrestricted access to all LEDs requires that thinkpad-acpi be +compiled with the CONFIG_THINKPAD_ACPI_UNSAFE_LEDS option enabled. +Distributions must never enable this option. Individual users that +are aware of the consequences are welcome to enabling it. + procfs notes: The available commands are: diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 3608081bc3e0..d45c6ab729f8 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -226,6 +226,30 @@ config THINKPAD_ACPI_DEBUG If you are not sure, say N here. +config THINKPAD_ACPI_UNSAFE_LEDS + bool "Allow control of important LEDs (unsafe)" + depends on THINKPAD_ACPI + default n + ---help--- + Overriding LED state on ThinkPads can mask important + firmware alerts (like critical battery condition), or misled + the user into damaging the hardware (undocking or ejecting + the bay while buses are still active), etc. + + LED control on the ThinkPad is write-only (with very few + exceptions on very ancient models), which makes it + impossible to know beforehand if important information will + be lost when one changes LED state. + + Users that know what they are doing can enable this option + and the driver will allow control of every LED, including + the ones on the dock stations. + + Never enable this option on a distribution kernel. + + Say N here, unless you are building a kernel for your own + use, and need to control the important firmware LEDs. + config THINKPAD_ACPI_DOCK bool "Legacy Docking Station Support" depends on THINKPAD_ACPI diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index f003fb7c79ca..38c34c79ff35 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -4657,6 +4657,16 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { "tpacpi::unknown_led", "tpacpi::standby", }; +#define TPACPI_SAFE_LEDS 0x0081U + +static inline bool tpacpi_is_led_restricted(const unsigned int led) +{ +#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS + return false; +#else + return (TPACPI_SAFE_LEDS & (1 << led)) == 0; +#endif +} static int led_get_status(const unsigned int led) { @@ -4694,16 +4704,20 @@ static int led_set_status(const unsigned int led, switch (led_supported) { case TPACPI_LED_570: /* 570 */ - if (led > 7) + if (unlikely(led > 7)) return -EINVAL; + if (unlikely(tpacpi_is_led_restricted(led))) + return -EPERM; if (!acpi_evalf(led_handle, NULL, NULL, "vdd", (1 << led), led_sled_arg1[ledstatus])) rc = -EIO; break; case TPACPI_LED_OLD: /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ - if (led > 7) + if (unlikely(led > 7)) return -EINVAL; + if (unlikely(tpacpi_is_led_restricted(led))) + return -EPERM; rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); if (rc >= 0) rc = ec_write(TPACPI_LED_EC_HLBL, @@ -4714,6 +4728,10 @@ static int led_set_status(const unsigned int led, break; case TPACPI_LED_NEW: /* all others */ + if (unlikely(led >= TPACPI_LED_NUMLEDS)) + return -EINVAL; + if (unlikely(tpacpi_is_led_restricted(led))) + return -EPERM; if (!acpi_evalf(led_handle, NULL, NULL, "vdd", led, led_led_arg1[ledstatus])) rc = -EIO; @@ -4806,6 +4824,30 @@ static void led_exit(void) kfree(tpacpi_leds); } +static int __init tpacpi_init_led(unsigned int led) +{ + int rc; + + tpacpi_leds[led].led = led; + + tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; + tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; + if (led_supported == TPACPI_LED_570) + tpacpi_leds[led].led_classdev.brightness_get = + &led_sysfs_get; + + tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led]; + + INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker); + + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_leds[led].led_classdev); + if (rc < 0) + tpacpi_leds[led].led_classdev.name = NULL; + + return rc; +} + static int __init led_init(struct ibm_init_struct *iibm) { unsigned int i; @@ -4839,27 +4881,21 @@ static int __init led_init(struct ibm_init_struct *iibm) } for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { - tpacpi_leds[i].led = i; - - tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set; - tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set; - if (led_supported == TPACPI_LED_570) - tpacpi_leds[i].led_classdev.brightness_get = - &led_sysfs_get; - - tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i]; - - INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker); - - rc = led_classdev_register(&tpacpi_pdev->dev, - &tpacpi_leds[i].led_classdev); - if (rc < 0) { - tpacpi_leds[i].led_classdev.name = NULL; - led_exit(); - return rc; + if (!tpacpi_is_led_restricted(i)) { + rc = tpacpi_init_led(i); + if (rc < 0) { + led_exit(); + return rc; + } } } +#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS + if (led_supported != TPACPI_LED_NONE) + printk(TPACPI_NOTICE + "warning: userspace override of important " + "firmware LEDs is enabled\n"); +#endif return (led_supported != TPACPI_LED_NONE)? 0 : 1; } From bee4cd9b9eaa8c72832e1ee7f4940604e94beb27 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:50 +0000 Subject: [PATCH 128/140] thinkpad-acpi: enhanced debugging messages for rfkill subdrivers Enhance debugging messages for all rfkill subdrivers in thinkpad-acpi. Also, log a warning if the deprecated sysfs attributes are in use. These attributes are going to be removed sometime in 2010. There is an user-visible side-effect: we now coalesce attempts to enable/disable bluetooth or WWAN in the procfs interface, instead of hammering the firmware with multiple requests. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 2 + drivers/platform/x86/thinkpad_acpi.c | 117 +++++++++++++++++++----- 2 files changed, 98 insertions(+), 21 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index bce1d959b703..7daca0553676 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1494,6 +1494,8 @@ to enable more than one output class, just add their values. accessing some functions of the driver 0x0001 Initialization and probing 0x0002 Removal + 0x0004 RF Transmitter control (RFKILL) + (bluetooth, WWAN, UWB...) There is also a kernel build option to enable more debugging information, which may be necessary to debug driver problems. diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 38c34c79ff35..57ab5512c796 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -189,6 +189,7 @@ enum { #define TPACPI_DBG_DISCLOSETASK 0x8000 #define TPACPI_DBG_INIT 0x0001 #define TPACPI_DBG_EXIT 0x0002 +#define TPACPI_DBG_RFKILL 0x0004 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -1016,10 +1017,13 @@ static int __init tpacpi_new_rfkill(const unsigned int id, /* try to set the initial state as the default for the rfkill * type, since we ask the firmware to preserve it across S5 in * NVRAM */ - rfkill_set_default(rfktype, + if (rfkill_set_default(rfktype, (initial_state == RFKILL_STATE_UNBLOCKED) ? RFKILL_STATE_UNBLOCKED : - RFKILL_STATE_SOFT_BLOCKED); + RFKILL_STATE_SOFT_BLOCKED) == -EPERM) + vdbg_printk(TPACPI_DBG_RFKILL, + "Default state for %s cannot be changed\n", + name); } *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); @@ -3018,13 +3022,17 @@ enum { TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */ }; +#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" + static struct rfkill *tpacpi_bluetooth_rfkill; static void bluetooth_suspend(pm_message_t state) { /* Try to make sure radio will resume powered off */ - acpi_evalf(NULL, NULL, "\\BLTH", "vd", - TP_ACPI_BLTH_PWR_OFF_ON_RESUME); + if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd", + TP_ACPI_BLTH_PWR_OFF_ON_RESUME)) + vdbg_printk(TPACPI_DBG_RFKILL, + "bluetooth power down on resume request failed\n"); } static int bluetooth_get_radiosw(void) @@ -3062,6 +3070,10 @@ static void bluetooth_update_rfk(void) if (status < 0) return; rfkill_force_state(tpacpi_bluetooth_rfkill, status); + + vdbg_printk(TPACPI_DBG_RFKILL, + "forced rfkill state to %d\n", + status); } static int bluetooth_set_radiosw(int radio_on, int update_rfk) @@ -3077,6 +3089,9 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk) && radio_on) return -EPERM; + vdbg_printk(TPACPI_DBG_RFKILL, + "will %s bluetooth\n", radio_on ? "enable" : "disable"); + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_bluetoothemul) { tpacpi_bluetooth_emulstate = !!radio_on; @@ -3129,6 +3144,8 @@ static ssize_t bluetooth_enable_store(struct device *dev, if (parse_strtoul(buf, 1, &t)) return -EINVAL; + tpacpi_disclose_usertask("bluetooth_enable", "set to %ld\n", t); + res = bluetooth_set_radiosw(t, 1); return (res) ? res : count; @@ -3162,6 +3179,8 @@ static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state) static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) { + dbg_printk(TPACPI_DBG_RFKILL, + "request to change radio state to %d\n", state); return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); } @@ -3172,6 +3191,9 @@ static void bluetooth_shutdown(void) TP_ACPI_BLTH_SAVE_STATE)) printk(TPACPI_NOTICE "failed to save bluetooth state to NVRAM\n"); + else + vdbg_printk(TPACPI_DBG_RFKILL, + "bluestooth state saved to NVRAM\n"); } static void bluetooth_exit(void) @@ -3190,7 +3212,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) int res; int status = 0; - vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, + "initializing bluetooth subdriver\n"); TPACPI_ACPIHANDLE_INIT(hkey); @@ -3199,7 +3222,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) tp_features.bluetooth = hkey_handle && acpi_evalf(hkey_handle, &status, "GBDC", "qd"); - vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n", + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, + "bluetooth is %s, status 0x%02x\n", str_supported(tp_features.bluetooth), status); @@ -3214,7 +3238,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { /* no bluetooth hardware present in system */ tp_features.bluetooth = 0; - dbg_printk(TPACPI_DBG_INIT, + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, "bluetooth hardware not installed\n"); } @@ -3229,7 +3253,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, &tpacpi_bluetooth_rfkill, RFKILL_TYPE_BLUETOOTH, - "tpacpi_bluetooth_sw", + TPACPI_RFK_BLUETOOTH_SW_NAME, true, tpacpi_bluetooth_rfk_set, tpacpi_bluetooth_rfk_get); @@ -3262,19 +3286,27 @@ static int bluetooth_read(char *p) static int bluetooth_write(char *buf) { char *cmd; + int state = -1; if (!tp_features.bluetooth) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "enable") == 0) { - bluetooth_set_radiosw(1, 1); + state = 1; } else if (strlencmp(cmd, "disable") == 0) { - bluetooth_set_radiosw(0, 1); + state = 0; } else return -EINVAL; } + if (state != -1) { + tpacpi_disclose_usertask("procfs bluetooth", + "attempt to %s\n", + state ? "enable" : "disable"); + bluetooth_set_radiosw(state, 1); + } + return 0; } @@ -3299,13 +3331,17 @@ enum { off / last state */ }; +#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" + static struct rfkill *tpacpi_wan_rfkill; static void wan_suspend(pm_message_t state) { /* Try to make sure radio will resume powered off */ - acpi_evalf(NULL, NULL, "\\WGSV", "qvd", - TP_ACPI_WGSV_PWR_OFF_ON_RESUME); + if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd", + TP_ACPI_WGSV_PWR_OFF_ON_RESUME)) + vdbg_printk(TPACPI_DBG_RFKILL, + "WWAN power down on resume request failed\n"); } static int wan_get_radiosw(void) @@ -3343,6 +3379,10 @@ static void wan_update_rfk(void) if (status < 0) return; rfkill_force_state(tpacpi_wan_rfkill, status); + + vdbg_printk(TPACPI_DBG_RFKILL, + "forced rfkill state to %d\n", + status); } static int wan_set_radiosw(int radio_on, int update_rfk) @@ -3358,6 +3398,9 @@ static int wan_set_radiosw(int radio_on, int update_rfk) && radio_on) return -EPERM; + vdbg_printk(TPACPI_DBG_RFKILL, + "will %s WWAN\n", radio_on ? "enable" : "disable"); + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_wwanemul) { tpacpi_wwan_emulstate = !!radio_on; @@ -3410,6 +3453,8 @@ static ssize_t wan_enable_store(struct device *dev, if (parse_strtoul(buf, 1, &t)) return -EINVAL; + tpacpi_disclose_usertask("wwan_enable", "set to %ld\n", t); + res = wan_set_radiosw(t, 1); return (res) ? res : count; @@ -3443,6 +3488,8 @@ static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state) static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) { + dbg_printk(TPACPI_DBG_RFKILL, + "request to change radio state to %d\n", state); return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); } @@ -3453,6 +3500,9 @@ static void wan_shutdown(void) TP_ACPI_WGSV_SAVE_STATE)) printk(TPACPI_NOTICE "failed to save WWAN state to NVRAM\n"); + else + vdbg_printk(TPACPI_DBG_RFKILL, + "WWAN state saved to NVRAM\n"); } static void wan_exit(void) @@ -3471,14 +3521,16 @@ static int __init wan_init(struct ibm_init_struct *iibm) int res; int status = 0; - vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, + "initializing wan subdriver\n"); TPACPI_ACPIHANDLE_INIT(hkey); tp_features.wan = hkey_handle && acpi_evalf(hkey_handle, &status, "GWAN", "qd"); - vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n", + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, + "wan is %s, status 0x%02x\n", str_supported(tp_features.wan), status); @@ -3493,7 +3545,7 @@ static int __init wan_init(struct ibm_init_struct *iibm) !(status & TP_ACPI_WANCARD_HWPRESENT)) { /* no wan hardware present in system */ tp_features.wan = 0; - dbg_printk(TPACPI_DBG_INIT, + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, "wan hardware not installed\n"); } @@ -3508,7 +3560,7 @@ static int __init wan_init(struct ibm_init_struct *iibm) res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, &tpacpi_wan_rfkill, RFKILL_TYPE_WWAN, - "tpacpi_wwan_sw", + TPACPI_RFK_WWAN_SW_NAME, true, tpacpi_wan_rfk_set, tpacpi_wan_rfk_get); @@ -3526,6 +3578,8 @@ static int wan_read(char *p) int len = 0; int status = wan_get_radiosw(); + tpacpi_disclose_usertask("procfs wan", "read"); + if (!tp_features.wan) len += sprintf(p + len, "status:\t\tnot supported\n"); else { @@ -3541,19 +3595,27 @@ static int wan_read(char *p) static int wan_write(char *buf) { char *cmd; + int state = -1; if (!tp_features.wan) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "enable") == 0) { - wan_set_radiosw(1, 1); + state = 1; } else if (strlencmp(cmd, "disable") == 0) { - wan_set_radiosw(0, 1); + state = 0; } else return -EINVAL; } + if (state != -1) { + tpacpi_disclose_usertask("procfs wan", + "attempt to %s\n", + state ? "enable" : "disable"); + wan_set_radiosw(state, 1); + } + return 0; } @@ -3576,6 +3638,8 @@ enum { TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */ }; +#define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw" + static struct rfkill *tpacpi_uwb_rfkill; static int uwb_get_radiosw(void) @@ -3613,6 +3677,10 @@ static void uwb_update_rfk(void) if (status < 0) return; rfkill_force_state(tpacpi_uwb_rfkill, status); + + vdbg_printk(TPACPI_DBG_RFKILL, + "forced rfkill state to %d\n", + status); } static int uwb_set_radiosw(int radio_on, int update_rfk) @@ -3628,6 +3696,9 @@ static int uwb_set_radiosw(int radio_on, int update_rfk) && radio_on) return -EPERM; + vdbg_printk(TPACPI_DBG_RFKILL, + "will %s UWB\n", radio_on ? "enable" : "disable"); + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_uwbemul) { tpacpi_uwb_emulstate = !!radio_on; @@ -3662,6 +3733,8 @@ static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state) static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state) { + dbg_printk(TPACPI_DBG_RFKILL, + "request to change radio state to %d\n", state); return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); } @@ -3676,14 +3749,16 @@ static int __init uwb_init(struct ibm_init_struct *iibm) int res; int status = 0; - vdbg_printk(TPACPI_DBG_INIT, "initializing uwb subdriver\n"); + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, + "initializing uwb subdriver\n"); TPACPI_ACPIHANDLE_INIT(hkey); tp_features.uwb = hkey_handle && acpi_evalf(hkey_handle, &status, "GUWB", "qd"); - vdbg_printk(TPACPI_DBG_INIT, "uwb is %s, status 0x%02x\n", + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL, + "uwb is %s, status 0x%02x\n", str_supported(tp_features.uwb), status); @@ -3708,7 +3783,7 @@ static int __init uwb_init(struct ibm_init_struct *iibm) res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID, &tpacpi_uwb_rfkill, RFKILL_TYPE_UWB, - "tpacpi_uwb_sw", + TPACPI_RFK_UWB_SW_NAME, false, tpacpi_uwb_rfk_set, tpacpi_uwb_rfk_get); From 56e2c200945dafafb86169762eb1e88aed0ce69e Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:51 +0000 Subject: [PATCH 129/140] thinkpad-acpi: enhanced debugging messages for the hotkey subdriver Enhance debugging messages for the hotkey subdriver. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 1 + drivers/platform/x86/thinkpad_acpi.c | 39 ++++++++++++++++++------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 7daca0553676..abbbe78a003b 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1496,6 +1496,7 @@ to enable more than one output class, just add their values. 0x0002 Removal 0x0004 RF Transmitter control (RFKILL) (bluetooth, WWAN, UWB...) + 0x0008 HKEY event interface, hotkeys There is also a kernel build option to enable more debugging information, which may be necessary to debug driver problems. diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 57ab5512c796..0a4796a246ea 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -190,6 +190,7 @@ enum { #define TPACPI_DBG_INIT 0x0001 #define TPACPI_DBG_EXIT 0x0002 #define TPACPI_DBG_RFKILL 0x0004 +#define TPACPI_DBG_HKEY 0x0008 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -1961,6 +1962,8 @@ static ssize_t hotkey_mask_store(struct device *dev, mutex_unlock(&hotkey_mutex); + tpacpi_disclose_usertask("hotkey_mask", "set to 0x%08lx\n", t); + return (res) ? res : count; } @@ -2047,6 +2050,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev, mutex_unlock(&hotkey_mutex); + tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t); + return count; } @@ -2079,6 +2084,8 @@ static ssize_t hotkey_poll_freq_store(struct device *dev, hotkey_poll_setup(1); mutex_unlock(&hotkey_mutex); + tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); + return count; } @@ -2248,7 +2255,7 @@ static void hotkey_exit(void) kfree(hotkey_keycode_map); if (tp_features.hotkey) { - dbg_printk(TPACPI_DBG_EXIT, + dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY, "restoring original hot key mask\n"); /* no short-circuit boolean operator below! */ if ((hotkey_mask_set(hotkey_orig_mask) | @@ -2378,7 +2385,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) int status; int hkeyv; - vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "initializing hotkey subdriver\n"); BUG_ON(!tpacpi_inputdev); BUG_ON(tpacpi_inputdev->open != NULL || @@ -2395,7 +2403,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* hotkey not supported on 570 */ tp_features.hotkey = hkey_handle != NULL; - vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "hotkeys are %s\n", str_supported(tp_features.hotkey)); if (!tp_features.hotkey) @@ -2427,10 +2436,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) * T4x, X31, and later */ tp_features.hotkey_mask = 1; + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "firmware HKEY interface version: 0x%x\n", + hkeyv); } } - vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "hotkey masks are %s\n", str_supported(tp_features.hotkey_mask)); if (tp_features.hotkey_mask) { @@ -2469,7 +2482,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; } - vdbg_printk(TPACPI_DBG_INIT, + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, "hotkey source mask 0x%08x, polling freq %d\n", hotkey_source_mask, hotkey_poll_freq); #endif @@ -2523,12 +2536,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) } if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { - dbg_printk(TPACPI_DBG_INIT, + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, "using Lenovo default hot key map\n"); memcpy(hotkey_keycode_map, &lenovo_keycode_map, TPACPI_HOTKEY_MAP_SIZE); } else { - dbg_printk(TPACPI_DBG_INIT, + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, "using IBM default hot key map\n"); memcpy(hotkey_keycode_map, &ibm_keycode_map, TPACPI_HOTKEY_MAP_SIZE); @@ -2585,7 +2598,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | (1 << TP_ACPI_HOTKEYSCAN_FNEND); } - dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "enabling firmware HKEY event interface...\n"); res = hotkey_status_set(true); if (res) { hotkey_exit(); @@ -2599,8 +2613,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) return res; } - dbg_printk(TPACPI_DBG_INIT, - "legacy hot key reporting over procfs %s\n", + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "legacy ibm/hotkey event reporting over procfs %s\n", (hotkey_report_mode < 2) ? "enabled" : "disabled"); @@ -2971,6 +2985,11 @@ static int hotkey_write(char *buf) goto errexit; } } + + if (!res) + tpacpi_disclose_usertask("procfs hotkey", + "set mask to 0x%08x\n", mask); + if (!res && mask != hotkey_mask) res = hotkey_mask_set(mask); From 74a60c0f828016456fc635feae388ffd12bb3bb9 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:52 +0000 Subject: [PATCH 130/140] thinkpad-acpi: enhanced debugging messages for the fan subdriver Enhance debugging messages for the fan subdriver. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 1 + drivers/platform/x86/thinkpad_acpi.c | 46 ++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index abbbe78a003b..25ed43d0a21f 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1497,6 +1497,7 @@ to enable more than one output class, just add their values. 0x0004 RF Transmitter control (RFKILL) (bluetooth, WWAN, UWB...) 0x0008 HKEY event interface, hotkeys + 0x0010 Fan control There is also a kernel build option to enable more debugging information, which may be necessary to debug driver problems. diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0a4796a246ea..4eec77032a71 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -191,6 +191,7 @@ enum { #define TPACPI_DBG_EXIT 0x0002 #define TPACPI_DBG_RFKILL 0x0004 #define TPACPI_DBG_HKEY 0x0008 +#define TPACPI_DBG_FAN 0x0010 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -6271,6 +6272,9 @@ static int fan_set_level(int level) default: return -ENXIO; } + + vdbg_printk(TPACPI_DBG_FAN, + "fan control: set fan control register to 0x%02x\n", level); return 0; } @@ -6348,6 +6352,11 @@ static int fan_set_enable(void) } mutex_unlock(&fan_mutex); + + if (!rc) + vdbg_printk(TPACPI_DBG_FAN, + "fan control: set fan control register to 0x%02x\n", + s); return rc; } @@ -6384,6 +6393,9 @@ static int fan_set_disable(void) rc = -ENXIO; } + if (!rc) + vdbg_printk(TPACPI_DBG_FAN, + "fan control: set fan control register to 0\n"); mutex_unlock(&fan_mutex); return rc; @@ -6512,6 +6524,9 @@ static ssize_t fan_pwm1_enable_store(struct device *dev, if (parse_strtoul(buf, 2, &t)) return -EINVAL; + tpacpi_disclose_usertask("hwmon pwm1_enable", + "set fan mode to %lu\n", t); + switch (t) { case 0: level = TP_EC_FAN_FULLSPEED; @@ -6577,6 +6592,9 @@ static ssize_t fan_pwm1_store(struct device *dev, if (parse_strtoul(buf, 255, &s)) return -EINVAL; + tpacpi_disclose_usertask("hwmon pwm1", + "set fan speed to %lu\n", s); + /* scale down from 0-255 to 0-7 */ newlevel = (s >> 5) & 0x07; @@ -6643,6 +6661,8 @@ static ssize_t fan_fan_watchdog_store(struct device_driver *drv, fan_watchdog_maxinterval = t; fan_watchdog_reset(); + tpacpi_disclose_usertask("fan_watchdog", "set to %lu\n", t); + return count; } @@ -6664,7 +6684,8 @@ static int __init fan_init(struct ibm_init_struct *iibm) { int rc; - vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, + "initializing fan subdriver\n"); mutex_init(&fan_mutex); fan_status_access_mode = TPACPI_FAN_NONE; @@ -6723,7 +6744,8 @@ static int __init fan_init(struct ibm_init_struct *iibm) } } - vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n", + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, + "fan is %s, modes %d, %d\n", str_supported(fan_status_access_mode != TPACPI_FAN_NONE || fan_control_access_mode != TPACPI_FAN_WR_NONE), fan_status_access_mode, fan_control_access_mode); @@ -6732,7 +6754,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) if (!fan_control_allowed) { fan_control_access_mode = TPACPI_FAN_WR_NONE; fan_control_commands = 0; - dbg_printk(TPACPI_DBG_INIT, + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, "fan control features disabled by parameter\n"); } @@ -6761,7 +6783,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) static void fan_exit(void) { - vdbg_printk(TPACPI_DBG_EXIT, + vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_FAN, "cancelling any pending fan watchdog tasks\n"); /* FIXME: can we really do this unconditionally? */ @@ -6942,6 +6964,9 @@ static int fan_write_cmd_level(const char *cmd, int *rc) if (*rc == -ENXIO) printk(TPACPI_ERR "level command accepted for unsupported " "access mode %d", fan_control_access_mode); + else if (!*rc) + tpacpi_disclose_usertask("procfs fan", + "set level to %d\n", level); return 1; } @@ -6955,6 +6980,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc) if (*rc == -ENXIO) printk(TPACPI_ERR "enable command accepted for unsupported " "access mode %d", fan_control_access_mode); + else if (!*rc) + tpacpi_disclose_usertask("procfs fan", "enable\n"); return 1; } @@ -6968,6 +6995,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc) if (*rc == -ENXIO) printk(TPACPI_ERR "disable command accepted for unsupported " "access mode %d", fan_control_access_mode); + else if (!*rc) + tpacpi_disclose_usertask("procfs fan", "disable\n"); return 1; } @@ -6986,6 +7015,9 @@ static int fan_write_cmd_speed(const char *cmd, int *rc) if (*rc == -ENXIO) printk(TPACPI_ERR "speed command accepted for unsupported " "access mode %d", fan_control_access_mode); + else if (!*rc) + tpacpi_disclose_usertask("procfs fan", + "set speed to %d\n", speed); return 1; } @@ -6999,8 +7031,12 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc) if (interval < 0 || interval > 120) *rc = -EINVAL; - else + else { fan_watchdog_maxinterval = interval; + tpacpi_disclose_usertask("procfs fan", + "set watchdog timer to %d\n", + interval); + } return 1; } From 0e501834f8c2ba7de2a56e332d346dcf4ac0b593 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 4 Apr 2009 04:25:53 +0000 Subject: [PATCH 131/140] thinkpad-acpi: rework brightness support Refactor and redesign the brightness control backend... In order to fix bugzilla #11750... Add a new brightness control mode: support direct NVRAM checkpointing of the backlight level (i.e. store directly to NVRAM without the need for UCMS calls), and use that together with the EC-based control. Disallow UCMS+EC, thus avoiding races with the SMM firmware. Switch the models that define HBRV (EC Brightness Value) in the DSDT to the new mode. These are: T40-T43, R50-R52, R50e, R51e, X31-X41. Change the default for all other IBM ThinkPads to UCMS-only. The Lenovo models already default to UCMS-only. Reported-by: Alexey Fisher Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 12 +- drivers/platform/x86/thinkpad_acpi.c | 317 ++++++++++++++++-------- 2 files changed, 227 insertions(+), 102 deletions(-) diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 25ed43d0a21f..3d7650768bb5 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1157,10 +1157,15 @@ display backlight brightness control methods have 16 levels, ranging from 0 to 15. There are two interfaces to the firmware for direct brightness control, -EC and CMOS. To select which one should be used, use the +EC and UCMS (or CMOS). To select which one should be used, use the brightness_mode module parameter: brightness_mode=1 selects EC mode, -brightness_mode=2 selects CMOS mode, brightness_mode=3 selects both EC -and CMOS. The driver tries to auto-detect which interface to use. +brightness_mode=2 selects UCMS mode, brightness_mode=3 selects EC +mode with NVRAM backing (so that brightness changes are remembered +across shutdown/reboot). + +The driver tries to select which interface to use from a table of +defaults for each ThinkPad model. If it makes a wrong choice, please +report this as a bug, so that we can fix it. When display backlight brightness controls are available through the standard ACPI interface, it is best to use it instead of this direct @@ -1498,6 +1503,7 @@ to enable more than one output class, just add their values. (bluetooth, WWAN, UWB...) 0x0008 HKEY event interface, hotkeys 0x0010 Fan control + 0x0020 Backlight brightness There is also a kernel build option to enable more debugging information, which may be necessary to debug driver problems. diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 4eec77032a71..ba3682c5cde0 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -192,6 +192,7 @@ enum { #define TPACPI_DBG_RFKILL 0x0004 #define TPACPI_DBG_HKEY 0x0008 #define TPACPI_DBG_FAN 0x0010 +#define TPACPI_DBG_BRGHT 0x0020 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") @@ -274,7 +275,6 @@ static struct { static struct { u16 hotkey_mask_ff:1; - u16 bright_cmos_ec_unsync:1; } tp_warned; struct thinkpad_id_data { @@ -5526,6 +5526,20 @@ static struct ibm_struct ecdump_driver_data = { #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" +/* + * ThinkPads can read brightness from two places: EC HBRV (0x31), or + * CMOS NVRAM byte 0x5E, bits 0-3. + * + * EC HBRV (0x31) has the following layout + * Bit 7: unknown function + * Bit 6: unknown function + * Bit 5: Z: honour scale changes, NZ: ignore scale changes + * Bit 4: must be set to zero to avoid problems + * Bit 3-0: backlight brightness level + * + * brightness_get_raw returns status data in the HBRV layout + */ + enum { TP_EC_BACKLIGHT = 0x31, @@ -5535,108 +5549,164 @@ enum { TP_EC_BACKLIGHT_MAPSW = 0x20, }; +enum tpacpi_brightness_access_mode { + TPACPI_BRGHT_MODE_AUTO = 0, /* Not implemented yet */ + TPACPI_BRGHT_MODE_EC, /* EC control */ + TPACPI_BRGHT_MODE_UCMS_STEP, /* UCMS step-based control */ + TPACPI_BRGHT_MODE_ECNVRAM, /* EC control w/ NVRAM store */ + TPACPI_BRGHT_MODE_MAX +}; + static struct backlight_device *ibm_backlight_device; -static int brightness_mode; + +static enum tpacpi_brightness_access_mode brightness_mode = + TPACPI_BRGHT_MODE_MAX; + static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ static struct mutex brightness_mutex; -/* - * ThinkPads can read brightness from two places: EC 0x31, or - * CMOS NVRAM byte 0x5E, bits 0-3. - * - * EC 0x31 has the following layout - * Bit 7: unknown function - * Bit 6: unknown function - * Bit 5: Z: honour scale changes, NZ: ignore scale changes - * Bit 4: must be set to zero to avoid problems - * Bit 3-0: backlight brightness level - * - * brightness_get_raw returns status data in the EC 0x31 layout - */ -static int brightness_get_raw(int *status) +/* NVRAM brightness access, + * call with brightness_mutex held! */ +static unsigned int tpacpi_brightness_nvram_get(void) { - u8 lec = 0, lcmos = 0, level = 0; + u8 lnvram; - if (brightness_mode & 1) { - if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec)) - return -EIO; - level = lec & TP_EC_BACKLIGHT_LVLMSK; - }; - if (brightness_mode & 2) { - lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) - & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) - >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; - lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; - level = lcmos; - } + lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) + & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) + >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; + lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07; - if (brightness_mode == 3) { - *status = lec; /* Prefer EC, CMOS is just a backing store */ - lec &= TP_EC_BACKLIGHT_LVLMSK; - if (lec == lcmos) - tp_warned.bright_cmos_ec_unsync = 0; - else { - if (!tp_warned.bright_cmos_ec_unsync) { - printk(TPACPI_ERR - "CMOS NVRAM (%u) and EC (%u) do not " - "agree on display brightness level\n", - (unsigned int) lcmos, - (unsigned int) lec); - tp_warned.bright_cmos_ec_unsync = 1; - } + return lnvram; +} + +static void tpacpi_brightness_checkpoint_nvram(void) +{ + u8 lec = 0; + u8 b_nvram; + + if (brightness_mode != TPACPI_BRGHT_MODE_ECNVRAM) + return; + + vdbg_printk(TPACPI_DBG_BRGHT, + "trying to checkpoint backlight level to NVRAM...\n"); + + if (mutex_lock_killable(&brightness_mutex) < 0) + return; + + if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec))) + goto unlock; + lec &= TP_EC_BACKLIGHT_LVLMSK; + b_nvram = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS); + + if (lec != ((b_nvram & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) + >> TP_NVRAM_POS_LEVEL_BRIGHTNESS)) { + /* NVRAM needs update */ + b_nvram &= ~(TP_NVRAM_MASK_LEVEL_BRIGHTNESS << + TP_NVRAM_POS_LEVEL_BRIGHTNESS); + b_nvram |= lec; + nvram_write_byte(b_nvram, TP_NVRAM_ADDR_BRIGHTNESS); + dbg_printk(TPACPI_DBG_BRGHT, + "updated NVRAM backlight level to %u (0x%02x)\n", + (unsigned int) lec, (unsigned int) b_nvram); + } else + vdbg_printk(TPACPI_DBG_BRGHT, + "NVRAM backlight level already is %u (0x%02x)\n", + (unsigned int) lec, (unsigned int) b_nvram); + +unlock: + mutex_unlock(&brightness_mutex); +} + + +/* call with brightness_mutex held! */ +static int tpacpi_brightness_get_raw(int *status) +{ + u8 lec = 0; + + switch (brightness_mode) { + case TPACPI_BRGHT_MODE_UCMS_STEP: + *status = tpacpi_brightness_nvram_get(); + return 0; + case TPACPI_BRGHT_MODE_EC: + case TPACPI_BRGHT_MODE_ECNVRAM: + if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec))) return -EIO; - } - } else { - *status = level; + *status = lec; + return 0; + default: + return -ENXIO; } +} + +/* call with brightness_mutex held! */ +/* do NOT call with illegal backlight level value */ +static int tpacpi_brightness_set_ec(unsigned int value) +{ + u8 lec = 0; + + if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec))) + return -EIO; + + if (unlikely(!acpi_ec_write(TP_EC_BACKLIGHT, + (lec & TP_EC_BACKLIGHT_CMDMSK) | + (value & TP_EC_BACKLIGHT_LVLMSK)))) + return -EIO; + + return 0; +} + +/* call with brightness_mutex held! */ +static int tpacpi_brightness_set_ucmsstep(unsigned int value) +{ + int cmos_cmd, inc; + unsigned int current_value, i; + + current_value = tpacpi_brightness_nvram_get(); + + if (value == current_value) + return 0; + + cmos_cmd = (value > current_value) ? + TP_CMOS_BRIGHTNESS_UP : + TP_CMOS_BRIGHTNESS_DOWN; + inc = (value > current_value) ? 1 : -1; + + for (i = current_value; i != value; i += inc) + if (issue_thinkpad_cmos_command(cmos_cmd)) + return -EIO; return 0; } /* May return EINTR which can always be mapped to ERESTARTSYS */ -static int brightness_set(int value) +static int brightness_set(unsigned int value) { - int cmos_cmd, inc, i, res; - int current_value; - int command_bits; + int res; if (value > ((tp_features.bright_16levels)? 15 : 7) || value < 0) return -EINVAL; + vdbg_printk(TPACPI_DBG_BRGHT, + "set backlight level to %d\n", value); + res = mutex_lock_killable(&brightness_mutex); if (res < 0) return res; - res = brightness_get_raw(¤t_value); - if (res < 0) - goto errout; - - command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK; - current_value &= TP_EC_BACKLIGHT_LVLMSK; - - cmos_cmd = value > current_value ? - TP_CMOS_BRIGHTNESS_UP : - TP_CMOS_BRIGHTNESS_DOWN; - inc = (value > current_value)? 1 : -1; - - res = 0; - for (i = current_value; i != value; i += inc) { - if ((brightness_mode & 2) && - issue_thinkpad_cmos_command(cmos_cmd)) { - res = -EIO; - goto errout; - } - if ((brightness_mode & 1) && - !acpi_ec_write(TP_EC_BACKLIGHT, - (i + inc) | command_bits)) { - res = -EIO; - goto errout;; - } + switch (brightness_mode) { + case TPACPI_BRGHT_MODE_EC: + case TPACPI_BRGHT_MODE_ECNVRAM: + res = tpacpi_brightness_set_ec(value); + break; + case TPACPI_BRGHT_MODE_UCMS_STEP: + res = tpacpi_brightness_set_ucmsstep(value); + break; + default: + res = -ENXIO; } -errout: mutex_unlock(&brightness_mutex); return res; } @@ -5645,21 +5715,34 @@ errout: static int brightness_update_status(struct backlight_device *bd) { - /* it is the backlight class's job (caller) to handle - * EINTR and other errors properly */ - return brightness_set( + unsigned int level = (bd->props.fb_blank == FB_BLANK_UNBLANK && bd->props.power == FB_BLANK_UNBLANK) ? - bd->props.brightness : 0); + bd->props.brightness : 0; + + dbg_printk(TPACPI_DBG_BRGHT, + "backlight: attempt to set level to %d\n", + level); + + /* it is the backlight class's job (caller) to handle + * EINTR and other errors properly */ + return brightness_set(level); } static int brightness_get(struct backlight_device *bd) { int status, res; - res = brightness_get_raw(&status); + res = mutex_lock_killable(&brightness_mutex); if (res < 0) - return 0; /* FIXME: teach backlight about error handling */ + return 0; + + res = tpacpi_brightness_get_raw(&status); + + mutex_unlock(&brightness_mutex); + + if (res < 0) + return 0; return status & TP_EC_BACKLIGHT_LVLMSK; } @@ -5709,7 +5792,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) } if (!brightness_enable) { - dbg_printk(TPACPI_DBG_INIT, + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, "brightness support disabled by " "module parameter\n"); return 1; @@ -5724,20 +5807,38 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (b == 16) tp_features.bright_16levels = 1; - if (!brightness_mode) { - if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) - brightness_mode = 2; - else - brightness_mode = 3; - - dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", - brightness_mode); - } - - if (brightness_mode > 3) + /* + * Check for module parameter bogosity, note that we + * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be + * able to detect "unspecified" + */ + if (brightness_mode > TPACPI_BRGHT_MODE_MAX) return -EINVAL; - if (brightness_get_raw(&b) < 0) + /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */ + if (brightness_mode == TPACPI_BRGHT_MODE_AUTO || + brightness_mode == TPACPI_BRGHT_MODE_MAX) { + if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) { + /* + * IBM models that define HBRV probably have + * EC-based backlight level control + */ + if (acpi_evalf(ec_handle, NULL, "HBRV", "qd")) + /* T40-T43, R50-R52, R50e, R51e, X31-X41 */ + brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM; + else + /* all other IBM ThinkPads */ + brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; + } else + /* All Lenovo ThinkPads */ + brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP; + + dbg_printk(TPACPI_DBG_BRGHT, + "selected brightness_mode=%d\n", + brightness_mode); + } + + if (tpacpi_brightness_get_raw(&b) < 0) return 1; if (tp_features.bright_16levels) @@ -5751,7 +5852,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm) printk(TPACPI_ERR "Could not register backlight device\n"); return PTR_ERR(ibm_backlight_device); } - vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n"); + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT, + "brightness is supported\n"); ibm_backlight_device->props.max_brightness = (tp_features.bright_16levels)? 15 : 7; @@ -5761,13 +5863,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm) return 0; } +static void brightness_suspend(pm_message_t state) +{ + tpacpi_brightness_checkpoint_nvram(); +} + +static void brightness_shutdown(void) +{ + tpacpi_brightness_checkpoint_nvram(); +} + static void brightness_exit(void) { if (ibm_backlight_device) { - vdbg_printk(TPACPI_DBG_EXIT, + vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_BRGHT, "calling backlight_device_unregister()\n"); backlight_device_unregister(ibm_backlight_device); } + + tpacpi_brightness_checkpoint_nvram(); } static int brightness_read(char *p) @@ -5814,6 +5928,9 @@ static int brightness_write(char *buf) return -EINVAL; } + tpacpi_disclose_usertask("procfs brightness", + "set level to %d\n", level); + /* * Now we know what the final level should be, so we try to set it. * Doing it this way makes the syscall restartable in case of EINTR @@ -5827,6 +5944,8 @@ static struct ibm_struct brightness_driver_data = { .read = brightness_read, .write = brightness_write, .exit = brightness_exit, + .suspend = brightness_suspend, + .shutdown = brightness_shutdown, }; /************************************************************************* @@ -7465,10 +7584,10 @@ module_param_named(fan_control, fan_control_allowed, bool, 0); MODULE_PARM_DESC(fan_control, "Enables setting fan parameters features when true"); -module_param_named(brightness_mode, brightness_mode, int, 0); +module_param_named(brightness_mode, brightness_mode, uint, 0); MODULE_PARM_DESC(brightness_mode, "Selects brightness control strategy: " - "0=auto, 1=EC, 2=CMOS, 3=both"); + "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); module_param(brightness_enable, uint, 0); MODULE_PARM_DESC(brightness_enable, From c07c9a78a95cab0a9bf0b253d0c52e7798af38c5 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Sat, 4 Apr 2009 03:33:45 -0400 Subject: [PATCH 132/140] video: build fix acpi_video_device_write_state() and friends now return ssize_t, while the constify patch assumed it was still int. Signed-off-by: Len Brown --- drivers/acpi/video.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 52779549d367..0e7e689634a7 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -217,7 +217,7 @@ static const struct file_operations acpi_video_bus_POST_info_fops = { }; static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file); -static int acpi_video_bus_write_POST(struct file *file, +static ssize_t acpi_video_bus_write_POST(struct file *file, const char __user *buffer, size_t count, loff_t *data); static const struct file_operations acpi_video_bus_POST_fops = { .owner = THIS_MODULE, @@ -229,7 +229,7 @@ static const struct file_operations acpi_video_bus_POST_fops = { }; static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file); -static int acpi_video_bus_write_DOS(struct file *file, +static ssize_t acpi_video_bus_write_DOS(struct file *file, const char __user *buffer, size_t count, loff_t *data); static const struct file_operations acpi_video_bus_DOS_fops = { .owner = THIS_MODULE, @@ -253,7 +253,7 @@ static const struct file_operations acpi_video_device_info_fops = { static int acpi_video_device_state_open_fs(struct inode *inode, struct file *file); -static int acpi_video_device_write_state(struct file *file, +static ssize_t acpi_video_device_write_state(struct file *file, const char __user *buffer, size_t count, loff_t *data); static const struct file_operations acpi_video_device_state_fops = { .owner = THIS_MODULE, @@ -266,7 +266,7 @@ static const struct file_operations acpi_video_device_state_fops = { static int acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file); -static int acpi_video_device_write_brightness(struct file *file, +static ssize_t acpi_video_device_write_brightness(struct file *file, const char __user *buffer, size_t count, loff_t *data); static struct file_operations acpi_video_device_brightness_fops = { .owner = THIS_MODULE, From a74dd5fdabcd34c93e17e9c7024eeb503c92b048 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 4 Apr 2009 09:33:29 +0100 Subject: [PATCH 133/140] acer-wmi: Blacklist Acer Aspire One The Aspire One's ACPI-WMI interface is a placeholder that does nothing, and the invalid results that we get from it are now causing userspace problems as acer-wmi always returns that the rfkill is enabled (i.e. the radio is off, when it isn't). As it's hardware controlled, acer-wmi isn't needed on the Aspire One either. Thanks to Andy Whitcroft at Canonical for tracking down Ubuntu's userspace issues to this. Signed-off-by: Carlos Corbacho Reported-by: Andy Whitcroft Cc: stable@kernel.org Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index a6a42e8c060b..60fbef283e73 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -225,6 +225,25 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = { .wireless = 2, }; +/* The Aspire One has a dummy ACPI-WMI interface - disable it */ +static struct dmi_system_id __devinitdata acer_blacklist[] = { + { + .ident = "Acer Aspire One (SSD)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"), + }, + }, + { + .ident = "Acer Aspire One (HDD)", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), + }, + }, + {} +}; + static struct dmi_system_id acer_quirks[] = { { .callback = dmi_matched, @@ -1254,6 +1273,12 @@ static int __init acer_wmi_init(void) printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n"); + if (dmi_check_system(acer_blacklist)) { + printk(ACER_INFO "Blacklisted hardware detected - " + "not loading\n"); + return -ENODEV; + } + find_quirks(); /* From 350e32907cf72ef82bbe7d72525fa2d9dcf64682 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Sat, 4 Apr 2009 09:33:34 +0100 Subject: [PATCH 134/140] acer-wmi: Cleanup the failure cleanup handling Cleanup the failure cleanup handling for brightness and email led. [cc: Split out from another patch] Signed-off-by: Andy Whitcroft Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 60fbef283e73..27837e8ae51d 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1136,11 +1136,17 @@ static int __devinit acer_platform_probe(struct platform_device *device) } err = acer_rfkill_init(&device->dev); + if (err) + goto error_rfkill; return err; +error_rfkill: + if (has_cap(ACER_CAP_BRIGHTNESS)) + acer_backlight_exit(); error_brightness: - acer_led_exit(); + if (has_cap(ACER_CAP_MAILLED)) + acer_led_exit(); error_mailled: return err; } From 4f0175dc13a57cb5d2abef44eb4394b0b964bdad Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 4 Apr 2009 09:33:39 +0100 Subject: [PATCH 135/140] acer-wmi: Update copyright notice & documentation Explicitly note in the documentation that the Acer Aspire One is not supported. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- Documentation/laptops/acer-wmi.txt | 10 +++++++--- drivers/platform/x86/acer-wmi.c | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt index 2b3a6b5260bf..5ee2a02b3b40 100644 --- a/Documentation/laptops/acer-wmi.txt +++ b/Documentation/laptops/acer-wmi.txt @@ -1,9 +1,9 @@ Acer Laptop WMI Extras Driver http://code.google.com/p/aceracpi -Version 0.2 -18th August 2008 +Version 0.3 +4th April 2009 -Copyright 2007-2008 Carlos Corbacho +Copyright 2007-2009 Carlos Corbacho acer-wmi is a driver to allow you to control various parts of your Acer laptop hardware under Linux which are exposed via ACPI-WMI. @@ -36,6 +36,10 @@ not possible in kernel space from a 64 bit OS. Supported Hardware ****************** +NOTE: The Acer Aspire One is not supported hardware. It cannot work with +acer-wmi until Acer fix their ACPI-WMI implementation on them, so has been +blacklisted until that happens. + Please see the website for the current list of known working hardare: http://code.google.com/p/aceracpi/wiki/SupportedHardware diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 27837e8ae51d..0f6e43bf4fc2 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1,7 +1,7 @@ /* * Acer WMI Laptop Extras * - * Copyright (C) 2007-2008 Carlos Corbacho + * Copyright (C) 2007-2009 Carlos Corbacho * * Based on acer_acpi: * Copyright (C) 2005-2007 E.M. Smith From 0f66af530116e9f4dd97f328d91718b56a6fc5a4 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 10 Jan 2009 14:19:05 -0500 Subject: [PATCH 136/140] ACPI: battery: asynchronous init The battery driver tends to take quite some time to initialize (100ms-300ms is quite typical). This patch initializes the batter driver asynchronously, so that other things in the kernel can initialize in parallel to this 300 msec. As part of this, the battery driver had to move to the back of the ACPI init order (hence the Makefile change). Without this move, the next ACPI driver would just block on the ACPI/devicee layer semaphores until the battery driver was done anyway, not gaining any boot time. Signed-off-by: Arjan van de Ven Signed-off-by: Len Brown --- drivers/acpi/Makefile | 2 +- drivers/acpi/battery.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index b130ea0d0759..298caf6862b6 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -37,7 +37,6 @@ obj-y += scan.o # Keep EC driver first. Initialization of others depend on it. obj-y += ec.o obj-$(CONFIG_ACPI_AC) += ac.o -obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_FAN) += fan.o obj-$(CONFIG_ACPI_DOCK) += dock.o @@ -57,5 +56,6 @@ obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o +obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbs.o diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 69cbc57c2d1c..0f1c8190c1d3 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI_PROCFS_POWER #include @@ -901,21 +902,27 @@ static struct acpi_driver acpi_battery_driver = { }, }; -static int __init acpi_battery_init(void) +static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) { if (acpi_disabled) - return -ENODEV; + return; #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) - return -ENODEV; + return; #endif if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif - return -ENODEV; + return; } + return; +} + +static int __init acpi_battery_init(void) +{ + async_schedule(acpi_battery_init_async, NULL); return 0; } From 15065531c1c5902775ae3ade24eb37d0e688353b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 30 Mar 2009 12:02:35 +0200 Subject: [PATCH 137/140] toshiba-acpi: remove MAINTAINERS entry "I'm not much opposed to marking this driver orphaned. I haven't used a Toshiba laptop in four years or so, and disagree with the recent additions of bluetooth and wireless control to the driver. --John" Signed-off-by: Johannes Berg Acked-by: John Belmonte Signed-off-by: Len Brown --- MAINTAINERS | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5d460c9d1c2c..c01fdfcb1271 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4286,10 +4286,7 @@ W: http://sourceforge.net/projects/tlan/ S: Maintained TOSHIBA ACPI EXTRAS DRIVER -P: John Belmonte -M: toshiba_acpi@memebeam.org -W: http://memebeam.org/toys/ToshibaAcpiDriver -S: Maintained +S: Orphan TOSHIBA SMM DRIVER P: Jonathan Buzzard From 46ec8598fde74ba59703575c22a6fb0b6b151bb6 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 30 Mar 2009 17:48:13 +0000 Subject: [PATCH 138/140] ACPI: support acpi_device_ops .notify methods This patch adds support for ACPI device driver .notify() methods. If such a method is present, Linux/ACPI installs a handler for device notifications (but not for system notifications such as Bus Check, Device Check, etc). When a device notification occurs, Linux/ACPI passes it on to the driver's .notify() method. In most cases, this removes the need for drivers to install their own handlers for device-specific notifications. For fixed hardware devices like some power and sleep buttons, there's no notification value because there's no control method to execute a Notify opcode. When a fixed hardware device generates an event, we handle it the same as a regular device notification, except we send a ACPI_FIXED_HARDWARE_EVENT value. This is outside the normal 0x0-0xff range used by Notify opcodes. Several drivers install their own handlers for system Bus Check and Device Check notifications so they can support hot-plug. This patch doesn't affect that usage. Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/scan.c | 71 +++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ include/acpi/acpi_drivers.h | 10 ++++++ 3 files changed, 83 insertions(+) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b7308efce458..20c23c049207 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -359,6 +359,61 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } +static void acpi_device_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_device *device = data; + + device->driver->ops.notify(device, event); +} + +static acpi_status acpi_device_notify_fixed(void *data) +{ + struct acpi_device *device = data; + + acpi_device_notify(device->handle, ACPI_FIXED_HARDWARE_EVENT, device); + return AE_OK; +} + +static int acpi_device_install_notify_handler(struct acpi_device *device) +{ + acpi_status status; + char *hid; + + hid = acpi_device_hid(device); + if (!strcmp(hid, ACPI_BUTTON_HID_POWERF)) + status = + acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, + acpi_device_notify_fixed, + device); + else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) + status = + acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, + acpi_device_notify_fixed, + device); + else + status = acpi_install_notify_handler(device->handle, + ACPI_DEVICE_NOTIFY, + acpi_device_notify, + device); + + if (ACPI_FAILURE(status)) + return -EINVAL; + return 0; +} + +static void acpi_device_remove_notify_handler(struct acpi_device *device) +{ + if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_POWERF)) + acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, + acpi_device_notify_fixed); + else if (!strcmp(acpi_device_hid(device), ACPI_BUTTON_HID_SLEEPF)) + acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, + acpi_device_notify_fixed); + else + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_device_notify); +} + static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *); static int acpi_start_single_object(struct acpi_device *); static int acpi_device_probe(struct device * dev) @@ -371,6 +426,20 @@ static int acpi_device_probe(struct device * dev) if (!ret) { if (acpi_dev->bus_ops.acpi_op_start) acpi_start_single_object(acpi_dev); + + if (acpi_drv->ops.notify) { + ret = acpi_device_install_notify_handler(acpi_dev); + if (ret) { + if (acpi_drv->ops.stop) + acpi_drv->ops.stop(acpi_dev, + acpi_dev->removal_type); + if (acpi_drv->ops.remove) + acpi_drv->ops.remove(acpi_dev, + acpi_dev->removal_type); + return ret; + } + } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n", acpi_drv->name, acpi_dev->pnp.bus_id)); @@ -385,6 +454,8 @@ static int acpi_device_remove(struct device * dev) struct acpi_driver *acpi_drv = acpi_dev->driver; if (acpi_drv) { + if (acpi_drv->ops.notify) + acpi_device_remove_notify_handler(acpi_dev); if (acpi_drv->ops.stop) acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type); if (acpi_drv->ops.remove) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 08ec60c8366a..a2228511d4be 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -95,6 +95,7 @@ typedef int (*acpi_op_suspend) (struct acpi_device * device, typedef int (*acpi_op_resume) (struct acpi_device * device); typedef int (*acpi_op_bind) (struct acpi_device * device); typedef int (*acpi_op_unbind) (struct acpi_device * device); +typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event); struct acpi_bus_ops { u32 acpi_op_add:1; @@ -110,6 +111,7 @@ struct acpi_device_ops { acpi_op_resume resume; acpi_op_bind bind; acpi_op_unbind unbind; + acpi_op_notify notify; }; struct acpi_driver { diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h index 241d227de6c0..0352c8f0b05b 100644 --- a/include/acpi/acpi_drivers.h +++ b/include/acpi/acpi_drivers.h @@ -67,6 +67,16 @@ #define ACPI_BAY_HID "LNXIOBAY" #define ACPI_DOCK_HID "LNXDOCK" +/* + * For fixed hardware buttons, we fabricate acpi_devices with HID + * ACPI_BUTTON_HID_POWERF or ACPI_BUTTON_HID_SLEEPF. Fixed hardware + * signals only an event; it doesn't supply a notification value. + * To allow drivers to treat notifications from fixed hardware the + * same as those from real devices, we turn the events into this + * notification value. + */ +#define ACPI_FIXED_HARDWARE_EVENT 0x100 + /* -------------------------------------------------------------------------- PCI -------------------------------------------------------------------------- */ From 373cfc360ec773be2f7615e59a19f3313255db7c Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 30 Mar 2009 17:48:18 +0000 Subject: [PATCH 139/140] ACPI: button: use .notify method instead of installing handler directly This patch adds a .notify() method. The presence of .notify() causes Linux/ACPI to manage event handlers and notify handlers on our behalf, so we don't have to install and remove them ourselves. Note that events from fixed hardware buttons now show up as a special notify event, so to preserve user-space backward compatibility, we convert that back to ACPI_BUTTON_NOTIFY_STATUS. Signed-off-by: Bjorn Helgaas Reviewed-by: Alex Chiang CC: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/button.c | 77 +++++-------------------------------------- 1 file changed, 8 insertions(+), 69 deletions(-) diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index c2f06069dcd4..d73c94b8441d 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -78,6 +78,7 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids); static int acpi_button_add(struct acpi_device *device); static int acpi_button_remove(struct acpi_device *device, int type); static int acpi_button_resume(struct acpi_device *device); +static void acpi_button_notify(struct acpi_device *device, u32 event); static int acpi_button_info_open_fs(struct inode *inode, struct file *file); static int acpi_button_state_open_fs(struct inode *inode, struct file *file); @@ -89,6 +90,7 @@ static struct acpi_driver acpi_button_driver = { .add = acpi_button_add, .resume = acpi_button_resume, .remove = acpi_button_remove, + .notify = acpi_button_notify, }, }; @@ -263,15 +265,18 @@ static int acpi_lid_send_state(struct acpi_button *button) return 0; } -static void acpi_button_notify(acpi_handle handle, u32 event, void *data) +static void acpi_button_notify(struct acpi_device *device, u32 event) { - struct acpi_button *button = data; + struct acpi_button *button = acpi_driver_data(device); struct input_dev *input; if (!button || !button->device) return; switch (event) { + case ACPI_FIXED_HARDWARE_EVENT: + event = ACPI_BUTTON_NOTIFY_STATUS; + /* fall through */ case ACPI_BUTTON_NOTIFY_STATUS: input = button->input; if (button->type == ACPI_BUTTON_TYPE_LID) { @@ -298,46 +303,6 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) return; } -static acpi_status acpi_button_notify_fixed(void *data) -{ - struct acpi_button *button = data; - - if (!button) - return AE_BAD_PARAMETER; - - acpi_button_notify(button->device->handle, ACPI_BUTTON_NOTIFY_STATUS, button); - - return AE_OK; -} - -static int acpi_button_install_notify_handlers(struct acpi_button *button) -{ - acpi_status status; - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWERF: - status = - acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, - acpi_button_notify_fixed, - button); - break; - case ACPI_BUTTON_TYPE_SLEEPF: - status = - acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, - acpi_button_notify_fixed, - button); - break; - default: - status = acpi_install_notify_handler(button->device->handle, - ACPI_DEVICE_NOTIFY, - acpi_button_notify, - button); - break; - } - - return ACPI_FAILURE(status) ? -ENODEV : 0; -} - static int acpi_button_resume(struct acpi_device *device) { struct acpi_button *button; @@ -349,25 +314,6 @@ static int acpi_button_resume(struct acpi_device *device) return 0; } -static void acpi_button_remove_notify_handlers(struct acpi_button *button) -{ - switch (button->type) { - case ACPI_BUTTON_TYPE_POWERF: - acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON, - acpi_button_notify_fixed); - break; - case ACPI_BUTTON_TYPE_SLEEPF: - acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON, - acpi_button_notify_fixed); - break; - default: - acpi_remove_notify_handler(button->device->handle, - ACPI_DEVICE_NOTIFY, - acpi_button_notify); - break; - } -} - static int acpi_button_add(struct acpi_device *device) { int error; @@ -432,10 +378,6 @@ static int acpi_button_add(struct acpi_device *device) if (error) goto err_free_input; - error = acpi_button_install_notify_handlers(button); - if (error) - goto err_remove_fs; - snprintf(button->phys, sizeof(button->phys), "%s/button/input0", acpi_device_hid(device)); @@ -466,7 +408,7 @@ static int acpi_button_add(struct acpi_device *device) error = input_register_device(input); if (error) - goto err_remove_handlers; + goto err_remove_fs; if (button->type == ACPI_BUTTON_TYPE_LID) acpi_lid_send_state(button); @@ -485,8 +427,6 @@ static int acpi_button_add(struct acpi_device *device) return 0; - err_remove_handlers: - acpi_button_remove_notify_handlers(button); err_remove_fs: acpi_button_remove_fs(device); err_free_input: @@ -505,7 +445,6 @@ static int acpi_button_remove(struct acpi_device *device, int type) button = acpi_driver_data(device); - acpi_button_remove_notify_handlers(button); acpi_button_remove_fs(device); input_unregister_device(button->input); kfree(button); From 7ec0a7290797f57b780f792d12f4bcc19c83aa4f Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 30 Mar 2009 17:48:24 +0000 Subject: [PATCH 140/140] ACPI: processor: use .notify method instead of installing handler directly This patch adds a .notify() method. The presence of .notify() causes Linux/ACPI to manage event handlers and notify handlers on our behalf, so we don't have to install and remove them ourselves. Signed-off-by: Bjorn Helgaas CC: Zhang Rui CC: Zhao Yakui CC: Venki Pallipadi CC: Anil S Keshavamurthy Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 8e683f8cc573..45ad3288c5ff 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -82,7 +82,7 @@ static int acpi_processor_add(struct acpi_device *device); static int acpi_processor_start(struct acpi_device *device); static int acpi_processor_remove(struct acpi_device *device, int type); static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); -static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); +static void acpi_processor_notify(struct acpi_device *device, u32 event); static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); static int acpi_processor_handle_eject(struct acpi_processor *pr); @@ -104,6 +104,7 @@ static struct acpi_driver acpi_processor_driver = { .start = acpi_processor_start, .suspend = acpi_processor_suspend, .resume = acpi_processor_resume, + .notify = acpi_processor_notify, }, }; @@ -691,7 +692,6 @@ static DEFINE_PER_CPU(void *, processor_device_array); static int __cpuinit acpi_processor_start(struct acpi_device *device) { int result = 0; - acpi_status status = AE_OK; struct acpi_processor *pr; struct sys_device *sysdev; @@ -728,9 +728,6 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) return -EFAULT; - status = acpi_install_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, - acpi_processor_notify, pr); - /* _PDC call should be done before doing anything else (if reqd.). */ arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); @@ -776,18 +773,14 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) return result; } -static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) +static void acpi_processor_notify(struct acpi_device *device, u32 event) { - struct acpi_processor *pr = data; - struct acpi_device *device = NULL; + struct acpi_processor *pr = acpi_driver_data(device); int saved; if (!pr) return; - if (acpi_bus_get_device(pr->handle, &device)) - return; - switch (event) { case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: saved = pr->performance_platform_limit; @@ -866,7 +859,6 @@ static int acpi_processor_add(struct acpi_device *device) static int acpi_processor_remove(struct acpi_device *device, int type) { - acpi_status status = AE_OK; struct acpi_processor *pr = NULL; @@ -885,9 +877,6 @@ static int acpi_processor_remove(struct acpi_device *device, int type) acpi_processor_power_exit(pr, device); - status = acpi_remove_notify_handler(pr->handle, ACPI_DEVICE_NOTIFY, - acpi_processor_notify); - sysfs_remove_link(&device->dev.kobj, "sysdev"); acpi_processor_remove_fs(device);