diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-05 16:24:19 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-10-05 16:24:19 -0400 |
commit | 939558f2a4b7851c11ce8d08387730914a1e1f5f (patch) | |
tree | 4013f9577fe56da1fd3f8cc49b0de790b0e85c4f /drivers/acpi | |
parent | 65e8627aad0b9ef24d282296f4d3a1638a2438e6 (diff) | |
parent | 5159e39bdf119613adc6556901ae2d2e5e027551 (diff) |
Merge branch 'acpi-apple'
* acpi-apple:
ACPI / SBS: Fix check in acpi_ac_get_present()
ACPI: Support _OSI("Darwin") correctly
ACPI / SBS: Disable smart battery manager on Apple
ACPI / SBS: Don't assume the existence of an SBS charger
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/osl.c | 10 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 14 | ||||
-rw-r--r-- | drivers/acpi/sbs.c | 80 |
3 files changed, 89 insertions, 15 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 3abe9b223ba7..938b6ac71dde 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -152,6 +152,16 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported) | |||
152 | osi_linux.dmi ? " via DMI" : ""); | 152 | osi_linux.dmi ? " via DMI" : ""); |
153 | } | 153 | } |
154 | 154 | ||
155 | if (!strcmp("Darwin", interface)) { | ||
156 | /* | ||
157 | * Apple firmware will behave poorly if it receives positive | ||
158 | * answers to "Darwin" and any other OS. Respond positively | ||
159 | * to Darwin and then disable all other vendor strings. | ||
160 | */ | ||
161 | acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS); | ||
162 | supported = ACPI_UINT32_MAX; | ||
163 | } | ||
164 | |||
155 | return supported; | 165 | return supported; |
156 | } | 166 | } |
157 | 167 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index e6ae603ed1a1..cd4de7e038ea 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/pci-aspm.h> | 35 | #include <linux/pci-aspm.h> |
36 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/dmi.h> | ||
38 | #include <acpi/apei.h> /* for acpi_hest_init() */ | 39 | #include <acpi/apei.h> /* for acpi_hest_init() */ |
39 | 40 | ||
40 | #include "internal.h" | 41 | #include "internal.h" |
@@ -430,6 +431,19 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, | |||
430 | acpi_handle handle = device->handle; | 431 | acpi_handle handle = device->handle; |
431 | 432 | ||
432 | /* | 433 | /* |
434 | * Apple always return failure on _OSC calls when _OSI("Darwin") has | ||
435 | * been called successfully. We know the feature set supported by the | ||
436 | * platform, so avoid calling _OSC at all | ||
437 | */ | ||
438 | |||
439 | if (dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) { | ||
440 | root->osc_control_set = ~OSC_PCI_EXPRESS_PME_CONTROL; | ||
441 | decode_osc_control(root, "OS assumes control of", | ||
442 | root->osc_control_set); | ||
443 | return; | ||
444 | } | ||
445 | |||
446 | /* | ||
433 | * All supported architectures that use ACPI have support for | 447 | * All supported architectures that use ACPI have support for |
434 | * PCI domains, so we indicate this in _OSC support capabilities. | 448 | * PCI domains, so we indicate this in _OSC support capabilities. |
435 | */ | 449 | */ |
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 366ca40a6f70..a7a3edd28beb 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/power_supply.h> | 37 | #include <linux/power_supply.h> |
38 | #include <linux/dmi.h> | ||
38 | 39 | ||
39 | #include "sbshc.h" | 40 | #include "sbshc.h" |
40 | #include "battery.h" | 41 | #include "battery.h" |
@@ -61,6 +62,8 @@ static unsigned int cache_time = 1000; | |||
61 | module_param(cache_time, uint, 0644); | 62 | module_param(cache_time, uint, 0644); |
62 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); | 63 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
63 | 64 | ||
65 | static bool sbs_manager_broken; | ||
66 | |||
64 | #define MAX_SBS_BAT 4 | 67 | #define MAX_SBS_BAT 4 |
65 | #define ACPI_SBS_BLOCK_MAX 32 | 68 | #define ACPI_SBS_BLOCK_MAX 32 |
66 | 69 | ||
@@ -109,6 +112,7 @@ struct acpi_sbs { | |||
109 | u8 batteries_supported:4; | 112 | u8 batteries_supported:4; |
110 | u8 manager_present:1; | 113 | u8 manager_present:1; |
111 | u8 charger_present:1; | 114 | u8 charger_present:1; |
115 | u8 charger_exists:1; | ||
112 | }; | 116 | }; |
113 | 117 | ||
114 | #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) | 118 | #define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) |
@@ -429,9 +433,19 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) | |||
429 | 433 | ||
430 | result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, | 434 | result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, |
431 | 0x13, (u8 *) & status); | 435 | 0x13, (u8 *) & status); |
432 | if (!result) | 436 | |
433 | sbs->charger_present = (status >> 15) & 0x1; | 437 | if (result) |
434 | return result; | 438 | return result; |
439 | |||
440 | /* | ||
441 | * The spec requires that bit 4 always be 1. If it's not set, assume | ||
442 | * that the implementation doesn't support an SBS charger | ||
443 | */ | ||
444 | if (!((status >> 4) & 0x1)) | ||
445 | return -ENODEV; | ||
446 | |||
447 | sbs->charger_present = (status >> 15) & 0x1; | ||
448 | return 0; | ||
435 | } | 449 | } |
436 | 450 | ||
437 | static ssize_t acpi_battery_alarm_show(struct device *dev, | 451 | static ssize_t acpi_battery_alarm_show(struct device *dev, |
@@ -483,16 +497,21 @@ static int acpi_battery_read(struct acpi_battery *battery) | |||
483 | ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); | 497 | ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); |
484 | } else if (battery->id == 0) | 498 | } else if (battery->id == 0) |
485 | battery->present = 1; | 499 | battery->present = 1; |
500 | |||
486 | if (result || !battery->present) | 501 | if (result || !battery->present) |
487 | return result; | 502 | return result; |
488 | 503 | ||
489 | if (saved_present != battery->present) { | 504 | if (saved_present != battery->present) { |
490 | battery->update_time = 0; | 505 | battery->update_time = 0; |
491 | result = acpi_battery_get_info(battery); | 506 | result = acpi_battery_get_info(battery); |
492 | if (result) | 507 | if (result) { |
508 | battery->present = 0; | ||
493 | return result; | 509 | return result; |
510 | } | ||
494 | } | 511 | } |
495 | result = acpi_battery_get_state(battery); | 512 | result = acpi_battery_get_state(battery); |
513 | if (result) | ||
514 | battery->present = 0; | ||
496 | return result; | 515 | return result; |
497 | } | 516 | } |
498 | 517 | ||
@@ -524,6 +543,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
524 | result = power_supply_register(&sbs->device->dev, &battery->bat); | 543 | result = power_supply_register(&sbs->device->dev, &battery->bat); |
525 | if (result) | 544 | if (result) |
526 | goto end; | 545 | goto end; |
546 | |||
527 | result = device_create_file(battery->bat.dev, &alarm_attr); | 547 | result = device_create_file(battery->bat.dev, &alarm_attr); |
528 | if (result) | 548 | if (result) |
529 | goto end; | 549 | goto end; |
@@ -554,6 +574,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) | |||
554 | if (result) | 574 | if (result) |
555 | goto end; | 575 | goto end; |
556 | 576 | ||
577 | sbs->charger_exists = 1; | ||
557 | sbs->charger.name = "sbs-charger"; | 578 | sbs->charger.name = "sbs-charger"; |
558 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; | 579 | sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; |
559 | sbs->charger.properties = sbs_ac_props; | 580 | sbs->charger.properties = sbs_ac_props; |
@@ -580,9 +601,12 @@ static void acpi_sbs_callback(void *context) | |||
580 | struct acpi_battery *bat; | 601 | struct acpi_battery *bat; |
581 | u8 saved_charger_state = sbs->charger_present; | 602 | u8 saved_charger_state = sbs->charger_present; |
582 | u8 saved_battery_state; | 603 | u8 saved_battery_state; |
583 | acpi_ac_get_present(sbs); | 604 | |
584 | if (sbs->charger_present != saved_charger_state) | 605 | if (sbs->charger_exists) { |
585 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); | 606 | acpi_ac_get_present(sbs); |
607 | if (sbs->charger_present != saved_charger_state) | ||
608 | kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); | ||
609 | } | ||
586 | 610 | ||
587 | if (sbs->manager_present) { | 611 | if (sbs->manager_present) { |
588 | for (id = 0; id < MAX_SBS_BAT; ++id) { | 612 | for (id = 0; id < MAX_SBS_BAT; ++id) { |
@@ -598,12 +622,31 @@ static void acpi_sbs_callback(void *context) | |||
598 | } | 622 | } |
599 | } | 623 | } |
600 | 624 | ||
625 | static int disable_sbs_manager(const struct dmi_system_id *d) | ||
626 | { | ||
627 | sbs_manager_broken = true; | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static struct dmi_system_id acpi_sbs_dmi_table[] = { | ||
632 | { | ||
633 | .callback = disable_sbs_manager, | ||
634 | .ident = "Apple", | ||
635 | .matches = { | ||
636 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc.") | ||
637 | }, | ||
638 | }, | ||
639 | { }, | ||
640 | }; | ||
641 | |||
601 | static int acpi_sbs_add(struct acpi_device *device) | 642 | static int acpi_sbs_add(struct acpi_device *device) |
602 | { | 643 | { |
603 | struct acpi_sbs *sbs; | 644 | struct acpi_sbs *sbs; |
604 | int result = 0; | 645 | int result = 0; |
605 | int id; | 646 | int id; |
606 | 647 | ||
648 | dmi_check_system(acpi_sbs_dmi_table); | ||
649 | |||
607 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); | 650 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); |
608 | if (!sbs) { | 651 | if (!sbs) { |
609 | result = -ENOMEM; | 652 | result = -ENOMEM; |
@@ -619,17 +662,24 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
619 | device->driver_data = sbs; | 662 | device->driver_data = sbs; |
620 | 663 | ||
621 | result = acpi_charger_add(sbs); | 664 | result = acpi_charger_add(sbs); |
622 | if (result) | 665 | if (result && result != -ENODEV) |
623 | goto end; | 666 | goto end; |
624 | 667 | ||
625 | result = acpi_manager_get_info(sbs); | 668 | result = 0; |
626 | if (!result) { | 669 | |
627 | sbs->manager_present = 1; | 670 | if (!sbs_manager_broken) { |
628 | for (id = 0; id < MAX_SBS_BAT; ++id) | 671 | result = acpi_manager_get_info(sbs); |
629 | if ((sbs->batteries_supported & (1 << id))) | 672 | if (!result) { |
630 | acpi_battery_add(sbs, id); | 673 | sbs->manager_present = 0; |
631 | } else | 674 | for (id = 0; id < MAX_SBS_BAT; ++id) |
675 | if ((sbs->batteries_supported & (1 << id))) | ||
676 | acpi_battery_add(sbs, id); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | if (!sbs->manager_present) | ||
632 | acpi_battery_add(sbs, 0); | 681 | acpi_battery_add(sbs, 0); |
682 | |||
633 | acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); | 683 | acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); |
634 | end: | 684 | end: |
635 | if (result) | 685 | if (result) |