diff options
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r-- | drivers/acpi/osl.c | 162 |
1 files changed, 50 insertions, 112 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 885e222bcabd..0c2e445410ab 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -111,7 +111,9 @@ static LIST_HEAD(acpi_ioremaps); | |||
111 | static DEFINE_SPINLOCK(acpi_ioremap_lock); | 111 | static DEFINE_SPINLOCK(acpi_ioremap_lock); |
112 | 112 | ||
113 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | 113 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
114 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; | 114 | static char osi_setup_string[OSI_STRING_LENGTH_MAX]; |
115 | |||
116 | static void __init acpi_osi_setup_late(void); | ||
115 | 117 | ||
116 | /* | 118 | /* |
117 | * The story of _OSI(Linux) | 119 | * The story of _OSI(Linux) |
@@ -153,6 +155,20 @@ static struct osi_linux { | |||
153 | unsigned int known:1; | 155 | unsigned int known:1; |
154 | } osi_linux = { 0, 0, 0, 0}; | 156 | } osi_linux = { 0, 0, 0, 0}; |
155 | 157 | ||
158 | static u32 acpi_osi_handler(acpi_string interface, u32 supported) | ||
159 | { | ||
160 | if (!strcmp("Linux", interface)) { | ||
161 | |||
162 | printk(KERN_NOTICE FW_BUG PREFIX | ||
163 | "BIOS _OSI(Linux) query %s%s\n", | ||
164 | osi_linux.enable ? "honored" : "ignored", | ||
165 | osi_linux.cmdline ? " via cmdline" : | ||
166 | osi_linux.dmi ? " via DMI" : ""); | ||
167 | } | ||
168 | |||
169 | return supported; | ||
170 | } | ||
171 | |||
156 | static void __init acpi_request_region (struct acpi_generic_address *addr, | 172 | static void __init acpi_request_region (struct acpi_generic_address *addr, |
157 | unsigned int length, char *desc) | 173 | unsigned int length, char *desc) |
158 | { | 174 | { |
@@ -692,9 +708,10 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) | |||
692 | 708 | ||
693 | acpi_status | 709 | acpi_status |
694 | acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, | 710 | acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, |
695 | u32 *value, u32 width) | 711 | u64 *value, u32 width) |
696 | { | 712 | { |
697 | int result, size; | 713 | int result, size; |
714 | u32 value32; | ||
698 | 715 | ||
699 | if (!value) | 716 | if (!value) |
700 | return AE_BAD_PARAMETER; | 717 | return AE_BAD_PARAMETER; |
@@ -715,7 +732,8 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, | |||
715 | 732 | ||
716 | result = raw_pci_read(pci_id->segment, pci_id->bus, | 733 | result = raw_pci_read(pci_id->segment, pci_id->bus, |
717 | PCI_DEVFN(pci_id->device, pci_id->function), | 734 | PCI_DEVFN(pci_id->device, pci_id->function), |
718 | reg, size, value); | 735 | reg, size, &value32); |
736 | *value = value32; | ||
719 | 737 | ||
720 | return (result ? AE_ERROR : AE_OK); | 738 | return (result ? AE_ERROR : AE_OK); |
721 | } | 739 | } |
@@ -747,74 +765,6 @@ acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, | |||
747 | return (result ? AE_ERROR : AE_OK); | 765 | return (result ? AE_ERROR : AE_OK); |
748 | } | 766 | } |
749 | 767 | ||
750 | /* TODO: Change code to take advantage of driver model more */ | ||
751 | static void acpi_os_derive_pci_id_2(acpi_handle rhandle, /* upper bound */ | ||
752 | acpi_handle chandle, /* current node */ | ||
753 | struct acpi_pci_id **id, | ||
754 | int *is_bridge, u8 * bus_number) | ||
755 | { | ||
756 | acpi_handle handle; | ||
757 | struct acpi_pci_id *pci_id = *id; | ||
758 | acpi_status status; | ||
759 | unsigned long long temp; | ||
760 | acpi_object_type type; | ||
761 | |||
762 | acpi_get_parent(chandle, &handle); | ||
763 | if (handle != rhandle) { | ||
764 | acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge, | ||
765 | bus_number); | ||
766 | |||
767 | status = acpi_get_type(handle, &type); | ||
768 | if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE)) | ||
769 | return; | ||
770 | |||
771 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, | ||
772 | &temp); | ||
773 | if (ACPI_SUCCESS(status)) { | ||
774 | u32 val; | ||
775 | pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp)); | ||
776 | pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp)); | ||
777 | |||
778 | if (*is_bridge) | ||
779 | pci_id->bus = *bus_number; | ||
780 | |||
781 | /* any nicer way to get bus number of bridge ? */ | ||
782 | status = | ||
783 | acpi_os_read_pci_configuration(pci_id, 0x0e, &val, | ||
784 | 8); | ||
785 | if (ACPI_SUCCESS(status) | ||
786 | && ((val & 0x7f) == 1 || (val & 0x7f) == 2)) { | ||
787 | status = | ||
788 | acpi_os_read_pci_configuration(pci_id, 0x18, | ||
789 | &val, 8); | ||
790 | if (!ACPI_SUCCESS(status)) { | ||
791 | /* Certainly broken... FIX ME */ | ||
792 | return; | ||
793 | } | ||
794 | *is_bridge = 1; | ||
795 | pci_id->bus = val; | ||
796 | status = | ||
797 | acpi_os_read_pci_configuration(pci_id, 0x19, | ||
798 | &val, 8); | ||
799 | if (ACPI_SUCCESS(status)) { | ||
800 | *bus_number = val; | ||
801 | } | ||
802 | } else | ||
803 | *is_bridge = 0; | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ | ||
809 | acpi_handle chandle, /* current node */ | ||
810 | struct acpi_pci_id **id) | ||
811 | { | ||
812 | int is_bridge = 1; | ||
813 | u8 bus_number = (*id)->bus; | ||
814 | |||
815 | acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number); | ||
816 | } | ||
817 | |||
818 | static void acpi_os_execute_deferred(struct work_struct *work) | 768 | static void acpi_os_execute_deferred(struct work_struct *work) |
819 | { | 769 | { |
820 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); | 770 | struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); |
@@ -1122,6 +1072,12 @@ static void __init set_osi_linux(unsigned int enable) | |||
1122 | printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", | 1072 | printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n", |
1123 | enable ? "Add": "Delet"); | 1073 | enable ? "Add": "Delet"); |
1124 | } | 1074 | } |
1075 | |||
1076 | if (osi_linux.enable) | ||
1077 | acpi_osi_setup("Linux"); | ||
1078 | else | ||
1079 | acpi_osi_setup("!Linux"); | ||
1080 | |||
1125 | return; | 1081 | return; |
1126 | } | 1082 | } |
1127 | 1083 | ||
@@ -1156,21 +1112,33 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d) | |||
1156 | * string starting with '!' disables that string | 1112 | * string starting with '!' disables that string |
1157 | * otherwise string is added to list, augmenting built-in strings | 1113 | * otherwise string is added to list, augmenting built-in strings |
1158 | */ | 1114 | */ |
1159 | int __init acpi_osi_setup(char *str) | 1115 | static void __init acpi_osi_setup_late(void) |
1160 | { | 1116 | { |
1161 | if (str == NULL || *str == '\0') { | 1117 | char *str = osi_setup_string; |
1162 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | 1118 | |
1163 | acpi_gbl_create_osi_method = FALSE; | 1119 | if (*str == '\0') |
1164 | } else if (!strcmp("!Linux", str)) { | 1120 | return; |
1121 | |||
1122 | if (!strcmp("!Linux", str)) { | ||
1165 | acpi_cmdline_osi_linux(0); /* !enable */ | 1123 | acpi_cmdline_osi_linux(0); /* !enable */ |
1166 | } else if (*str == '!') { | 1124 | } else if (*str == '!') { |
1167 | if (acpi_osi_invalidate(++str) == AE_OK) | 1125 | if (acpi_remove_interface(++str) == AE_OK) |
1168 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); | 1126 | printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str); |
1169 | } else if (!strcmp("Linux", str)) { | 1127 | } else if (!strcmp("Linux", str)) { |
1170 | acpi_cmdline_osi_linux(1); /* enable */ | 1128 | acpi_cmdline_osi_linux(1); /* enable */ |
1171 | } else if (*osi_additional_string == '\0') { | 1129 | } else { |
1172 | strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX); | 1130 | if (acpi_install_interface(str) == AE_OK) |
1173 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); | 1131 | printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str); |
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | int __init acpi_osi_setup(char *str) | ||
1136 | { | ||
1137 | if (str == NULL || *str == '\0') { | ||
1138 | printk(KERN_INFO PREFIX "_OSI method disabled\n"); | ||
1139 | acpi_gbl_create_osi_method = FALSE; | ||
1140 | } else { | ||
1141 | strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX); | ||
1174 | } | 1142 | } |
1175 | 1143 | ||
1176 | return 1; | 1144 | return 1; |
@@ -1427,38 +1395,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) | |||
1427 | return (AE_OK); | 1395 | return (AE_OK); |
1428 | } | 1396 | } |
1429 | 1397 | ||
1430 | /****************************************************************************** | ||
1431 | * | ||
1432 | * FUNCTION: acpi_os_validate_interface | ||
1433 | * | ||
1434 | * PARAMETERS: interface - Requested interface to be validated | ||
1435 | * | ||
1436 | * RETURN: AE_OK if interface is supported, AE_SUPPORT otherwise | ||
1437 | * | ||
1438 | * DESCRIPTION: Match an interface string to the interfaces supported by the | ||
1439 | * host. Strings originate from an AML call to the _OSI method. | ||
1440 | * | ||
1441 | *****************************************************************************/ | ||
1442 | |||
1443 | acpi_status | ||
1444 | acpi_os_validate_interface (char *interface) | ||
1445 | { | ||
1446 | if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX)) | ||
1447 | return AE_OK; | ||
1448 | if (!strcmp("Linux", interface)) { | ||
1449 | |||
1450 | printk(KERN_NOTICE PREFIX | ||
1451 | "BIOS _OSI(Linux) query %s%s\n", | ||
1452 | osi_linux.enable ? "honored" : "ignored", | ||
1453 | osi_linux.cmdline ? " via cmdline" : | ||
1454 | osi_linux.dmi ? " via DMI" : ""); | ||
1455 | |||
1456 | if (osi_linux.enable) | ||
1457 | return AE_OK; | ||
1458 | } | ||
1459 | return AE_SUPPORT; | ||
1460 | } | ||
1461 | |||
1462 | static inline int acpi_res_list_add(struct acpi_res_list *res) | 1398 | static inline int acpi_res_list_add(struct acpi_res_list *res) |
1463 | { | 1399 | { |
1464 | struct acpi_res_list *res_list_elem; | 1400 | struct acpi_res_list *res_list_elem; |
@@ -1627,6 +1563,8 @@ acpi_status acpi_os_initialize1(void) | |||
1627 | BUG_ON(!kacpid_wq); | 1563 | BUG_ON(!kacpid_wq); |
1628 | BUG_ON(!kacpi_notify_wq); | 1564 | BUG_ON(!kacpi_notify_wq); |
1629 | BUG_ON(!kacpi_hotplug_wq); | 1565 | BUG_ON(!kacpi_hotplug_wq); |
1566 | acpi_install_interface_handler(acpi_osi_handler); | ||
1567 | acpi_osi_setup_late(); | ||
1630 | return AE_OK; | 1568 | return AE_OK; |
1631 | } | 1569 | } |
1632 | 1570 | ||