aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/osl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/osl.c')
-rw-r--r--drivers/acpi/osl.c162
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);
111static DEFINE_SPINLOCK(acpi_ioremap_lock); 111static DEFINE_SPINLOCK(acpi_ioremap_lock);
112 112
113#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 113#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
114static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 114static char osi_setup_string[OSI_STRING_LENGTH_MAX];
115
116static 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
158static 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
156static void __init acpi_request_region (struct acpi_generic_address *addr, 172static 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
693acpi_status 709acpi_status
694acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg, 710acpi_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 */
751static 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
808void 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
818static void acpi_os_execute_deferred(struct work_struct *work) 768static 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 */
1159int __init acpi_osi_setup(char *str) 1115static 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
1135int __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
1443acpi_status
1444acpi_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
1462static inline int acpi_res_list_add(struct acpi_res_list *res) 1398static 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