diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-21 10:29:36 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-21 10:29:36 -0500 |
commit | dedd0c2a48d1eb779373de5eddd04a3e059ce540 (patch) | |
tree | 7c88094810291c16d6f42a76ee4f0c94260d1a61 | |
parent | 15e551e52bf62f595f06ddf7a66b750ccfe41683 (diff) | |
parent | 418521deef3b3dd478a54e4e21d983e010c848f7 (diff) |
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (23 commits)
ACPI: delete acpi_processor_power_verify_c2()
ACPI: allow C3 > 1000usec
ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C
ACPI: power_meter: remove double kfree()
ACPI: processor: restrict early _PDC to opt-in platforms
ACPI: Fix unused variable warning in sbs.c
acpi: make ACPI device id constant
sony-laptop - fix using of uninitialized variable
ACPI: Fix section mismatch error for acpi_early_processor_set_pdc()
eeepc-laptop: disable wireless hotplug for 1201N
eeepc-laptop: add hotplug_disable parameter
eeepc-laptop: switch to using sparse keymap library
eeepc-laptop: dmi blacklist to disable pci hotplug code
eeepc-laptop: disable cpu speed control on EeePC 701
ACPI: don't cond_resched if irq is disabled
ACPI: Remove unnecessary cast.
ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes
ACPI: EC: Add wait for irq storm
ACPI: SBS: Move SBS HC callback to faster Notify queue
x86, ACPI: delete acpi_boot_table_init() return value
...
-rw-r--r-- | arch/x86/kernel/acpi/boot.c | 22 | ||||
-rw-r--r-- | drivers/acpi/acpi_pad.c | 37 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 7 | ||||
-rw-r--r-- | drivers/acpi/ec.c | 126 | ||||
-rw-r--r-- | drivers/acpi/pci_link.c | 2 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 2 | ||||
-rw-r--r-- | drivers/acpi/power.c | 2 | ||||
-rw-r--r-- | drivers/acpi/power_meter.c | 4 | ||||
-rw-r--r-- | drivers/acpi/processor_idle.c | 64 | ||||
-rw-r--r-- | drivers/acpi/processor_pdc.c | 32 | ||||
-rw-r--r-- | drivers/acpi/processor_thermal.c | 3 | ||||
-rw-r--r-- | drivers/acpi/sbs.c | 3 | ||||
-rw-r--r-- | drivers/acpi/sbshc.c | 2 | ||||
-rw-r--r-- | drivers/acpi/video.c | 43 | ||||
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 298 | ||||
-rw-r--r-- | drivers/platform/x86/sony-laptop.c | 9 | ||||
-rw-r--r-- | include/acpi/platform/aclinux.h | 2 | ||||
-rw-r--r-- | include/linux/acpi.h | 6 |
19 files changed, 396 insertions, 269 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index fb1035cd9a6a..036d28adf59d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -1529,16 +1529,10 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { | |||
1529 | * if acpi_blacklisted() acpi_disabled = 1; | 1529 | * if acpi_blacklisted() acpi_disabled = 1; |
1530 | * acpi_irq_model=... | 1530 | * acpi_irq_model=... |
1531 | * ... | 1531 | * ... |
1532 | * | ||
1533 | * return value: (currently ignored) | ||
1534 | * 0: success | ||
1535 | * !0: failure | ||
1536 | */ | 1532 | */ |
1537 | 1533 | ||
1538 | int __init acpi_boot_table_init(void) | 1534 | void __init acpi_boot_table_init(void) |
1539 | { | 1535 | { |
1540 | int error; | ||
1541 | |||
1542 | dmi_check_system(acpi_dmi_table); | 1536 | dmi_check_system(acpi_dmi_table); |
1543 | 1537 | ||
1544 | /* | 1538 | /* |
@@ -1546,15 +1540,14 @@ int __init acpi_boot_table_init(void) | |||
1546 | * One exception: acpi=ht continues far enough to enumerate LAPICs | 1540 | * One exception: acpi=ht continues far enough to enumerate LAPICs |
1547 | */ | 1541 | */ |
1548 | if (acpi_disabled && !acpi_ht) | 1542 | if (acpi_disabled && !acpi_ht) |
1549 | return 1; | 1543 | return; |
1550 | 1544 | ||
1551 | /* | 1545 | /* |
1552 | * Initialize the ACPI boot-time table parser. | 1546 | * Initialize the ACPI boot-time table parser. |
1553 | */ | 1547 | */ |
1554 | error = acpi_table_init(); | 1548 | if (acpi_table_init()) { |
1555 | if (error) { | ||
1556 | disable_acpi(); | 1549 | disable_acpi(); |
1557 | return error; | 1550 | return; |
1558 | } | 1551 | } |
1559 | 1552 | ||
1560 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); | 1553 | acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); |
@@ -1562,18 +1555,15 @@ int __init acpi_boot_table_init(void) | |||
1562 | /* | 1555 | /* |
1563 | * blacklist may disable ACPI entirely | 1556 | * blacklist may disable ACPI entirely |
1564 | */ | 1557 | */ |
1565 | error = acpi_blacklisted(); | 1558 | if (acpi_blacklisted()) { |
1566 | if (error) { | ||
1567 | if (acpi_force) { | 1559 | if (acpi_force) { |
1568 | printk(KERN_WARNING PREFIX "acpi=force override\n"); | 1560 | printk(KERN_WARNING PREFIX "acpi=force override\n"); |
1569 | } else { | 1561 | } else { |
1570 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); | 1562 | printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); |
1571 | disable_acpi(); | 1563 | disable_acpi(); |
1572 | return error; | 1564 | return; |
1573 | } | 1565 | } |
1574 | } | 1566 | } |
1575 | |||
1576 | return 0; | ||
1577 | } | 1567 | } |
1578 | 1568 | ||
1579 | int __init early_acpi_boot_init(void) | 1569 | int __init early_acpi_boot_init(void) |
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 97991ac6f5fc..7e52295f1ecc 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -208,7 +208,7 @@ static int power_saving_thread(void *data) | |||
208 | * the mechanism only works when all CPUs have RT task running, | 208 | * the mechanism only works when all CPUs have RT task running, |
209 | * as if one CPU hasn't RT task, RT task from other CPUs will | 209 | * as if one CPU hasn't RT task, RT task from other CPUs will |
210 | * borrow CPU time from this CPU and cause RT task use > 95% | 210 | * borrow CPU time from this CPU and cause RT task use > 95% |
211 | * CPU time. To make 'avoid staration' work, takes a nap here. | 211 | * CPU time. To make 'avoid starvation' work, takes a nap here. |
212 | */ | 212 | */ |
213 | if (do_sleep) | 213 | if (do_sleep) |
214 | schedule_timeout_killable(HZ * idle_pct / 100); | 214 | schedule_timeout_killable(HZ * idle_pct / 100); |
@@ -222,14 +222,18 @@ static struct task_struct *ps_tsks[NR_CPUS]; | |||
222 | static unsigned int ps_tsk_num; | 222 | static unsigned int ps_tsk_num; |
223 | static int create_power_saving_task(void) | 223 | static int create_power_saving_task(void) |
224 | { | 224 | { |
225 | int rc = -ENOMEM; | ||
226 | |||
225 | ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, | 227 | ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, |
226 | (void *)(unsigned long)ps_tsk_num, | 228 | (void *)(unsigned long)ps_tsk_num, |
227 | "power_saving/%d", ps_tsk_num); | 229 | "power_saving/%d", ps_tsk_num); |
228 | if (ps_tsks[ps_tsk_num]) { | 230 | rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; |
231 | if (!rc) | ||
229 | ps_tsk_num++; | 232 | ps_tsk_num++; |
230 | return 0; | 233 | else |
231 | } | 234 | ps_tsks[ps_tsk_num] = NULL; |
232 | return -EINVAL; | 235 | |
236 | return rc; | ||
233 | } | 237 | } |
234 | 238 | ||
235 | static void destroy_power_saving_task(void) | 239 | static void destroy_power_saving_task(void) |
@@ -237,6 +241,7 @@ static void destroy_power_saving_task(void) | |||
237 | if (ps_tsk_num > 0) { | 241 | if (ps_tsk_num > 0) { |
238 | ps_tsk_num--; | 242 | ps_tsk_num--; |
239 | kthread_stop(ps_tsks[ps_tsk_num]); | 243 | kthread_stop(ps_tsks[ps_tsk_num]); |
244 | ps_tsks[ps_tsk_num] = NULL; | ||
240 | } | 245 | } |
241 | } | 246 | } |
242 | 247 | ||
@@ -253,7 +258,7 @@ static void set_power_saving_task_num(unsigned int num) | |||
253 | } | 258 | } |
254 | } | 259 | } |
255 | 260 | ||
256 | static int acpi_pad_idle_cpus(unsigned int num_cpus) | 261 | static void acpi_pad_idle_cpus(unsigned int num_cpus) |
257 | { | 262 | { |
258 | get_online_cpus(); | 263 | get_online_cpus(); |
259 | 264 | ||
@@ -261,7 +266,6 @@ static int acpi_pad_idle_cpus(unsigned int num_cpus) | |||
261 | set_power_saving_task_num(num_cpus); | 266 | set_power_saving_task_num(num_cpus); |
262 | 267 | ||
263 | put_online_cpus(); | 268 | put_online_cpus(); |
264 | return 0; | ||
265 | } | 269 | } |
266 | 270 | ||
267 | static uint32_t acpi_pad_idle_cpus_num(void) | 271 | static uint32_t acpi_pad_idle_cpus_num(void) |
@@ -369,19 +373,21 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) | |||
369 | static int acpi_pad_pur(acpi_handle handle, int *num_cpus) | 373 | static int acpi_pad_pur(acpi_handle handle, int *num_cpus) |
370 | { | 374 | { |
371 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 375 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
372 | acpi_status status; | ||
373 | union acpi_object *package; | 376 | union acpi_object *package; |
374 | int rev, num, ret = -EINVAL; | 377 | int rev, num, ret = -EINVAL; |
375 | 378 | ||
376 | status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); | 379 | if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) |
377 | if (ACPI_FAILURE(status)) | 380 | return -EINVAL; |
381 | |||
382 | if (!buffer.length || !buffer.pointer) | ||
378 | return -EINVAL; | 383 | return -EINVAL; |
384 | |||
379 | package = buffer.pointer; | 385 | package = buffer.pointer; |
380 | if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) | 386 | if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) |
381 | goto out; | 387 | goto out; |
382 | rev = package->package.elements[0].integer.value; | 388 | rev = package->package.elements[0].integer.value; |
383 | num = package->package.elements[1].integer.value; | 389 | num = package->package.elements[1].integer.value; |
384 | if (rev != 1) | 390 | if (rev != 1 || num < 0) |
385 | goto out; | 391 | goto out; |
386 | *num_cpus = num; | 392 | *num_cpus = num; |
387 | ret = 0; | 393 | ret = 0; |
@@ -410,7 +416,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat, | |||
410 | 416 | ||
411 | static void acpi_pad_handle_notify(acpi_handle handle) | 417 | static void acpi_pad_handle_notify(acpi_handle handle) |
412 | { | 418 | { |
413 | int num_cpus, ret; | 419 | int num_cpus; |
414 | uint32_t idle_cpus; | 420 | uint32_t idle_cpus; |
415 | 421 | ||
416 | mutex_lock(&isolated_cpus_lock); | 422 | mutex_lock(&isolated_cpus_lock); |
@@ -418,12 +424,9 @@ static void acpi_pad_handle_notify(acpi_handle handle) | |||
418 | mutex_unlock(&isolated_cpus_lock); | 424 | mutex_unlock(&isolated_cpus_lock); |
419 | return; | 425 | return; |
420 | } | 426 | } |
421 | ret = acpi_pad_idle_cpus(num_cpus); | 427 | acpi_pad_idle_cpus(num_cpus); |
422 | idle_cpus = acpi_pad_idle_cpus_num(); | 428 | idle_cpus = acpi_pad_idle_cpus_num(); |
423 | if (!ret) | 429 | acpi_pad_ost(handle, 0, idle_cpus); |
424 | acpi_pad_ost(handle, 0, idle_cpus); | ||
425 | else | ||
426 | acpi_pad_ost(handle, 1, 0); | ||
427 | mutex_unlock(&isolated_cpus_lock); | 430 | mutex_unlock(&isolated_cpus_lock); |
428 | } | 431 | } |
429 | 432 | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index cf761b904e4a..a52126e46307 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -490,9 +490,14 @@ static void acpi_bus_osc_support(void) | |||
490 | 490 | ||
491 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 491 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; |
492 | capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ | 492 | capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ |
493 | #ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR | 493 | #if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ |
494 | defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) | ||
494 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; | 495 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; |
495 | #endif | 496 | #endif |
497 | |||
498 | #if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) | ||
499 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; | ||
500 | #endif | ||
496 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) | 501 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) |
497 | return; | 502 | return; |
498 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) | 503 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index fd1801bdee66..d6471bb6852f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -201,14 +201,13 @@ unlock: | |||
201 | spin_unlock_irqrestore(&ec->curr_lock, flags); | 201 | spin_unlock_irqrestore(&ec->curr_lock, flags); |
202 | } | 202 | } |
203 | 203 | ||
204 | static void acpi_ec_gpe_query(void *ec_cxt); | 204 | static int acpi_ec_sync_query(struct acpi_ec *ec); |
205 | 205 | ||
206 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | 206 | static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) |
207 | { | 207 | { |
208 | if (state & ACPI_EC_FLAG_SCI) { | 208 | if (state & ACPI_EC_FLAG_SCI) { |
209 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) | 209 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) |
210 | return acpi_os_execute(OSL_EC_BURST_HANDLER, | 210 | return acpi_ec_sync_query(ec); |
211 | acpi_ec_gpe_query, ec); | ||
212 | } | 211 | } |
213 | return 0; | 212 | return 0; |
214 | } | 213 | } |
@@ -249,11 +248,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
249 | { | 248 | { |
250 | unsigned long tmp; | 249 | unsigned long tmp; |
251 | int ret = 0; | 250 | int ret = 0; |
252 | pr_debug(PREFIX "transaction start\n"); | ||
253 | /* disable GPE during transaction if storm is detected */ | ||
254 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
255 | acpi_disable_gpe(NULL, ec->gpe); | ||
256 | } | ||
257 | if (EC_FLAGS_MSI) | 251 | if (EC_FLAGS_MSI) |
258 | udelay(ACPI_EC_MSI_UDELAY); | 252 | udelay(ACPI_EC_MSI_UDELAY); |
259 | /* start transaction */ | 253 | /* start transaction */ |
@@ -265,20 +259,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
265 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 259 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
266 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 260 | spin_unlock_irqrestore(&ec->curr_lock, tmp); |
267 | ret = ec_poll(ec); | 261 | ret = ec_poll(ec); |
268 | pr_debug(PREFIX "transaction end\n"); | ||
269 | spin_lock_irqsave(&ec->curr_lock, tmp); | 262 | spin_lock_irqsave(&ec->curr_lock, tmp); |
270 | ec->curr = NULL; | 263 | ec->curr = NULL; |
271 | spin_unlock_irqrestore(&ec->curr_lock, tmp); | 264 | spin_unlock_irqrestore(&ec->curr_lock, tmp); |
272 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
273 | /* check if we received SCI during transaction */ | ||
274 | ec_check_sci(ec, acpi_ec_read_status(ec)); | ||
275 | /* it is safe to enable GPE outside of transaction */ | ||
276 | acpi_enable_gpe(NULL, ec->gpe); | ||
277 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { | ||
278 | pr_info(PREFIX "GPE storm detected, " | ||
279 | "transactions will use polling mode\n"); | ||
280 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | ||
281 | } | ||
282 | return ret; | 265 | return ret; |
283 | } | 266 | } |
284 | 267 | ||
@@ -321,7 +304,26 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) | |||
321 | status = -ETIME; | 304 | status = -ETIME; |
322 | goto end; | 305 | goto end; |
323 | } | 306 | } |
307 | pr_debug(PREFIX "transaction start\n"); | ||
308 | /* disable GPE during transaction if storm is detected */ | ||
309 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
310 | acpi_disable_gpe(NULL, ec->gpe); | ||
311 | } | ||
312 | |||
324 | status = acpi_ec_transaction_unlocked(ec, t); | 313 | status = acpi_ec_transaction_unlocked(ec, t); |
314 | |||
315 | /* check if we received SCI during transaction */ | ||
316 | ec_check_sci_sync(ec, acpi_ec_read_status(ec)); | ||
317 | if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { | ||
318 | msleep(1); | ||
319 | /* it is safe to enable GPE outside of transaction */ | ||
320 | acpi_enable_gpe(NULL, ec->gpe); | ||
321 | } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { | ||
322 | pr_info(PREFIX "GPE storm detected, " | ||
323 | "transactions will use polling mode\n"); | ||
324 | set_bit(EC_FLAGS_GPE_STORM, &ec->flags); | ||
325 | } | ||
326 | pr_debug(PREFIX "transaction end\n"); | ||
325 | end: | 327 | end: |
326 | if (ec->global_lock) | 328 | if (ec->global_lock) |
327 | acpi_release_global_lock(glk); | 329 | acpi_release_global_lock(glk); |
@@ -443,7 +445,7 @@ int ec_transaction(u8 command, | |||
443 | 445 | ||
444 | EXPORT_SYMBOL(ec_transaction); | 446 | EXPORT_SYMBOL(ec_transaction); |
445 | 447 | ||
446 | static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | 448 | static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) |
447 | { | 449 | { |
448 | int result; | 450 | int result; |
449 | u8 d; | 451 | u8 d; |
@@ -452,20 +454,16 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | |||
452 | .wlen = 0, .rlen = 1}; | 454 | .wlen = 0, .rlen = 1}; |
453 | if (!ec || !data) | 455 | if (!ec || !data) |
454 | return -EINVAL; | 456 | return -EINVAL; |
455 | |||
456 | /* | 457 | /* |
457 | * Query the EC to find out which _Qxx method we need to evaluate. | 458 | * Query the EC to find out which _Qxx method we need to evaluate. |
458 | * Note that successful completion of the query causes the ACPI_EC_SCI | 459 | * Note that successful completion of the query causes the ACPI_EC_SCI |
459 | * bit to be cleared (and thus clearing the interrupt source). | 460 | * bit to be cleared (and thus clearing the interrupt source). |
460 | */ | 461 | */ |
461 | 462 | result = acpi_ec_transaction_unlocked(ec, &t); | |
462 | result = acpi_ec_transaction(ec, &t); | ||
463 | if (result) | 463 | if (result) |
464 | return result; | 464 | return result; |
465 | |||
466 | if (!d) | 465 | if (!d) |
467 | return -ENODATA; | 466 | return -ENODATA; |
468 | |||
469 | *data = d; | 467 | *data = d; |
470 | return 0; | 468 | return 0; |
471 | } | 469 | } |
@@ -509,43 +507,79 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) | |||
509 | 507 | ||
510 | EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); | 508 | EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); |
511 | 509 | ||
512 | static void acpi_ec_gpe_query(void *ec_cxt) | 510 | static void acpi_ec_run(void *cxt) |
513 | { | 511 | { |
514 | struct acpi_ec *ec = ec_cxt; | 512 | struct acpi_ec_query_handler *handler = cxt; |
515 | u8 value = 0; | 513 | if (!handler) |
516 | struct acpi_ec_query_handler *handler, copy; | ||
517 | |||
518 | if (!ec || acpi_ec_query(ec, &value)) | ||
519 | return; | 514 | return; |
520 | mutex_lock(&ec->lock); | 515 | pr_debug(PREFIX "start query execution\n"); |
516 | if (handler->func) | ||
517 | handler->func(handler->data); | ||
518 | else if (handler->handle) | ||
519 | acpi_evaluate_object(handler->handle, NULL, NULL, NULL); | ||
520 | pr_debug(PREFIX "stop query execution\n"); | ||
521 | kfree(handler); | ||
522 | } | ||
523 | |||
524 | static int acpi_ec_sync_query(struct acpi_ec *ec) | ||
525 | { | ||
526 | u8 value = 0; | ||
527 | int status; | ||
528 | struct acpi_ec_query_handler *handler, *copy; | ||
529 | if ((status = acpi_ec_query_unlocked(ec, &value))) | ||
530 | return status; | ||
521 | list_for_each_entry(handler, &ec->list, node) { | 531 | list_for_each_entry(handler, &ec->list, node) { |
522 | if (value == handler->query_bit) { | 532 | if (value == handler->query_bit) { |
523 | /* have custom handler for this bit */ | 533 | /* have custom handler for this bit */ |
524 | memcpy(©, handler, sizeof(copy)); | 534 | copy = kmalloc(sizeof(*handler), GFP_KERNEL); |
525 | mutex_unlock(&ec->lock); | 535 | if (!copy) |
526 | if (copy.func) { | 536 | return -ENOMEM; |
527 | copy.func(copy.data); | 537 | memcpy(copy, handler, sizeof(*copy)); |
528 | } else if (copy.handle) { | 538 | pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); |
529 | acpi_evaluate_object(copy.handle, NULL, NULL, NULL); | 539 | return acpi_os_execute((copy->func) ? |
530 | } | 540 | OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, |
531 | return; | 541 | acpi_ec_run, copy); |
532 | } | 542 | } |
533 | } | 543 | } |
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static void acpi_ec_gpe_query(void *ec_cxt) | ||
548 | { | ||
549 | struct acpi_ec *ec = ec_cxt; | ||
550 | if (!ec) | ||
551 | return; | ||
552 | mutex_lock(&ec->lock); | ||
553 | acpi_ec_sync_query(ec); | ||
534 | mutex_unlock(&ec->lock); | 554 | mutex_unlock(&ec->lock); |
535 | } | 555 | } |
536 | 556 | ||
557 | static void acpi_ec_gpe_query(void *ec_cxt); | ||
558 | |||
559 | static int ec_check_sci(struct acpi_ec *ec, u8 state) | ||
560 | { | ||
561 | if (state & ACPI_EC_FLAG_SCI) { | ||
562 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { | ||
563 | pr_debug(PREFIX "push gpe query to the queue\n"); | ||
564 | return acpi_os_execute(OSL_NOTIFY_HANDLER, | ||
565 | acpi_ec_gpe_query, ec); | ||
566 | } | ||
567 | } | ||
568 | return 0; | ||
569 | } | ||
570 | |||
537 | static u32 acpi_ec_gpe_handler(void *data) | 571 | static u32 acpi_ec_gpe_handler(void *data) |
538 | { | 572 | { |
539 | struct acpi_ec *ec = data; | 573 | struct acpi_ec *ec = data; |
540 | u8 status; | ||
541 | 574 | ||
542 | pr_debug(PREFIX "~~~> interrupt\n"); | 575 | pr_debug(PREFIX "~~~> interrupt\n"); |
543 | status = acpi_ec_read_status(ec); | ||
544 | 576 | ||
545 | advance_transaction(ec, status); | 577 | advance_transaction(ec, acpi_ec_read_status(ec)); |
546 | if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) | 578 | if (ec_transaction_done(ec) && |
579 | (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { | ||
547 | wake_up(&ec->wait); | 580 | wake_up(&ec->wait); |
548 | ec_check_sci(ec, status); | 581 | ec_check_sci(ec, acpi_ec_read_status(ec)); |
582 | } | ||
549 | return ACPI_INTERRUPT_HANDLED; | 583 | return ACPI_INTERRUPT_HANDLED; |
550 | } | 584 | } |
551 | 585 | ||
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 394ae89409c2..04b0f007c9b7 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link"); | |||
56 | static int acpi_pci_link_add(struct acpi_device *device); | 56 | static int acpi_pci_link_add(struct acpi_device *device); |
57 | static int acpi_pci_link_remove(struct acpi_device *device, int type); | 57 | static int acpi_pci_link_remove(struct acpi_device *device, int type); |
58 | 58 | ||
59 | static struct acpi_device_id link_device_ids[] = { | 59 | static const struct acpi_device_id link_device_ids[] = { |
60 | {"PNP0C0F", 0}, | 60 | {"PNP0C0F", 0}, |
61 | {"", 0}, | 61 | {"", 0}, |
62 | }; | 62 | }; |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 101cce3681d1..64f55b6db73c 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device); | |||
46 | static int acpi_pci_root_remove(struct acpi_device *device, int type); | 46 | static int acpi_pci_root_remove(struct acpi_device *device, int type); |
47 | static int acpi_pci_root_start(struct acpi_device *device); | 47 | static int acpi_pci_root_start(struct acpi_device *device); |
48 | 48 | ||
49 | static struct acpi_device_id root_device_ids[] = { | 49 | static const struct acpi_device_id root_device_ids[] = { |
50 | {"PNP0A03", 0}, | 50 | {"PNP0A03", 0}, |
51 | {"", 0}, | 51 | {"", 0}, |
52 | }; | 52 | }; |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 22b297916519..0f30c3c1eea4 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type); | |||
65 | static int acpi_power_resume(struct acpi_device *device); | 65 | static int acpi_power_resume(struct acpi_device *device); |
66 | static int acpi_power_open_fs(struct inode *inode, struct file *file); | 66 | static int acpi_power_open_fs(struct inode *inode, struct file *file); |
67 | 67 | ||
68 | static struct acpi_device_id power_device_ids[] = { | 68 | static const struct acpi_device_id power_device_ids[] = { |
69 | {ACPI_POWER_HID, 0}, | 69 | {ACPI_POWER_HID, 0}, |
70 | {"", 0}, | 70 | {"", 0}, |
71 | }; | 71 | }; |
diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index 2ef7030a0c28..dc4ffadf8122 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c | |||
@@ -64,7 +64,7 @@ static int can_cap_in_hardware(void) | |||
64 | return force_cap_on || cap_in_hardware; | 64 | return force_cap_on || cap_in_hardware; |
65 | } | 65 | } |
66 | 66 | ||
67 | static struct acpi_device_id power_meter_ids[] = { | 67 | static const struct acpi_device_id power_meter_ids[] = { |
68 | {"ACPI000D", 0}, | 68 | {"ACPI000D", 0}, |
69 | {"", 0}, | 69 | {"", 0}, |
70 | }; | 70 | }; |
@@ -534,6 +534,7 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) | |||
534 | 534 | ||
535 | kfree(resource->domain_devices); | 535 | kfree(resource->domain_devices); |
536 | kobject_put(resource->holders_dir); | 536 | kobject_put(resource->holders_dir); |
537 | resource->num_domain_devices = 0; | ||
537 | } | 538 | } |
538 | 539 | ||
539 | static int read_domain_devices(struct acpi_power_meter_resource *resource) | 540 | static int read_domain_devices(struct acpi_power_meter_resource *resource) |
@@ -740,7 +741,6 @@ skip_unsafe_cap: | |||
740 | 741 | ||
741 | return res; | 742 | return res; |
742 | error: | 743 | error: |
743 | remove_domain_devices(resource); | ||
744 | remove_attrs(resource); | 744 | remove_attrs(resource); |
745 | return res; | 745 | return res; |
746 | } | 746 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d1676b1754d9..7c0441f63b39 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -305,6 +305,28 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) | |||
305 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; | 305 | pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; |
306 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; | 306 | pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; |
307 | 307 | ||
308 | /* | ||
309 | * FADT specified C2 latency must be less than or equal to | ||
310 | * 100 microseconds. | ||
311 | */ | ||
312 | if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | ||
313 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
314 | "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); | ||
315 | /* invalidate C2 */ | ||
316 | pr->power.states[ACPI_STATE_C2].address = 0; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * FADT supplied C3 latency must be less than or equal to | ||
321 | * 1000 microseconds. | ||
322 | */ | ||
323 | if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | ||
324 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
325 | "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); | ||
326 | /* invalidate C3 */ | ||
327 | pr->power.states[ACPI_STATE_C3].address = 0; | ||
328 | } | ||
329 | |||
308 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 330 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
309 | "lvl2[0x%08x] lvl3[0x%08x]\n", | 331 | "lvl2[0x%08x] lvl3[0x%08x]\n", |
310 | pr->power.states[ACPI_STATE_C2].address, | 332 | pr->power.states[ACPI_STATE_C2].address, |
@@ -494,33 +516,6 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
494 | return status; | 516 | return status; |
495 | } | 517 | } |
496 | 518 | ||
497 | static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) | ||
498 | { | ||
499 | |||
500 | if (!cx->address) | ||
501 | return; | ||
502 | |||
503 | /* | ||
504 | * C2 latency must be less than or equal to 100 | ||
505 | * microseconds. | ||
506 | */ | ||
507 | else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { | ||
508 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
509 | "latency too large [%d]\n", cx->latency)); | ||
510 | return; | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * Otherwise we've met all of our C2 requirements. | ||
515 | * Normalize the C2 latency to expidite policy | ||
516 | */ | ||
517 | cx->valid = 1; | ||
518 | |||
519 | cx->latency_ticks = cx->latency; | ||
520 | |||
521 | return; | ||
522 | } | ||
523 | |||
524 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | 519 | static void acpi_processor_power_verify_c3(struct acpi_processor *pr, |
525 | struct acpi_processor_cx *cx) | 520 | struct acpi_processor_cx *cx) |
526 | { | 521 | { |
@@ -532,16 +527,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
532 | return; | 527 | return; |
533 | 528 | ||
534 | /* | 529 | /* |
535 | * C3 latency must be less than or equal to 1000 | ||
536 | * microseconds. | ||
537 | */ | ||
538 | else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { | ||
539 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
540 | "latency too large [%d]\n", cx->latency)); | ||
541 | return; | ||
542 | } | ||
543 | |||
544 | /* | ||
545 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) | 530 | * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) |
546 | * DMA transfers are used by any ISA device to avoid livelock. | 531 | * DMA transfers are used by any ISA device to avoid livelock. |
547 | * Note that we could disable Type-F DMA (as recommended by | 532 | * Note that we could disable Type-F DMA (as recommended by |
@@ -629,7 +614,10 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
629 | break; | 614 | break; |
630 | 615 | ||
631 | case ACPI_STATE_C2: | 616 | case ACPI_STATE_C2: |
632 | acpi_processor_power_verify_c2(cx); | 617 | if (!cx->address) |
618 | break; | ||
619 | cx->valid = 1; | ||
620 | cx->latency_ticks = cx->latency; /* Normalize latency */ | ||
633 | break; | 621 | break; |
634 | 622 | ||
635 | case ACPI_STATE_C3: | 623 | case ACPI_STATE_C3: |
diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 30e4dc0cdf30..7247819dbd80 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c | |||
@@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle) | |||
144 | } | 144 | } |
145 | EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); | 145 | EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); |
146 | 146 | ||
147 | static int early_pdc_optin; | ||
148 | static int set_early_pdc_optin(const struct dmi_system_id *id) | ||
149 | { | ||
150 | early_pdc_optin = 1; | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { | ||
155 | { | ||
156 | set_early_pdc_optin, "HP Envy", { | ||
157 | DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), | ||
158 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, | ||
159 | { | ||
160 | set_early_pdc_optin, "HP Pavilion dv6", { | ||
161 | DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), | ||
162 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, | ||
163 | { | ||
164 | set_early_pdc_optin, "HP Pavilion dv7", { | ||
165 | DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), | ||
166 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, | ||
167 | {}, | ||
168 | }; | ||
169 | |||
147 | static acpi_status | 170 | static acpi_status |
148 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | 171 | early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) |
149 | { | 172 | { |
@@ -151,7 +174,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
151 | return AE_OK; | 174 | return AE_OK; |
152 | } | 175 | } |
153 | 176 | ||
154 | void acpi_early_processor_set_pdc(void) | 177 | void __init acpi_early_processor_set_pdc(void) |
155 | { | 178 | { |
156 | /* | 179 | /* |
157 | * Check whether the system is DMI table. If yes, OSPM | 180 | * Check whether the system is DMI table. If yes, OSPM |
@@ -159,6 +182,13 @@ void acpi_early_processor_set_pdc(void) | |||
159 | */ | 182 | */ |
160 | dmi_check_system(processor_idle_dmi_table); | 183 | dmi_check_system(processor_idle_dmi_table); |
161 | 184 | ||
185 | /* | ||
186 | * Allow systems to opt-in to early _PDC evaluation. | ||
187 | */ | ||
188 | dmi_check_system(early_pdc_optin_table); | ||
189 | if (!early_pdc_optin) | ||
190 | return; | ||
191 | |||
162 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | 192 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, |
163 | ACPI_UINT32_MAX, | 193 | ACPI_UINT32_MAX, |
164 | early_init_pdc, NULL, NULL, NULL); | 194 | early_init_pdc, NULL, NULL, NULL); |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 140c5c5b423c..6deafb4aa0da 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -443,8 +443,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { | |||
443 | #ifdef CONFIG_ACPI_PROCFS | 443 | #ifdef CONFIG_ACPI_PROCFS |
444 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) | 444 | static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) |
445 | { | 445 | { |
446 | struct acpi_processor *pr = (struct acpi_processor *)seq->private; | 446 | struct acpi_processor *pr = seq->private; |
447 | |||
448 | 447 | ||
449 | if (!pr) | 448 | if (!pr) |
450 | goto end; | 449 | goto end; |
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 52b9db8afc20..b16ddbf23a9c 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -822,7 +822,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
822 | 822 | ||
823 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) | 823 | static void acpi_battery_remove(struct acpi_sbs *sbs, int id) |
824 | { | 824 | { |
825 | #if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) | ||
825 | struct acpi_battery *battery = &sbs->battery[id]; | 826 | struct acpi_battery *battery = &sbs->battery[id]; |
827 | #endif | ||
828 | |||
826 | #ifdef CONFIG_ACPI_SYSFS_POWER | 829 | #ifdef CONFIG_ACPI_SYSFS_POWER |
827 | if (battery->bat.dev) { | 830 | if (battery->bat.dev) { |
828 | if (battery->have_sysfs_alarm) | 831 | if (battery->have_sysfs_alarm) |
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index d9339806df45..fd09229282ea 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c | |||
@@ -242,7 +242,7 @@ static int smbus_alarm(void *context) | |||
242 | case ACPI_SBS_CHARGER: | 242 | case ACPI_SBS_CHARGER: |
243 | case ACPI_SBS_MANAGER: | 243 | case ACPI_SBS_MANAGER: |
244 | case ACPI_SBS_BATTERY: | 244 | case ACPI_SBS_BATTERY: |
245 | acpi_os_execute(OSL_GPE_HANDLER, | 245 | acpi_os_execute(OSL_NOTIFY_HANDLER, |
246 | acpi_smbus_callback, hc); | 246 | acpi_smbus_callback, hc); |
247 | default:; | 247 | default:; |
248 | } | 248 | } |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 72e76b4b6538..b765790b32be 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -78,6 +78,13 @@ MODULE_LICENSE("GPL"); | |||
78 | static int brightness_switch_enabled = 1; | 78 | static int brightness_switch_enabled = 1; |
79 | module_param(brightness_switch_enabled, bool, 0644); | 79 | module_param(brightness_switch_enabled, bool, 0644); |
80 | 80 | ||
81 | /* | ||
82 | * By default, we don't allow duplicate ACPI video bus devices | ||
83 | * under the same VGA controller | ||
84 | */ | ||
85 | static int allow_duplicates; | ||
86 | module_param(allow_duplicates, bool, 0644); | ||
87 | |||
81 | static int register_count = 0; | 88 | static int register_count = 0; |
82 | static int acpi_video_bus_add(struct acpi_device *device); | 89 | static int acpi_video_bus_add(struct acpi_device *device); |
83 | static int acpi_video_bus_remove(struct acpi_device *device, int type); | 90 | static int acpi_video_bus_remove(struct acpi_device *device, int type); |
@@ -2239,11 +2246,47 @@ static int acpi_video_resume(struct acpi_device *device) | |||
2239 | return AE_OK; | 2246 | return AE_OK; |
2240 | } | 2247 | } |
2241 | 2248 | ||
2249 | static acpi_status | ||
2250 | acpi_video_bus_match(acpi_handle handle, u32 level, void *context, | ||
2251 | void **return_value) | ||
2252 | { | ||
2253 | struct acpi_device *device = context; | ||
2254 | struct acpi_device *sibling; | ||
2255 | int result; | ||
2256 | |||
2257 | if (handle == device->handle) | ||
2258 | return AE_CTRL_TERMINATE; | ||
2259 | |||
2260 | result = acpi_bus_get_device(handle, &sibling); | ||
2261 | if (result) | ||
2262 | return AE_OK; | ||
2263 | |||
2264 | if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) | ||
2265 | return AE_ALREADY_EXISTS; | ||
2266 | |||
2267 | return AE_OK; | ||
2268 | } | ||
2269 | |||
2242 | static int acpi_video_bus_add(struct acpi_device *device) | 2270 | static int acpi_video_bus_add(struct acpi_device *device) |
2243 | { | 2271 | { |
2244 | struct acpi_video_bus *video; | 2272 | struct acpi_video_bus *video; |
2245 | struct input_dev *input; | 2273 | struct input_dev *input; |
2246 | int error; | 2274 | int error; |
2275 | acpi_status status; | ||
2276 | |||
2277 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, | ||
2278 | device->parent->handle, 1, | ||
2279 | acpi_video_bus_match, NULL, | ||
2280 | device, NULL); | ||
2281 | if (status == AE_ALREADY_EXISTS) { | ||
2282 | printk(KERN_WARNING FW_BUG | ||
2283 | "Duplicate ACPI video bus devices for the" | ||
2284 | " same VGA controller, please try module " | ||
2285 | "parameter \"video.allow_duplicates=1\"" | ||
2286 | "if the current driver doesn't work.\n"); | ||
2287 | if (!allow_duplicates) | ||
2288 | return -ENODEV; | ||
2289 | } | ||
2247 | 2290 | ||
2248 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); | 2291 | video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); |
2249 | if (!video) | 2292 | if (!video) |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index db32c25e3605..f526e735c5ab 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -364,6 +364,7 @@ config EEEPC_LAPTOP | |||
364 | select HWMON | 364 | select HWMON |
365 | select LEDS_CLASS | 365 | select LEDS_CLASS |
366 | select NEW_LEDS | 366 | select NEW_LEDS |
367 | select INPUT_SPARSEKMAP | ||
367 | ---help--- | 368 | ---help--- |
368 | This driver supports the Fn-Fx keys on Eee PC laptops. | 369 | This driver supports the Fn-Fx keys on Eee PC laptops. |
369 | 370 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 5838c69b2fb3..e2be6bb33d92 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -31,10 +31,12 @@ | |||
31 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> |
32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
33 | #include <linux/input.h> | 33 | #include <linux/input.h> |
34 | #include <linux/input/sparse-keymap.h> | ||
34 | #include <linux/rfkill.h> | 35 | #include <linux/rfkill.h> |
35 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
36 | #include <linux/pci_hotplug.h> | 37 | #include <linux/pci_hotplug.h> |
37 | #include <linux/leds.h> | 38 | #include <linux/leds.h> |
39 | #include <linux/dmi.h> | ||
38 | 40 | ||
39 | #define EEEPC_LAPTOP_VERSION "0.1" | 41 | #define EEEPC_LAPTOP_VERSION "0.1" |
40 | #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" | 42 | #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" |
@@ -48,6 +50,14 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper"); | |||
48 | MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); | 50 | MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); |
49 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
50 | 52 | ||
53 | static bool hotplug_disabled; | ||
54 | |||
55 | module_param(hotplug_disabled, bool, 0644); | ||
56 | MODULE_PARM_DESC(hotplug_disabled, | ||
57 | "Disable hotplug for wireless device. " | ||
58 | "If your laptop need that, please report to " | ||
59 | "acpi4asus-user@lists.sourceforge.net."); | ||
60 | |||
51 | /* | 61 | /* |
52 | * Definitions for Asus EeePC | 62 | * Definitions for Asus EeePC |
53 | */ | 63 | */ |
@@ -120,38 +130,28 @@ static const char *cm_setv[] = { | |||
120 | NULL, NULL, "PBPS", "TPDS" | 130 | NULL, NULL, "PBPS", "TPDS" |
121 | }; | 131 | }; |
122 | 132 | ||
123 | struct key_entry { | ||
124 | char type; | ||
125 | u8 code; | ||
126 | u16 keycode; | ||
127 | }; | ||
128 | |||
129 | enum { KE_KEY, KE_END }; | ||
130 | |||
131 | static const struct key_entry eeepc_keymap[] = { | 133 | static const struct key_entry eeepc_keymap[] = { |
132 | /* Sleep already handled via generic ACPI code */ | 134 | { KE_KEY, 0x10, { KEY_WLAN } }, |
133 | {KE_KEY, 0x10, KEY_WLAN }, | 135 | { KE_KEY, 0x11, { KEY_WLAN } }, |
134 | {KE_KEY, 0x11, KEY_WLAN }, | 136 | { KE_KEY, 0x12, { KEY_PROG1 } }, |
135 | {KE_KEY, 0x12, KEY_PROG1 }, | 137 | { KE_KEY, 0x13, { KEY_MUTE } }, |
136 | {KE_KEY, 0x13, KEY_MUTE }, | 138 | { KE_KEY, 0x14, { KEY_VOLUMEDOWN } }, |
137 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, | 139 | { KE_KEY, 0x15, { KEY_VOLUMEUP } }, |
138 | {KE_KEY, 0x15, KEY_VOLUMEUP }, | 140 | { KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, |
139 | {KE_KEY, 0x16, KEY_DISPLAY_OFF }, | 141 | { KE_KEY, 0x1a, { KEY_COFFEE } }, |
140 | {KE_KEY, 0x1a, KEY_COFFEE }, | 142 | { KE_KEY, 0x1b, { KEY_ZOOM } }, |
141 | {KE_KEY, 0x1b, KEY_ZOOM }, | 143 | { KE_KEY, 0x1c, { KEY_PROG2 } }, |
142 | {KE_KEY, 0x1c, KEY_PROG2 }, | 144 | { KE_KEY, 0x1d, { KEY_PROG3 } }, |
143 | {KE_KEY, 0x1d, KEY_PROG3 }, | 145 | { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } }, |
144 | {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, | 146 | { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } }, |
145 | {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, | 147 | { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, |
146 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, | 148 | { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, |
147 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, | 149 | { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, |
148 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, | 150 | { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ |
149 | {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ | 151 | { KE_KEY, 0x38, { KEY_F14 } }, |
150 | {KE_KEY, 0x38, KEY_F14 }, | 152 | { KE_END, 0 }, |
151 | {KE_END, 0}, | ||
152 | }; | 153 | }; |
153 | 154 | ||
154 | |||
155 | /* | 155 | /* |
156 | * This is the main structure, we can use it to store useful information | 156 | * This is the main structure, we can use it to store useful information |
157 | */ | 157 | */ |
@@ -159,6 +159,8 @@ struct eeepc_laptop { | |||
159 | acpi_handle handle; /* the handle of the acpi device */ | 159 | acpi_handle handle; /* the handle of the acpi device */ |
160 | u32 cm_supported; /* the control methods supported | 160 | u32 cm_supported; /* the control methods supported |
161 | by this BIOS */ | 161 | by this BIOS */ |
162 | bool cpufv_disabled; | ||
163 | bool hotplug_disabled; | ||
162 | u16 event_count[128]; /* count for each event */ | 164 | u16 event_count[128]; /* count for each event */ |
163 | 165 | ||
164 | struct platform_device *platform_device; | 166 | struct platform_device *platform_device; |
@@ -378,6 +380,8 @@ static ssize_t store_cpufv(struct device *dev, | |||
378 | struct eeepc_cpufv c; | 380 | struct eeepc_cpufv c; |
379 | int rv, value; | 381 | int rv, value; |
380 | 382 | ||
383 | if (eeepc->cpufv_disabled) | ||
384 | return -EPERM; | ||
381 | if (get_cpufv(eeepc, &c)) | 385 | if (get_cpufv(eeepc, &c)) |
382 | return -ENODEV; | 386 | return -ENODEV; |
383 | rv = parse_arg(buf, count, &value); | 387 | rv = parse_arg(buf, count, &value); |
@@ -389,6 +393,41 @@ static ssize_t store_cpufv(struct device *dev, | |||
389 | return rv; | 393 | return rv; |
390 | } | 394 | } |
391 | 395 | ||
396 | static ssize_t show_cpufv_disabled(struct device *dev, | ||
397 | struct device_attribute *attr, | ||
398 | char *buf) | ||
399 | { | ||
400 | struct eeepc_laptop *eeepc = dev_get_drvdata(dev); | ||
401 | |||
402 | return sprintf(buf, "%d\n", eeepc->cpufv_disabled); | ||
403 | } | ||
404 | |||
405 | static ssize_t store_cpufv_disabled(struct device *dev, | ||
406 | struct device_attribute *attr, | ||
407 | const char *buf, size_t count) | ||
408 | { | ||
409 | struct eeepc_laptop *eeepc = dev_get_drvdata(dev); | ||
410 | int rv, value; | ||
411 | |||
412 | rv = parse_arg(buf, count, &value); | ||
413 | if (rv < 0) | ||
414 | return rv; | ||
415 | |||
416 | switch (value) { | ||
417 | case 0: | ||
418 | if (eeepc->cpufv_disabled) | ||
419 | pr_warning("cpufv enabled (not officially supported " | ||
420 | "on this model)\n"); | ||
421 | eeepc->cpufv_disabled = false; | ||
422 | return rv; | ||
423 | case 1: | ||
424 | return -EPERM; | ||
425 | default: | ||
426 | return -EINVAL; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | |||
392 | static struct device_attribute dev_attr_cpufv = { | 431 | static struct device_attribute dev_attr_cpufv = { |
393 | .attr = { | 432 | .attr = { |
394 | .name = "cpufv", | 433 | .name = "cpufv", |
@@ -404,12 +443,22 @@ static struct device_attribute dev_attr_available_cpufv = { | |||
404 | .show = show_available_cpufv | 443 | .show = show_available_cpufv |
405 | }; | 444 | }; |
406 | 445 | ||
446 | static struct device_attribute dev_attr_cpufv_disabled = { | ||
447 | .attr = { | ||
448 | .name = "cpufv_disabled", | ||
449 | .mode = 0644 }, | ||
450 | .show = show_cpufv_disabled, | ||
451 | .store = store_cpufv_disabled | ||
452 | }; | ||
453 | |||
454 | |||
407 | static struct attribute *platform_attributes[] = { | 455 | static struct attribute *platform_attributes[] = { |
408 | &dev_attr_camera.attr, | 456 | &dev_attr_camera.attr, |
409 | &dev_attr_cardr.attr, | 457 | &dev_attr_cardr.attr, |
410 | &dev_attr_disp.attr, | 458 | &dev_attr_disp.attr, |
411 | &dev_attr_cpufv.attr, | 459 | &dev_attr_cpufv.attr, |
412 | &dev_attr_available_cpufv.attr, | 460 | &dev_attr_available_cpufv.attr, |
461 | &dev_attr_cpufv_disabled.attr, | ||
413 | NULL | 462 | NULL |
414 | }; | 463 | }; |
415 | 464 | ||
@@ -796,6 +845,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) | |||
796 | if (result && result != -ENODEV) | 845 | if (result && result != -ENODEV) |
797 | goto exit; | 846 | goto exit; |
798 | 847 | ||
848 | if (eeepc->hotplug_disabled) | ||
849 | return 0; | ||
850 | |||
799 | result = eeepc_setup_pci_hotplug(eeepc); | 851 | result = eeepc_setup_pci_hotplug(eeepc); |
800 | /* | 852 | /* |
801 | * If we get -EBUSY then something else is handling the PCI hotplug - | 853 | * If we get -EBUSY then something else is handling the PCI hotplug - |
@@ -1090,120 +1142,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) | |||
1090 | /* | 1142 | /* |
1091 | * Input device (i.e. hotkeys) | 1143 | * Input device (i.e. hotkeys) |
1092 | */ | 1144 | */ |
1093 | static struct key_entry *eeepc_get_entry_by_scancode( | 1145 | static int eeepc_input_init(struct eeepc_laptop *eeepc) |
1094 | struct eeepc_laptop *eeepc, | ||
1095 | int code) | ||
1096 | { | 1146 | { |
1097 | struct key_entry *key; | 1147 | struct input_dev *input; |
1148 | int error; | ||
1098 | 1149 | ||
1099 | for (key = eeepc->keymap; key->type != KE_END; key++) | 1150 | input = input_allocate_device(); |
1100 | if (code == key->code) | 1151 | if (!input) { |
1101 | return key; | 1152 | pr_info("Unable to allocate input device\n"); |
1102 | 1153 | return -ENOMEM; | |
1103 | return NULL; | ||
1104 | } | ||
1105 | |||
1106 | static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) | ||
1107 | { | ||
1108 | static struct key_entry *key; | ||
1109 | |||
1110 | key = eeepc_get_entry_by_scancode(eeepc, event); | ||
1111 | if (key) { | ||
1112 | switch (key->type) { | ||
1113 | case KE_KEY: | ||
1114 | input_report_key(eeepc->inputdev, key->keycode, | ||
1115 | 1); | ||
1116 | input_sync(eeepc->inputdev); | ||
1117 | input_report_key(eeepc->inputdev, key->keycode, | ||
1118 | 0); | ||
1119 | input_sync(eeepc->inputdev); | ||
1120 | break; | ||
1121 | } | ||
1122 | } | 1154 | } |
1123 | } | ||
1124 | |||
1125 | static struct key_entry *eeepc_get_entry_by_keycode( | ||
1126 | struct eeepc_laptop *eeepc, int code) | ||
1127 | { | ||
1128 | struct key_entry *key; | ||
1129 | |||
1130 | for (key = eeepc->keymap; key->type != KE_END; key++) | ||
1131 | if (code == key->keycode && key->type == KE_KEY) | ||
1132 | return key; | ||
1133 | 1155 | ||
1134 | return NULL; | 1156 | input->name = "Asus EeePC extra buttons"; |
1135 | } | 1157 | input->phys = EEEPC_LAPTOP_FILE "/input0"; |
1158 | input->id.bustype = BUS_HOST; | ||
1159 | input->dev.parent = &eeepc->platform_device->dev; | ||
1136 | 1160 | ||
1137 | static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) | 1161 | error = sparse_keymap_setup(input, eeepc_keymap, NULL); |
1138 | { | 1162 | if (error) { |
1139 | struct eeepc_laptop *eeepc = input_get_drvdata(dev); | 1163 | pr_err("Unable to setup input device keymap\n"); |
1140 | struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); | 1164 | goto err_free_dev; |
1141 | |||
1142 | if (key && key->type == KE_KEY) { | ||
1143 | *keycode = key->keycode; | ||
1144 | return 0; | ||
1145 | } | 1165 | } |
1146 | 1166 | ||
1147 | return -EINVAL; | 1167 | error = input_register_device(input); |
1148 | } | 1168 | if (error) { |
1149 | 1169 | pr_err("Unable to register input device\n"); | |
1150 | static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | 1170 | goto err_free_keymap; |
1151 | { | ||
1152 | struct eeepc_laptop *eeepc = input_get_drvdata(dev); | ||
1153 | struct key_entry *key; | ||
1154 | int old_keycode; | ||
1155 | |||
1156 | if (keycode < 0 || keycode > KEY_MAX) | ||
1157 | return -EINVAL; | ||
1158 | |||
1159 | key = eeepc_get_entry_by_scancode(eeepc, scancode); | ||
1160 | if (key && key->type == KE_KEY) { | ||
1161 | old_keycode = key->keycode; | ||
1162 | key->keycode = keycode; | ||
1163 | set_bit(keycode, dev->keybit); | ||
1164 | if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) | ||
1165 | clear_bit(old_keycode, dev->keybit); | ||
1166 | return 0; | ||
1167 | } | 1171 | } |
1168 | 1172 | ||
1169 | return -EINVAL; | 1173 | eeepc->inputdev = input; |
1170 | } | ||
1171 | |||
1172 | static int eeepc_input_init(struct eeepc_laptop *eeepc) | ||
1173 | { | ||
1174 | const struct key_entry *key; | ||
1175 | int result; | ||
1176 | |||
1177 | eeepc->inputdev = input_allocate_device(); | ||
1178 | if (!eeepc->inputdev) { | ||
1179 | pr_info("Unable to allocate input device\n"); | ||
1180 | return -ENOMEM; | ||
1181 | } | ||
1182 | eeepc->inputdev->name = "Asus EeePC extra buttons"; | ||
1183 | eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; | ||
1184 | eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; | ||
1185 | eeepc->inputdev->id.bustype = BUS_HOST; | ||
1186 | eeepc->inputdev->getkeycode = eeepc_getkeycode; | ||
1187 | eeepc->inputdev->setkeycode = eeepc_setkeycode; | ||
1188 | input_set_drvdata(eeepc->inputdev, eeepc); | ||
1189 | |||
1190 | eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), | ||
1191 | GFP_KERNEL); | ||
1192 | for (key = eeepc_keymap; key->type != KE_END; key++) { | ||
1193 | switch (key->type) { | ||
1194 | case KE_KEY: | ||
1195 | set_bit(EV_KEY, eeepc->inputdev->evbit); | ||
1196 | set_bit(key->keycode, eeepc->inputdev->keybit); | ||
1197 | break; | ||
1198 | } | ||
1199 | } | ||
1200 | result = input_register_device(eeepc->inputdev); | ||
1201 | if (result) { | ||
1202 | pr_info("Unable to register input device\n"); | ||
1203 | input_free_device(eeepc->inputdev); | ||
1204 | return result; | ||
1205 | } | ||
1206 | return 0; | 1174 | return 0; |
1175 | |||
1176 | err_free_keymap: | ||
1177 | sparse_keymap_free(input); | ||
1178 | err_free_dev: | ||
1179 | input_free_device(input); | ||
1180 | return error; | ||
1207 | } | 1181 | } |
1208 | 1182 | ||
1209 | static void eeepc_input_exit(struct eeepc_laptop *eeepc) | 1183 | static void eeepc_input_exit(struct eeepc_laptop *eeepc) |
@@ -1253,11 +1227,59 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) | |||
1253 | * event will be desired value (or else ignored) | 1227 | * event will be desired value (or else ignored) |
1254 | */ | 1228 | */ |
1255 | } | 1229 | } |
1256 | eeepc_input_notify(eeepc, event); | 1230 | sparse_keymap_report_event(eeepc->inputdev, event, |
1231 | 1, true); | ||
1257 | } | 1232 | } |
1258 | } else { | 1233 | } else { |
1259 | /* Everything else is a bona-fide keypress event */ | 1234 | /* Everything else is a bona-fide keypress event */ |
1260 | eeepc_input_notify(eeepc, event); | 1235 | sparse_keymap_report_event(eeepc->inputdev, event, 1, true); |
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | static void eeepc_dmi_check(struct eeepc_laptop *eeepc) | ||
1240 | { | ||
1241 | const char *model; | ||
1242 | |||
1243 | model = dmi_get_system_info(DMI_PRODUCT_NAME); | ||
1244 | if (!model) | ||
1245 | return; | ||
1246 | |||
1247 | /* | ||
1248 | * Blacklist for setting cpufv (cpu speed). | ||
1249 | * | ||
1250 | * EeePC 4G ("701") implements CFVS, but it is not supported | ||
1251 | * by the pre-installed OS, and the original option to change it | ||
1252 | * in the BIOS setup screen was removed in later versions. | ||
1253 | * | ||
1254 | * Judging by the lack of "Super Hybrid Engine" on Asus product pages, | ||
1255 | * this applies to all "701" models (4G/4G Surf/2G Surf). | ||
1256 | * | ||
1257 | * So Asus made a deliberate decision not to support it on this model. | ||
1258 | * We have several reports that using it can cause the system to hang | ||
1259 | * | ||
1260 | * The hang has also been reported on a "702" (Model name "8G"?). | ||
1261 | * | ||
1262 | * We avoid dmi_check_system() / dmi_match(), because they use | ||
1263 | * substring matching. We don't want to affect the "701SD" | ||
1264 | * and "701SDX" models, because they do support S.H.E. | ||
1265 | */ | ||
1266 | if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { | ||
1267 | eeepc->cpufv_disabled = true; | ||
1268 | pr_info("model %s does not officially support setting cpu " | ||
1269 | "speed\n", model); | ||
1270 | pr_info("cpufv disabled to avoid instability\n"); | ||
1271 | } | ||
1272 | |||
1273 | /* | ||
1274 | * Blacklist for wlan hotplug | ||
1275 | * | ||
1276 | * Eeepc 1005HA doesn't work like others models and don't need the | ||
1277 | * hotplug code. In fact, current hotplug code seems to unplug another | ||
1278 | * device... | ||
1279 | */ | ||
1280 | if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { | ||
1281 | eeepc->hotplug_disabled = true; | ||
1282 | pr_info("wlan hotplug disabled\n"); | ||
1261 | } | 1283 | } |
1262 | } | 1284 | } |
1263 | 1285 | ||
@@ -1342,6 +1364,10 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) | |||
1342 | strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); | 1364 | strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); |
1343 | device->driver_data = eeepc; | 1365 | device->driver_data = eeepc; |
1344 | 1366 | ||
1367 | eeepc->hotplug_disabled = hotplug_disabled; | ||
1368 | |||
1369 | eeepc_dmi_check(eeepc); | ||
1370 | |||
1345 | result = eeepc_acpi_init(eeepc, device); | 1371 | result = eeepc_acpi_init(eeepc, device); |
1346 | if (result) | 1372 | if (result) |
1347 | goto fail_platform; | 1373 | goto fail_platform; |
@@ -1452,10 +1478,12 @@ static int __init eeepc_laptop_init(void) | |||
1452 | result = acpi_bus_register_driver(&eeepc_acpi_driver); | 1478 | result = acpi_bus_register_driver(&eeepc_acpi_driver); |
1453 | if (result < 0) | 1479 | if (result < 0) |
1454 | goto fail_acpi_driver; | 1480 | goto fail_acpi_driver; |
1481 | |||
1455 | if (!eeepc_device_present) { | 1482 | if (!eeepc_device_present) { |
1456 | result = -ENODEV; | 1483 | result = -ENODEV; |
1457 | goto fail_no_device; | 1484 | goto fail_no_device; |
1458 | } | 1485 | } |
1486 | |||
1459 | return 0; | 1487 | return 0; |
1460 | 1488 | ||
1461 | fail_no_device: | 1489 | fail_no_device: |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 5af53340da6f..3f71a605a492 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -1201,9 +1201,12 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) | |||
1201 | /* the buffer is filled with magic numbers describing the devices | 1201 | /* the buffer is filled with magic numbers describing the devices |
1202 | * available, 0xff terminates the enumeration | 1202 | * available, 0xff terminates the enumeration |
1203 | */ | 1203 | */ |
1204 | while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && | 1204 | for (i = 0; i < device_enum->buffer.length; i++) { |
1205 | i < device_enum->buffer.length) { | 1205 | |
1206 | i++; | 1206 | dev_code = *(device_enum->buffer.pointer + i); |
1207 | if (dev_code == 0xff) | ||
1208 | break; | ||
1209 | |||
1207 | dprintk("Radio devices, looking at 0x%.2x\n", dev_code); | 1210 | dprintk("Radio devices, looking at 0x%.2x\n", dev_code); |
1208 | 1211 | ||
1209 | if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) | 1212 | if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) |
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 9d7febde10a1..09469971472f 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h | |||
@@ -152,7 +152,7 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) | |||
152 | #include <linux/hardirq.h> | 152 | #include <linux/hardirq.h> |
153 | #define ACPI_PREEMPTION_POINT() \ | 153 | #define ACPI_PREEMPTION_POINT() \ |
154 | do { \ | 154 | do { \ |
155 | if (!in_atomic_preempt_off()) \ | 155 | if (!in_atomic_preempt_off() && !irqs_disabled()) \ |
156 | cond_resched(); \ | 156 | cond_resched(); \ |
157 | } while (0) | 157 | } while (0) |
158 | 158 | ||
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 36924255c0d5..b926afe8c03e 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -80,7 +80,7 @@ char * __acpi_map_table (unsigned long phys_addr, unsigned long size); | |||
80 | void __acpi_unmap_table(char *map, unsigned long size); | 80 | void __acpi_unmap_table(char *map, unsigned long size); |
81 | int early_acpi_boot_init(void); | 81 | int early_acpi_boot_init(void); |
82 | int acpi_boot_init (void); | 82 | int acpi_boot_init (void); |
83 | int acpi_boot_table_init (void); | 83 | void acpi_boot_table_init (void); |
84 | int acpi_mps_check (void); | 84 | int acpi_mps_check (void); |
85 | int acpi_numa_init (void); | 85 | int acpi_numa_init (void); |
86 | 86 | ||
@@ -321,9 +321,9 @@ static inline int acpi_boot_init(void) | |||
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
323 | 323 | ||
324 | static inline int acpi_boot_table_init(void) | 324 | static inline void acpi_boot_table_init(void) |
325 | { | 325 | { |
326 | return 0; | 326 | return; |
327 | } | 327 | } |
328 | 328 | ||
329 | static inline int acpi_mps_check(void) | 329 | static inline int acpi_mps_check(void) |