diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-10 21:36:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-10 21:36:30 -0400 |
commit | b67db9d5e1294ddcd7f9bea43736a897132f4df7 (patch) | |
tree | d0ac50692253158ad0889a37021e839fefe3cc07 | |
parent | 4c71842375f52dc8a8a6097ffcd625243e153649 (diff) | |
parent | 2091044299e9bc3340d845301b13bd92d6c10993 (diff) |
Merge tag 'pm+acpi-3.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull ACPI and power management fixes from Rafael Wysocki:
"These are a few regression fixes for ACPI device enumeration and
resources management, intel_pstate and cpufreq, a revert of an ACPI
commit removing user space interfaces in /proc that we incorrectly
thought were not used any more, fixes for some long-standing
concurrency issues in the ACPI EC driver, two ACPI battery driver
fixes, stable-candidate fixes for intel_pstate, an ACPI-related fix
for i915 and two new ACPI video blacklist entries for Win8-oriented
BIOSes.
Specifics:
- Missing device ID for ACPI enumeration of PNP devices that we
overlooked during the recent rework of that code from Zhang Rui.
- Fix for a problem introduced during the 3.14 cycle in the ACPI
device resources management code and causing it to reject all
resources of length 0 although some of them are actually valid
which affects serial ports detection on a number of systems. From
Andy Whitcroft.
- intel_pstate fix for a boot problem on some BayTrail-based systems
introduced by a previous fix related to that platform during the
3.13 cycle from Dirk Brandewie.
- Revert of a 3.13 commit that removed the ACPI AC /proc interface
which turns out to be still needed by some old utilities
(kpowersave from kde 3.5.10 in particular) from Lan Tianyu.
- cpufreq build fix for the davinci ARM platform from Prabhakar Lad
(the breakage was introduced during the 3.10 cycle).
- ACPI-related i915 fix preventing firmware on some Thinkpad laptops
from setting backlight levels incorrectly during AC plug/unplug.
From Aaron Lu.
- Fixes for two nasty race conditions in the ACPI embedded controller
driver that may be responsible for a number of past bug reports
related to the EC from Lv Zhang and a fix for two memory leaks in
error code paths in that driver from Colin Ian King.
- Fixes for a couple of corner-case issues in the intel_pstate driver
(all candidates for -stable) from Dirk Brandewie and Vincent Minet.
- Fixes for two corner-case issues in the ACPI battery driver from
Josef Gajdusek and Lan Tianyu.
- Two new ACPI video blacklist entries for Acer TravelMate B113 and
Dell Inspiron 5737 from Edward Lin and Martin Kepplinger"
* tag 'pm+acpi-3.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI / PNP: add soc_button_array device ID to PNP IDs list
cpufreq: Makefile: fix compilation for davinci platform
ACPI / video: Add Acer TravelMate B113 to native backlight blacklist
ACPI / video: Add Dell Inspiron 5737 to the blacklist
ACPI / i915: ignore firmware requests for backlight change
ACPI / battery: fix wrong value of capacity_now reported when fully charged
ACPI / resources: only reject zero length resources based at address zero
ACPI / battery: Retry to get battery information if failed during probing
ACPI / EC: Free saved_ec on error exit path
ACPI / EC: Add detailed fields debugging support of EC_SC(R).
ACPI / EC: Update revision due to recent changes
ACPI / EC: Fix race condition in ec_transaction_completed()
ACPI / EC: Remove duplicated ec_wait_ibf0() waiter
ACPI / EC: Add asynchronous command byte write support
ACPI / EC: Avoid race condition related to advance_transaction()
intel_pstate: Set CPU number before accessing MSRs
intel_pstate: Update documentation of {max,min}_perf_pct sysfs files
intel_pstate: don't touch turbo bit if turbo disabled or unavailable.
intel_pstate: Fix setting VID
Revert "ACPI / AC: Remove AC's proc directory."
-rw-r--r-- | Documentation/cpu-freq/intel-pstate.txt | 7 | ||||
-rw-r--r-- | drivers/acpi/ac.c | 130 | ||||
-rw-r--r-- | drivers/acpi/acpi_pnp.c | 2 | ||||
-rw-r--r-- | drivers/acpi/battery.c | 41 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 164 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 10 | ||||
-rw-r--r-- | drivers/acpi/video.c | 11 | ||||
-rw-r--r-- | drivers/acpi/video_detect.c | 8 | ||||
-rw-r--r-- | drivers/cpufreq/Makefile | 2 | ||||
-rw-r--r-- | drivers/cpufreq/intel_pstate.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_opregion.c | 9 | ||||
-rw-r--r-- | include/acpi/video.h | 2 |
12 files changed, 317 insertions, 104 deletions
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt index e742d21dbd96..a69ffe1d54d5 100644 --- a/Documentation/cpu-freq/intel-pstate.txt +++ b/Documentation/cpu-freq/intel-pstate.txt | |||
@@ -15,10 +15,13 @@ New sysfs files for controlling P state selection have been added to | |||
15 | /sys/devices/system/cpu/intel_pstate/ | 15 | /sys/devices/system/cpu/intel_pstate/ |
16 | 16 | ||
17 | max_perf_pct: limits the maximum P state that will be requested by | 17 | max_perf_pct: limits the maximum P state that will be requested by |
18 | the driver stated as a percentage of the available performance. | 18 | the driver stated as a percentage of the available performance. The |
19 | available (P states) performance may be reduced by the no_turbo | ||
20 | setting described below. | ||
19 | 21 | ||
20 | min_perf_pct: limits the minimum P state that will be requested by | 22 | min_perf_pct: limits the minimum P state that will be requested by |
21 | the driver stated as a percentage of the available performance. | 23 | the driver stated as a percentage of the max (non-turbo) |
24 | performance level. | ||
22 | 25 | ||
23 | no_turbo: limits the driver to selecting P states below the turbo | 26 | no_turbo: limits the driver to selecting P states below the turbo |
24 | frequency range. | 27 | frequency range. |
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c67f6f5ad611..36b0e61f9c09 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -30,6 +30,10 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
34 | #include <linux/proc_fs.h> | ||
35 | #include <linux/seq_file.h> | ||
36 | #endif | ||
33 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
34 | #include <linux/power_supply.h> | 38 | #include <linux/power_supply.h> |
35 | #include <linux/acpi.h> | 39 | #include <linux/acpi.h> |
@@ -52,6 +56,7 @@ MODULE_AUTHOR("Paul Diefenbaugh"); | |||
52 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); | 56 | MODULE_DESCRIPTION("ACPI AC Adapter Driver"); |
53 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
54 | 58 | ||
59 | |||
55 | static int acpi_ac_add(struct acpi_device *device); | 60 | static int acpi_ac_add(struct acpi_device *device); |
56 | static int acpi_ac_remove(struct acpi_device *device); | 61 | static int acpi_ac_remove(struct acpi_device *device); |
57 | static void acpi_ac_notify(struct acpi_device *device, u32 event); | 62 | static void acpi_ac_notify(struct acpi_device *device, u32 event); |
@@ -67,6 +72,13 @@ static int acpi_ac_resume(struct device *dev); | |||
67 | #endif | 72 | #endif |
68 | static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); | 73 | static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); |
69 | 74 | ||
75 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
76 | extern struct proc_dir_entry *acpi_lock_ac_dir(void); | ||
77 | extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); | ||
78 | static int acpi_ac_open_fs(struct inode *inode, struct file *file); | ||
79 | #endif | ||
80 | |||
81 | |||
70 | static int ac_sleep_before_get_state_ms; | 82 | static int ac_sleep_before_get_state_ms; |
71 | 83 | ||
72 | static struct acpi_driver acpi_ac_driver = { | 84 | static struct acpi_driver acpi_ac_driver = { |
@@ -91,6 +103,16 @@ struct acpi_ac { | |||
91 | 103 | ||
92 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) | 104 | #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) |
93 | 105 | ||
106 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
107 | static const struct file_operations acpi_ac_fops = { | ||
108 | .owner = THIS_MODULE, | ||
109 | .open = acpi_ac_open_fs, | ||
110 | .read = seq_read, | ||
111 | .llseek = seq_lseek, | ||
112 | .release = single_release, | ||
113 | }; | ||
114 | #endif | ||
115 | |||
94 | /* -------------------------------------------------------------------------- | 116 | /* -------------------------------------------------------------------------- |
95 | AC Adapter Management | 117 | AC Adapter Management |
96 | -------------------------------------------------------------------------- */ | 118 | -------------------------------------------------------------------------- */ |
@@ -143,6 +165,83 @@ static enum power_supply_property ac_props[] = { | |||
143 | POWER_SUPPLY_PROP_ONLINE, | 165 | POWER_SUPPLY_PROP_ONLINE, |
144 | }; | 166 | }; |
145 | 167 | ||
168 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
169 | /* -------------------------------------------------------------------------- | ||
170 | FS Interface (/proc) | ||
171 | -------------------------------------------------------------------------- */ | ||
172 | |||
173 | static struct proc_dir_entry *acpi_ac_dir; | ||
174 | |||
175 | static int acpi_ac_seq_show(struct seq_file *seq, void *offset) | ||
176 | { | ||
177 | struct acpi_ac *ac = seq->private; | ||
178 | |||
179 | |||
180 | if (!ac) | ||
181 | return 0; | ||
182 | |||
183 | if (acpi_ac_get_state(ac)) { | ||
184 | seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); | ||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | seq_puts(seq, "state: "); | ||
189 | switch (ac->state) { | ||
190 | case ACPI_AC_STATUS_OFFLINE: | ||
191 | seq_puts(seq, "off-line\n"); | ||
192 | break; | ||
193 | case ACPI_AC_STATUS_ONLINE: | ||
194 | seq_puts(seq, "on-line\n"); | ||
195 | break; | ||
196 | default: | ||
197 | seq_puts(seq, "unknown\n"); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int acpi_ac_open_fs(struct inode *inode, struct file *file) | ||
205 | { | ||
206 | return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); | ||
207 | } | ||
208 | |||
209 | static int acpi_ac_add_fs(struct acpi_ac *ac) | ||
210 | { | ||
211 | struct proc_dir_entry *entry = NULL; | ||
212 | |||
213 | printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," | ||
214 | " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); | ||
215 | if (!acpi_device_dir(ac->device)) { | ||
216 | acpi_device_dir(ac->device) = | ||
217 | proc_mkdir(acpi_device_bid(ac->device), acpi_ac_dir); | ||
218 | if (!acpi_device_dir(ac->device)) | ||
219 | return -ENODEV; | ||
220 | } | ||
221 | |||
222 | /* 'state' [R] */ | ||
223 | entry = proc_create_data(ACPI_AC_FILE_STATE, | ||
224 | S_IRUGO, acpi_device_dir(ac->device), | ||
225 | &acpi_ac_fops, ac); | ||
226 | if (!entry) | ||
227 | return -ENODEV; | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int acpi_ac_remove_fs(struct acpi_ac *ac) | ||
232 | { | ||
233 | |||
234 | if (acpi_device_dir(ac->device)) { | ||
235 | remove_proc_entry(ACPI_AC_FILE_STATE, | ||
236 | acpi_device_dir(ac->device)); | ||
237 | remove_proc_entry(acpi_device_bid(ac->device), acpi_ac_dir); | ||
238 | acpi_device_dir(ac->device) = NULL; | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | #endif | ||
244 | |||
146 | /* -------------------------------------------------------------------------- | 245 | /* -------------------------------------------------------------------------- |
147 | Driver Model | 246 | Driver Model |
148 | -------------------------------------------------------------------------- */ | 247 | -------------------------------------------------------------------------- */ |
@@ -243,6 +342,11 @@ static int acpi_ac_add(struct acpi_device *device) | |||
243 | goto end; | 342 | goto end; |
244 | 343 | ||
245 | ac->charger.name = acpi_device_bid(device); | 344 | ac->charger.name = acpi_device_bid(device); |
345 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
346 | result = acpi_ac_add_fs(ac); | ||
347 | if (result) | ||
348 | goto end; | ||
349 | #endif | ||
246 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; | 350 | ac->charger.type = POWER_SUPPLY_TYPE_MAINS; |
247 | ac->charger.properties = ac_props; | 351 | ac->charger.properties = ac_props; |
248 | ac->charger.num_properties = ARRAY_SIZE(ac_props); | 352 | ac->charger.num_properties = ARRAY_SIZE(ac_props); |
@@ -258,8 +362,12 @@ static int acpi_ac_add(struct acpi_device *device) | |||
258 | ac->battery_nb.notifier_call = acpi_ac_battery_notify; | 362 | ac->battery_nb.notifier_call = acpi_ac_battery_notify; |
259 | register_acpi_notifier(&ac->battery_nb); | 363 | register_acpi_notifier(&ac->battery_nb); |
260 | end: | 364 | end: |
261 | if (result) | 365 | if (result) { |
366 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
367 | acpi_ac_remove_fs(ac); | ||
368 | #endif | ||
262 | kfree(ac); | 369 | kfree(ac); |
370 | } | ||
263 | 371 | ||
264 | dmi_check_system(ac_dmi_table); | 372 | dmi_check_system(ac_dmi_table); |
265 | return result; | 373 | return result; |
@@ -303,6 +411,10 @@ static int acpi_ac_remove(struct acpi_device *device) | |||
303 | power_supply_unregister(&ac->charger); | 411 | power_supply_unregister(&ac->charger); |
304 | unregister_acpi_notifier(&ac->battery_nb); | 412 | unregister_acpi_notifier(&ac->battery_nb); |
305 | 413 | ||
414 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
415 | acpi_ac_remove_fs(ac); | ||
416 | #endif | ||
417 | |||
306 | kfree(ac); | 418 | kfree(ac); |
307 | 419 | ||
308 | return 0; | 420 | return 0; |
@@ -315,9 +427,20 @@ static int __init acpi_ac_init(void) | |||
315 | if (acpi_disabled) | 427 | if (acpi_disabled) |
316 | return -ENODEV; | 428 | return -ENODEV; |
317 | 429 | ||
430 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
431 | acpi_ac_dir = acpi_lock_ac_dir(); | ||
432 | if (!acpi_ac_dir) | ||
433 | return -ENODEV; | ||
434 | #endif | ||
435 | |||
436 | |||
318 | result = acpi_bus_register_driver(&acpi_ac_driver); | 437 | result = acpi_bus_register_driver(&acpi_ac_driver); |
319 | if (result < 0) | 438 | if (result < 0) { |
439 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
440 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
441 | #endif | ||
320 | return -ENODEV; | 442 | return -ENODEV; |
443 | } | ||
321 | 444 | ||
322 | return 0; | 445 | return 0; |
323 | } | 446 | } |
@@ -325,6 +448,9 @@ static int __init acpi_ac_init(void) | |||
325 | static void __exit acpi_ac_exit(void) | 448 | static void __exit acpi_ac_exit(void) |
326 | { | 449 | { |
327 | acpi_bus_unregister_driver(&acpi_ac_driver); | 450 | acpi_bus_unregister_driver(&acpi_ac_driver); |
451 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
452 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
453 | #endif | ||
328 | } | 454 | } |
329 | module_init(acpi_ac_init); | 455 | module_init(acpi_ac_init); |
330 | module_exit(acpi_ac_exit); | 456 | module_exit(acpi_ac_exit); |
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 6703c1fd993a..4ddb0dca56f6 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | 15 | ||
16 | static const struct acpi_device_id acpi_pnp_device_ids[] = { | 16 | static const struct acpi_device_id acpi_pnp_device_ids[] = { |
17 | /* soc_button_array */ | ||
18 | {"PNP0C40"}, | ||
17 | /* pata_isapnp */ | 19 | /* pata_isapnp */ |
18 | {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ | 20 | {"PNP0600"}, /* Generic ESDI/IDE/ATA compatible hard disk controller */ |
19 | /* floppy */ | 21 | /* floppy */ |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 0d7116f34b95..130f513e08c9 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/suspend.h> | 37 | #include <linux/suspend.h> |
38 | #include <linux/delay.h> | ||
38 | #include <asm/unaligned.h> | 39 | #include <asm/unaligned.h> |
39 | 40 | ||
40 | #ifdef CONFIG_ACPI_PROCFS_POWER | 41 | #ifdef CONFIG_ACPI_PROCFS_POWER |
@@ -534,6 +535,20 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
534 | " invalid.\n"); | 535 | " invalid.\n"); |
535 | } | 536 | } |
536 | 537 | ||
538 | /* | ||
539 | * When fully charged, some batteries wrongly report | ||
540 | * capacity_now = design_capacity instead of = full_charge_capacity | ||
541 | */ | ||
542 | if (battery->capacity_now > battery->full_charge_capacity | ||
543 | && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) { | ||
544 | battery->capacity_now = battery->full_charge_capacity; | ||
545 | if (battery->capacity_now != battery->design_capacity) | ||
546 | printk_once(KERN_WARNING FW_BUG | ||
547 | "battery: reported current charge level (%d) " | ||
548 | "is higher than reported maximum charge level (%d).\n", | ||
549 | battery->capacity_now, battery->full_charge_capacity); | ||
550 | } | ||
551 | |||
537 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | 552 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) |
538 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) | 553 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) |
539 | battery->capacity_now = (battery->capacity_now * | 554 | battery->capacity_now = (battery->capacity_now * |
@@ -1151,6 +1166,28 @@ static struct dmi_system_id bat_dmi_table[] = { | |||
1151 | {}, | 1166 | {}, |
1152 | }; | 1167 | }; |
1153 | 1168 | ||
1169 | /* | ||
1170 | * Some machines'(E,G Lenovo Z480) ECs are not stable | ||
1171 | * during boot up and this causes battery driver fails to be | ||
1172 | * probed due to failure of getting battery information | ||
1173 | * from EC sometimes. After several retries, the operation | ||
1174 | * may work. So add retry code here and 20ms sleep between | ||
1175 | * every retries. | ||
1176 | */ | ||
1177 | static int acpi_battery_update_retry(struct acpi_battery *battery) | ||
1178 | { | ||
1179 | int retry, ret; | ||
1180 | |||
1181 | for (retry = 5; retry; retry--) { | ||
1182 | ret = acpi_battery_update(battery, false); | ||
1183 | if (!ret) | ||
1184 | break; | ||
1185 | |||
1186 | msleep(20); | ||
1187 | } | ||
1188 | return ret; | ||
1189 | } | ||
1190 | |||
1154 | static int acpi_battery_add(struct acpi_device *device) | 1191 | static int acpi_battery_add(struct acpi_device *device) |
1155 | { | 1192 | { |
1156 | int result = 0; | 1193 | int result = 0; |
@@ -1169,9 +1206,11 @@ static int acpi_battery_add(struct acpi_device *device) | |||
1169 | mutex_init(&battery->sysfs_lock); | 1206 | mutex_init(&battery->sysfs_lock); |
1170 | if (acpi_has_method(battery->device->handle, "_BIX")) | 1207 | if (acpi_has_method(battery->device->handle, "_BIX")) |
1171 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); | 1208 | set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); |
1172 | result = acpi_battery_update(battery, false); | 1209 | |
1210 | result = acpi_battery_update_retry(battery); | ||
1173 | if (result) | 1211 | if (result) |
1174 | goto fail; | 1212 | goto fail; |
1213 | |||
1175 | #ifdef CONFIG_ACPI_PROCFS_POWER | 1214 | #ifdef CONFIG_ACPI_PROCFS_POWER |
1176 | result = acpi_battery_add_fs(device); | 1215 | result = acpi_battery_add_fs(device); |
1177 | #endif | 1216 | #endif |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index ad11ba4a412d..a66ab658abbc 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -1,11 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * ec.c - ACPI Embedded Controller Driver (v2.1) | 2 | * ec.c - ACPI Embedded Controller Driver (v2.2) |
3 | * | 3 | * |
4 | * Copyright (C) 2006-2008 Alexey Starikovskiy <astarikovskiy@suse.de> | 4 | * Copyright (C) 2001-2014 Intel Corporation |
5 | * Copyright (C) 2006 Denis Sadykov <denis.m.sadykov@intel.com> | 5 | * Author: 2014 Lv Zheng <lv.zheng@intel.com> |
6 | * Copyright (C) 2004 Luming Yu <luming.yu@intel.com> | 6 | * 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> |
7 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 7 | * 2006 Denis Sadykov <denis.m.sadykov@intel.com> |
8 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 8 | * 2004 Luming Yu <luming.yu@intel.com> |
9 | * 2001, 2002 Andy Grover <andrew.grover@intel.com> | ||
10 | * 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | ||
11 | * Copyright (C) 2008 Alexey Starikovskiy <astarikovskiy@suse.de> | ||
9 | * | 12 | * |
10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 13 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
11 | * | 14 | * |
@@ -52,6 +55,7 @@ | |||
52 | /* EC status register */ | 55 | /* EC status register */ |
53 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 56 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
54 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 57 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
58 | #define ACPI_EC_FLAG_CMD 0x08 /* Input buffer contains a command */ | ||
55 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ | 59 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ |
56 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ | 60 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ |
57 | 61 | ||
@@ -78,6 +82,9 @@ enum { | |||
78 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ | 82 | EC_FLAGS_BLOCKED, /* Transactions are blocked */ |
79 | }; | 83 | }; |
80 | 84 | ||
85 | #define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ | ||
86 | #define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */ | ||
87 | |||
81 | /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ | 88 | /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ |
82 | static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; | 89 | static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; |
83 | module_param(ec_delay, uint, 0644); | 90 | module_param(ec_delay, uint, 0644); |
@@ -109,7 +116,7 @@ struct transaction { | |||
109 | u8 ri; | 116 | u8 ri; |
110 | u8 wlen; | 117 | u8 wlen; |
111 | u8 rlen; | 118 | u8 rlen; |
112 | bool done; | 119 | u8 flags; |
113 | }; | 120 | }; |
114 | 121 | ||
115 | struct acpi_ec *boot_ec, *first_ec; | 122 | struct acpi_ec *boot_ec, *first_ec; |
@@ -127,83 +134,104 @@ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ | |||
127 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) | 134 | static inline u8 acpi_ec_read_status(struct acpi_ec *ec) |
128 | { | 135 | { |
129 | u8 x = inb(ec->command_addr); | 136 | u8 x = inb(ec->command_addr); |
130 | pr_debug("---> status = 0x%2.2x\n", x); | 137 | pr_debug("EC_SC(R) = 0x%2.2x " |
138 | "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d\n", | ||
139 | x, | ||
140 | !!(x & ACPI_EC_FLAG_SCI), | ||
141 | !!(x & ACPI_EC_FLAG_BURST), | ||
142 | !!(x & ACPI_EC_FLAG_CMD), | ||
143 | !!(x & ACPI_EC_FLAG_IBF), | ||
144 | !!(x & ACPI_EC_FLAG_OBF)); | ||
131 | return x; | 145 | return x; |
132 | } | 146 | } |
133 | 147 | ||
134 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) | 148 | static inline u8 acpi_ec_read_data(struct acpi_ec *ec) |
135 | { | 149 | { |
136 | u8 x = inb(ec->data_addr); | 150 | u8 x = inb(ec->data_addr); |
137 | pr_debug("---> data = 0x%2.2x\n", x); | 151 | pr_debug("EC_DATA(R) = 0x%2.2x\n", x); |
138 | return x; | 152 | return x; |
139 | } | 153 | } |
140 | 154 | ||
141 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) | 155 | static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) |
142 | { | 156 | { |
143 | pr_debug("<--- command = 0x%2.2x\n", command); | 157 | pr_debug("EC_SC(W) = 0x%2.2x\n", command); |
144 | outb(command, ec->command_addr); | 158 | outb(command, ec->command_addr); |
145 | } | 159 | } |
146 | 160 | ||
147 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) | 161 | static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) |
148 | { | 162 | { |
149 | pr_debug("<--- data = 0x%2.2x\n", data); | 163 | pr_debug("EC_DATA(W) = 0x%2.2x\n", data); |
150 | outb(data, ec->data_addr); | 164 | outb(data, ec->data_addr); |
151 | } | 165 | } |
152 | 166 | ||
153 | static int ec_transaction_done(struct acpi_ec *ec) | 167 | static int ec_transaction_completed(struct acpi_ec *ec) |
154 | { | 168 | { |
155 | unsigned long flags; | 169 | unsigned long flags; |
156 | int ret = 0; | 170 | int ret = 0; |
157 | spin_lock_irqsave(&ec->lock, flags); | 171 | spin_lock_irqsave(&ec->lock, flags); |
158 | if (!ec->curr || ec->curr->done) | 172 | if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE)) |
159 | ret = 1; | 173 | ret = 1; |
160 | spin_unlock_irqrestore(&ec->lock, flags); | 174 | spin_unlock_irqrestore(&ec->lock, flags); |
161 | return ret; | 175 | return ret; |
162 | } | 176 | } |
163 | 177 | ||
164 | static void start_transaction(struct acpi_ec *ec) | 178 | static bool advance_transaction(struct acpi_ec *ec) |
165 | { | 179 | { |
166 | ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; | ||
167 | ec->curr->done = false; | ||
168 | acpi_ec_write_cmd(ec, ec->curr->command); | ||
169 | } | ||
170 | |||
171 | static void advance_transaction(struct acpi_ec *ec, u8 status) | ||
172 | { | ||
173 | unsigned long flags; | ||
174 | struct transaction *t; | 180 | struct transaction *t; |
181 | u8 status; | ||
182 | bool wakeup = false; | ||
175 | 183 | ||
176 | spin_lock_irqsave(&ec->lock, flags); | 184 | pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK"); |
185 | status = acpi_ec_read_status(ec); | ||
177 | t = ec->curr; | 186 | t = ec->curr; |
178 | if (!t) | 187 | if (!t) |
179 | goto unlock; | 188 | goto err; |
180 | if (t->wlen > t->wi) { | 189 | if (t->flags & ACPI_EC_COMMAND_POLL) { |
181 | if ((status & ACPI_EC_FLAG_IBF) == 0) | 190 | if (t->wlen > t->wi) { |
182 | acpi_ec_write_data(ec, | 191 | if ((status & ACPI_EC_FLAG_IBF) == 0) |
183 | t->wdata[t->wi++]); | 192 | acpi_ec_write_data(ec, t->wdata[t->wi++]); |
184 | else | 193 | else |
185 | goto err; | 194 | goto err; |
186 | } else if (t->rlen > t->ri) { | 195 | } else if (t->rlen > t->ri) { |
187 | if ((status & ACPI_EC_FLAG_OBF) == 1) { | 196 | if ((status & ACPI_EC_FLAG_OBF) == 1) { |
188 | t->rdata[t->ri++] = acpi_ec_read_data(ec); | 197 | t->rdata[t->ri++] = acpi_ec_read_data(ec); |
189 | if (t->rlen == t->ri) | 198 | if (t->rlen == t->ri) { |
190 | t->done = true; | 199 | t->flags |= ACPI_EC_COMMAND_COMPLETE; |
200 | wakeup = true; | ||
201 | } | ||
202 | } else | ||
203 | goto err; | ||
204 | } else if (t->wlen == t->wi && | ||
205 | (status & ACPI_EC_FLAG_IBF) == 0) { | ||
206 | t->flags |= ACPI_EC_COMMAND_COMPLETE; | ||
207 | wakeup = true; | ||
208 | } | ||
209 | return wakeup; | ||
210 | } else { | ||
211 | if ((status & ACPI_EC_FLAG_IBF) == 0) { | ||
212 | acpi_ec_write_cmd(ec, t->command); | ||
213 | t->flags |= ACPI_EC_COMMAND_POLL; | ||
191 | } else | 214 | } else |
192 | goto err; | 215 | goto err; |
193 | } else if (t->wlen == t->wi && | 216 | return wakeup; |
194 | (status & ACPI_EC_FLAG_IBF) == 0) | 217 | } |
195 | t->done = true; | ||
196 | goto unlock; | ||
197 | err: | 218 | err: |
198 | /* | 219 | /* |
199 | * If SCI bit is set, then don't think it's a false IRQ | 220 | * If SCI bit is set, then don't think it's a false IRQ |
200 | * otherwise will take a not handled IRQ as a false one. | 221 | * otherwise will take a not handled IRQ as a false one. |
201 | */ | 222 | */ |
202 | if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI)) | 223 | if (!(status & ACPI_EC_FLAG_SCI)) { |
203 | ++t->irq_count; | 224 | if (in_interrupt() && t) |
225 | ++t->irq_count; | ||
226 | } | ||
227 | return wakeup; | ||
228 | } | ||
204 | 229 | ||
205 | unlock: | 230 | static void start_transaction(struct acpi_ec *ec) |
206 | spin_unlock_irqrestore(&ec->lock, flags); | 231 | { |
232 | ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; | ||
233 | ec->curr->flags = 0; | ||
234 | (void)advance_transaction(ec); | ||
207 | } | 235 | } |
208 | 236 | ||
209 | static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); | 237 | static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); |
@@ -228,15 +256,17 @@ static int ec_poll(struct acpi_ec *ec) | |||
228 | /* don't sleep with disabled interrupts */ | 256 | /* don't sleep with disabled interrupts */ |
229 | if (EC_FLAGS_MSI || irqs_disabled()) { | 257 | if (EC_FLAGS_MSI || irqs_disabled()) { |
230 | udelay(ACPI_EC_MSI_UDELAY); | 258 | udelay(ACPI_EC_MSI_UDELAY); |
231 | if (ec_transaction_done(ec)) | 259 | if (ec_transaction_completed(ec)) |
232 | return 0; | 260 | return 0; |
233 | } else { | 261 | } else { |
234 | if (wait_event_timeout(ec->wait, | 262 | if (wait_event_timeout(ec->wait, |
235 | ec_transaction_done(ec), | 263 | ec_transaction_completed(ec), |
236 | msecs_to_jiffies(1))) | 264 | msecs_to_jiffies(1))) |
237 | return 0; | 265 | return 0; |
238 | } | 266 | } |
239 | advance_transaction(ec, acpi_ec_read_status(ec)); | 267 | spin_lock_irqsave(&ec->lock, flags); |
268 | (void)advance_transaction(ec); | ||
269 | spin_unlock_irqrestore(&ec->lock, flags); | ||
240 | } while (time_before(jiffies, delay)); | 270 | } while (time_before(jiffies, delay)); |
241 | pr_debug("controller reset, restart transaction\n"); | 271 | pr_debug("controller reset, restart transaction\n"); |
242 | spin_lock_irqsave(&ec->lock, flags); | 272 | spin_lock_irqsave(&ec->lock, flags); |
@@ -268,23 +298,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
268 | return ret; | 298 | return ret; |
269 | } | 299 | } |
270 | 300 | ||
271 | static int ec_check_ibf0(struct acpi_ec *ec) | ||
272 | { | ||
273 | u8 status = acpi_ec_read_status(ec); | ||
274 | return (status & ACPI_EC_FLAG_IBF) == 0; | ||
275 | } | ||
276 | |||
277 | static int ec_wait_ibf0(struct acpi_ec *ec) | ||
278 | { | ||
279 | unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); | ||
280 | /* interrupt wait manually if GPE mode is not active */ | ||
281 | while (time_before(jiffies, delay)) | ||
282 | if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), | ||
283 | msecs_to_jiffies(1))) | ||
284 | return 0; | ||
285 | return -ETIME; | ||
286 | } | ||
287 | |||
288 | static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | 301 | static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) |
289 | { | 302 | { |
290 | int status; | 303 | int status; |
@@ -305,12 +318,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
305 | goto unlock; | 318 | goto unlock; |
306 | } | 319 | } |
307 | } | 320 | } |
308 | if (ec_wait_ibf0(ec)) { | ||
309 | pr_err("input buffer is not empty, " | ||
310 | "aborting transaction\n"); | ||
311 | status = -ETIME; | ||
312 | goto end; | ||
313 | } | ||
314 | pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n", | 321 | pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n", |
315 | t->command, t->wdata ? t->wdata[0] : 0); | 322 | t->command, t->wdata ? t->wdata[0] : 0); |
316 | /* disable GPE during transaction if storm is detected */ | 323 | /* disable GPE during transaction if storm is detected */ |
@@ -334,7 +341,6 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
334 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | 341 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); |
335 | } | 342 | } |
336 | pr_debug("transaction end\n"); | 343 | pr_debug("transaction end\n"); |
337 | end: | ||
338 | if (ec->global_lock) | 344 | if (ec->global_lock) |
339 | acpi_release_global_lock(glk); | 345 | acpi_release_global_lock(glk); |
340 | unlock: | 346 | unlock: |
@@ -634,17 +640,14 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) | |||
634 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, | 640 | static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, |
635 | u32 gpe_number, void *data) | 641 | u32 gpe_number, void *data) |
636 | { | 642 | { |
643 | unsigned long flags; | ||
637 | struct acpi_ec *ec = data; | 644 | struct acpi_ec *ec = data; |
638 | u8 status = acpi_ec_read_status(ec); | ||
639 | 645 | ||
640 | pr_debug("~~~> interrupt, status:0x%02x\n", status); | 646 | spin_lock_irqsave(&ec->lock, flags); |
641 | 647 | if (advance_transaction(ec)) | |
642 | advance_transaction(ec, status); | ||
643 | if (ec_transaction_done(ec) && | ||
644 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
645 | wake_up(&ec->wait); | 648 | wake_up(&ec->wait); |
646 | ec_check_sci(ec, acpi_ec_read_status(ec)); | 649 | spin_unlock_irqrestore(&ec->lock, flags); |
647 | } | 650 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
648 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; | 651 | return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE; |
649 | } | 652 | } |
650 | 653 | ||
@@ -1066,8 +1069,10 @@ int __init acpi_ec_ecdt_probe(void) | |||
1066 | /* fall through */ | 1069 | /* fall through */ |
1067 | } | 1070 | } |
1068 | 1071 | ||
1069 | if (EC_FLAGS_SKIP_DSDT_SCAN) | 1072 | if (EC_FLAGS_SKIP_DSDT_SCAN) { |
1073 | kfree(saved_ec); | ||
1070 | return -ENODEV; | 1074 | return -ENODEV; |
1075 | } | ||
1071 | 1076 | ||
1072 | /* This workaround is needed only on some broken machines, | 1077 | /* This workaround is needed only on some broken machines, |
1073 | * which require early EC, but fail to provide ECDT */ | 1078 | * which require early EC, but fail to provide ECDT */ |
@@ -1105,6 +1110,7 @@ install: | |||
1105 | } | 1110 | } |
1106 | error: | 1111 | error: |
1107 | kfree(boot_ec); | 1112 | kfree(boot_ec); |
1113 | kfree(saved_ec); | ||
1108 | boot_ec = NULL; | 1114 | boot_ec = NULL; |
1109 | return -ENODEV; | 1115 | return -ENODEV; |
1110 | } | 1116 | } |
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 0bdacc5e26a3..2ba8f02ced36 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c | |||
@@ -77,7 +77,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
77 | switch (ares->type) { | 77 | switch (ares->type) { |
78 | case ACPI_RESOURCE_TYPE_MEMORY24: | 78 | case ACPI_RESOURCE_TYPE_MEMORY24: |
79 | memory24 = &ares->data.memory24; | 79 | memory24 = &ares->data.memory24; |
80 | if (!memory24->address_length) | 80 | if (!memory24->minimum && !memory24->address_length) |
81 | return false; | 81 | return false; |
82 | acpi_dev_get_memresource(res, memory24->minimum, | 82 | acpi_dev_get_memresource(res, memory24->minimum, |
83 | memory24->address_length, | 83 | memory24->address_length, |
@@ -85,7 +85,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
85 | break; | 85 | break; |
86 | case ACPI_RESOURCE_TYPE_MEMORY32: | 86 | case ACPI_RESOURCE_TYPE_MEMORY32: |
87 | memory32 = &ares->data.memory32; | 87 | memory32 = &ares->data.memory32; |
88 | if (!memory32->address_length) | 88 | if (!memory32->minimum && !memory32->address_length) |
89 | return false; | 89 | return false; |
90 | acpi_dev_get_memresource(res, memory32->minimum, | 90 | acpi_dev_get_memresource(res, memory32->minimum, |
91 | memory32->address_length, | 91 | memory32->address_length, |
@@ -93,7 +93,7 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
93 | break; | 93 | break; |
94 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 94 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
95 | fixed_memory32 = &ares->data.fixed_memory32; | 95 | fixed_memory32 = &ares->data.fixed_memory32; |
96 | if (!fixed_memory32->address_length) | 96 | if (!fixed_memory32->address && !fixed_memory32->address_length) |
97 | return false; | 97 | return false; |
98 | acpi_dev_get_memresource(res, fixed_memory32->address, | 98 | acpi_dev_get_memresource(res, fixed_memory32->address, |
99 | fixed_memory32->address_length, | 99 | fixed_memory32->address_length, |
@@ -150,7 +150,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | |||
150 | switch (ares->type) { | 150 | switch (ares->type) { |
151 | case ACPI_RESOURCE_TYPE_IO: | 151 | case ACPI_RESOURCE_TYPE_IO: |
152 | io = &ares->data.io; | 152 | io = &ares->data.io; |
153 | if (!io->address_length) | 153 | if (!io->minimum && !io->address_length) |
154 | return false; | 154 | return false; |
155 | acpi_dev_get_ioresource(res, io->minimum, | 155 | acpi_dev_get_ioresource(res, io->minimum, |
156 | io->address_length, | 156 | io->address_length, |
@@ -158,7 +158,7 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | |||
158 | break; | 158 | break; |
159 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 159 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
160 | fixed_io = &ares->data.fixed_io; | 160 | fixed_io = &ares->data.fixed_io; |
161 | if (!fixed_io->address_length) | 161 | if (!fixed_io->address && !fixed_io->address_length) |
162 | return false; | 162 | return false; |
163 | acpi_dev_get_ioresource(res, fixed_io->address, | 163 | acpi_dev_get_ioresource(res, fixed_io->address, |
164 | fixed_io->address_length, | 164 | fixed_io->address_length, |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index fb9ffe9adc64..071c1dfb93f3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -241,13 +241,14 @@ static bool acpi_video_use_native_backlight(void) | |||
241 | return use_native_backlight_dmi; | 241 | return use_native_backlight_dmi; |
242 | } | 242 | } |
243 | 243 | ||
244 | static bool acpi_video_verify_backlight_support(void) | 244 | bool acpi_video_verify_backlight_support(void) |
245 | { | 245 | { |
246 | if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && | 246 | if (acpi_osi_is_win8() && acpi_video_use_native_backlight() && |
247 | backlight_device_registered(BACKLIGHT_RAW)) | 247 | backlight_device_registered(BACKLIGHT_RAW)) |
248 | return false; | 248 | return false; |
249 | return acpi_video_backlight_support(); | 249 | return acpi_video_backlight_support(); |
250 | } | 250 | } |
251 | EXPORT_SYMBOL_GPL(acpi_video_verify_backlight_support); | ||
251 | 252 | ||
252 | /* backlight device sysfs support */ | 253 | /* backlight device sysfs support */ |
253 | static int acpi_video_get_brightness(struct backlight_device *bd) | 254 | static int acpi_video_get_brightness(struct backlight_device *bd) |
@@ -563,6 +564,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
563 | }, | 564 | }, |
564 | }, | 565 | }, |
565 | { | 566 | { |
567 | .callback = video_set_use_native_backlight, | ||
568 | .ident = "Acer TravelMate B113", | ||
569 | .matches = { | ||
570 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
571 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate B113"), | ||
572 | }, | ||
573 | }, | ||
574 | { | ||
566 | .callback = video_set_use_native_backlight, | 575 | .callback = video_set_use_native_backlight, |
567 | .ident = "HP ProBook 4340s", | 576 | .ident = "HP ProBook 4340s", |
568 | .matches = { | 577 | .matches = { |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 33e3db548a29..c42feb2bacd0 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -166,6 +166,14 @@ static struct dmi_system_id video_detect_dmi_table[] = { | |||
166 | DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), | 166 | DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"), |
167 | }, | 167 | }, |
168 | }, | 168 | }, |
169 | { | ||
170 | .callback = video_detect_force_vendor, | ||
171 | .ident = "Dell Inspiron 5737", | ||
172 | .matches = { | ||
173 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
174 | DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5737"), | ||
175 | }, | ||
176 | }, | ||
169 | { }, | 177 | { }, |
170 | }; | 178 | }; |
171 | 179 | ||
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 738c8b7b17dc..db6d9a2fea4d 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
@@ -49,7 +49,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o | |||
49 | # LITTLE drivers, so that it is probed last. | 49 | # LITTLE drivers, so that it is probed last. |
50 | obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o | 50 | obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o |
51 | 51 | ||
52 | obj-$(CONFIG_ARCH_DAVINCI_DA850) += davinci-cpufreq.o | 52 | obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o |
53 | obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o | 53 | obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o |
54 | obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o | 54 | obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o |
55 | obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o | 55 | obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 924bb2d42b1c..86631cb6f7de 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -128,6 +128,7 @@ static struct pstate_funcs pstate_funcs; | |||
128 | 128 | ||
129 | struct perf_limits { | 129 | struct perf_limits { |
130 | int no_turbo; | 130 | int no_turbo; |
131 | int turbo_disabled; | ||
131 | int max_perf_pct; | 132 | int max_perf_pct; |
132 | int min_perf_pct; | 133 | int min_perf_pct; |
133 | int32_t max_perf; | 134 | int32_t max_perf; |
@@ -287,7 +288,10 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, | |||
287 | if (ret != 1) | 288 | if (ret != 1) |
288 | return -EINVAL; | 289 | return -EINVAL; |
289 | limits.no_turbo = clamp_t(int, input, 0 , 1); | 290 | limits.no_turbo = clamp_t(int, input, 0 , 1); |
290 | 291 | if (limits.turbo_disabled) { | |
292 | pr_warn("Turbo disabled by BIOS or unavailable on processor\n"); | ||
293 | limits.no_turbo = limits.turbo_disabled; | ||
294 | } | ||
291 | return count; | 295 | return count; |
292 | } | 296 | } |
293 | 297 | ||
@@ -357,21 +361,21 @@ static int byt_get_min_pstate(void) | |||
357 | { | 361 | { |
358 | u64 value; | 362 | u64 value; |
359 | rdmsrl(BYT_RATIOS, value); | 363 | rdmsrl(BYT_RATIOS, value); |
360 | return (value >> 8) & 0x3F; | 364 | return (value >> 8) & 0x7F; |
361 | } | 365 | } |
362 | 366 | ||
363 | static int byt_get_max_pstate(void) | 367 | static int byt_get_max_pstate(void) |
364 | { | 368 | { |
365 | u64 value; | 369 | u64 value; |
366 | rdmsrl(BYT_RATIOS, value); | 370 | rdmsrl(BYT_RATIOS, value); |
367 | return (value >> 16) & 0x3F; | 371 | return (value >> 16) & 0x7F; |
368 | } | 372 | } |
369 | 373 | ||
370 | static int byt_get_turbo_pstate(void) | 374 | static int byt_get_turbo_pstate(void) |
371 | { | 375 | { |
372 | u64 value; | 376 | u64 value; |
373 | rdmsrl(BYT_TURBO_RATIOS, value); | 377 | rdmsrl(BYT_TURBO_RATIOS, value); |
374 | return value & 0x3F; | 378 | return value & 0x7F; |
375 | } | 379 | } |
376 | 380 | ||
377 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) | 381 | static void byt_set_pstate(struct cpudata *cpudata, int pstate) |
@@ -381,7 +385,7 @@ static void byt_set_pstate(struct cpudata *cpudata, int pstate) | |||
381 | u32 vid; | 385 | u32 vid; |
382 | 386 | ||
383 | val = pstate << 8; | 387 | val = pstate << 8; |
384 | if (limits.no_turbo) | 388 | if (limits.no_turbo && !limits.turbo_disabled) |
385 | val |= (u64)1 << 32; | 389 | val |= (u64)1 << 32; |
386 | 390 | ||
387 | vid_fp = cpudata->vid.min + mul_fp( | 391 | vid_fp = cpudata->vid.min + mul_fp( |
@@ -405,8 +409,8 @@ static void byt_get_vid(struct cpudata *cpudata) | |||
405 | 409 | ||
406 | 410 | ||
407 | rdmsrl(BYT_VIDS, value); | 411 | rdmsrl(BYT_VIDS, value); |
408 | cpudata->vid.min = int_tofp((value >> 8) & 0x3f); | 412 | cpudata->vid.min = int_tofp((value >> 8) & 0x7f); |
409 | cpudata->vid.max = int_tofp((value >> 16) & 0x3f); | 413 | cpudata->vid.max = int_tofp((value >> 16) & 0x7f); |
410 | cpudata->vid.ratio = div_fp( | 414 | cpudata->vid.ratio = div_fp( |
411 | cpudata->vid.max - cpudata->vid.min, | 415 | cpudata->vid.max - cpudata->vid.min, |
412 | int_tofp(cpudata->pstate.max_pstate - | 416 | int_tofp(cpudata->pstate.max_pstate - |
@@ -448,7 +452,7 @@ static void core_set_pstate(struct cpudata *cpudata, int pstate) | |||
448 | u64 val; | 452 | u64 val; |
449 | 453 | ||
450 | val = pstate << 8; | 454 | val = pstate << 8; |
451 | if (limits.no_turbo) | 455 | if (limits.no_turbo && !limits.turbo_disabled) |
452 | val |= (u64)1 << 32; | 456 | val |= (u64)1 << 32; |
453 | 457 | ||
454 | wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); | 458 | wrmsrl_on_cpu(cpudata->cpu, MSR_IA32_PERF_CTL, val); |
@@ -696,9 +700,8 @@ static int intel_pstate_init_cpu(unsigned int cpunum) | |||
696 | 700 | ||
697 | cpu = all_cpu_data[cpunum]; | 701 | cpu = all_cpu_data[cpunum]; |
698 | 702 | ||
699 | intel_pstate_get_cpu_pstates(cpu); | ||
700 | |||
701 | cpu->cpu = cpunum; | 703 | cpu->cpu = cpunum; |
704 | intel_pstate_get_cpu_pstates(cpu); | ||
702 | 705 | ||
703 | init_timer_deferrable(&cpu->timer); | 706 | init_timer_deferrable(&cpu->timer); |
704 | cpu->timer.function = intel_pstate_timer_func; | 707 | cpu->timer.function = intel_pstate_timer_func; |
@@ -741,7 +744,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
741 | limits.min_perf = int_tofp(1); | 744 | limits.min_perf = int_tofp(1); |
742 | limits.max_perf_pct = 100; | 745 | limits.max_perf_pct = 100; |
743 | limits.max_perf = int_tofp(1); | 746 | limits.max_perf = int_tofp(1); |
744 | limits.no_turbo = 0; | 747 | limits.no_turbo = limits.turbo_disabled; |
745 | return 0; | 748 | return 0; |
746 | } | 749 | } |
747 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 750 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
@@ -784,6 +787,7 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
784 | { | 787 | { |
785 | struct cpudata *cpu; | 788 | struct cpudata *cpu; |
786 | int rc; | 789 | int rc; |
790 | u64 misc_en; | ||
787 | 791 | ||
788 | rc = intel_pstate_init_cpu(policy->cpu); | 792 | rc = intel_pstate_init_cpu(policy->cpu); |
789 | if (rc) | 793 | if (rc) |
@@ -791,8 +795,13 @@ static int intel_pstate_cpu_init(struct cpufreq_policy *policy) | |||
791 | 795 | ||
792 | cpu = all_cpu_data[policy->cpu]; | 796 | cpu = all_cpu_data[policy->cpu]; |
793 | 797 | ||
794 | if (!limits.no_turbo && | 798 | rdmsrl(MSR_IA32_MISC_ENABLE, misc_en); |
795 | limits.min_perf_pct == 100 && limits.max_perf_pct == 100) | 799 | if (misc_en & MSR_IA32_MISC_ENABLE_TURBO_DISABLE || |
800 | cpu->pstate.max_pstate == cpu->pstate.turbo_pstate) { | ||
801 | limits.turbo_disabled = 1; | ||
802 | limits.no_turbo = 1; | ||
803 | } | ||
804 | if (limits.min_perf_pct == 100 && limits.max_perf_pct == 100) | ||
796 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; | 805 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; |
797 | else | 806 | else |
798 | policy->policy = CPUFREQ_POLICY_POWERSAVE; | 807 | policy->policy = CPUFREQ_POLICY_POWERSAVE; |
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 2e2c71fcc9ed..4f6b53998d79 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c | |||
@@ -403,6 +403,15 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) | |||
403 | 403 | ||
404 | DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); | 404 | DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); |
405 | 405 | ||
406 | /* | ||
407 | * If the acpi_video interface is not supposed to be used, don't | ||
408 | * bother processing backlight level change requests from firmware. | ||
409 | */ | ||
410 | if (!acpi_video_verify_backlight_support()) { | ||
411 | DRM_DEBUG_KMS("opregion backlight request ignored\n"); | ||
412 | return 0; | ||
413 | } | ||
414 | |||
406 | if (!(bclp & ASLE_BCLP_VALID)) | 415 | if (!(bclp & ASLE_BCLP_VALID)) |
407 | return ASLC_BACKLIGHT_FAILED; | 416 | return ASLC_BACKLIGHT_FAILED; |
408 | 417 | ||
diff --git a/include/acpi/video.h b/include/acpi/video.h index ea4c7bbded4d..843ef1adfbfa 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h | |||
@@ -22,6 +22,7 @@ extern void acpi_video_unregister(void); | |||
22 | extern void acpi_video_unregister_backlight(void); | 22 | extern void acpi_video_unregister_backlight(void); |
23 | extern int acpi_video_get_edid(struct acpi_device *device, int type, | 23 | extern int acpi_video_get_edid(struct acpi_device *device, int type, |
24 | int device_id, void **edid); | 24 | int device_id, void **edid); |
25 | extern bool acpi_video_verify_backlight_support(void); | ||
25 | #else | 26 | #else |
26 | static inline int acpi_video_register(void) { return 0; } | 27 | static inline int acpi_video_register(void) { return 0; } |
27 | static inline void acpi_video_unregister(void) { return; } | 28 | static inline void acpi_video_unregister(void) { return; } |
@@ -31,6 +32,7 @@ static inline int acpi_video_get_edid(struct acpi_device *device, int type, | |||
31 | { | 32 | { |
32 | return -ENODEV; | 33 | return -ENODEV; |
33 | } | 34 | } |
35 | static inline bool acpi_video_verify_backlight_support(void) { return false; } | ||
34 | #endif | 36 | #endif |
35 | 37 | ||
36 | #endif | 38 | #endif |