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.c257
1 files changed, 209 insertions, 48 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 7fcacc5ed821..c2c585366fa6 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -44,6 +44,8 @@
44#include <asm/uaccess.h> 44#include <asm/uaccess.h>
45 45
46#include <linux/efi.h> 46#include <linux/efi.h>
47#include <linux/ioport.h>
48#include <linux/list.h>
47 49
48#define _COMPONENT ACPI_OS_SERVICES 50#define _COMPONENT ACPI_OS_SERVICES
49ACPI_MODULE_NAME("osl"); 51ACPI_MODULE_NAME("osl");
@@ -74,6 +76,18 @@ static void *acpi_irq_context;
74static struct workqueue_struct *kacpid_wq; 76static struct workqueue_struct *kacpid_wq;
75static struct workqueue_struct *kacpi_notify_wq; 77static struct workqueue_struct *kacpi_notify_wq;
76 78
79struct acpi_res_list {
80 resource_size_t start;
81 resource_size_t end;
82 acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
83 char name[5]; /* only can have a length of 4 chars, make use of this
84 one instead of res->name, no need to kalloc then */
85 struct list_head resource_list;
86};
87
88static LIST_HEAD(resource_list_head);
89static DEFINE_SPINLOCK(acpi_res_lock);
90
77#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 91#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
78static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 92static char osi_additional_string[OSI_STRING_LENGTH_MAX];
79 93
@@ -120,7 +134,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
120 */ 134 */
121#define OSI_LINUX_ENABLE 0 135#define OSI_LINUX_ENABLE 0
122 136
123struct osi_linux { 137static struct osi_linux {
124 unsigned int enable:1; 138 unsigned int enable:1;
125 unsigned int dmi:1; 139 unsigned int dmi:1;
126 unsigned int cmdline:1; 140 unsigned int cmdline:1;
@@ -248,11 +262,16 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
248 "System description tables not found\n"); 262 "System description tables not found\n");
249 return 0; 263 return 0;
250 } 264 }
251 } else 265 } else {
252 return acpi_find_rsdp(); 266 acpi_physical_address pa = 0;
267
268 acpi_find_root_pointer(&pa);
269 return pa;
270 }
253} 271}
254 272
255void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) 273void __iomem *__init_refok
274acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
256{ 275{
257 if (phys > ULONG_MAX) { 276 if (phys > ULONG_MAX) {
258 printk(KERN_ERR PREFIX "Cannot map memory that high\n"); 277 printk(KERN_ERR PREFIX "Cannot map memory that high\n");
@@ -330,7 +349,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
330 349
331static irqreturn_t acpi_irq(int irq, void *dev_id) 350static irqreturn_t acpi_irq(int irq, void *dev_id)
332{ 351{
333 return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; 352 u32 handled;
353
354 handled = (*acpi_irq_handler) (acpi_irq_context);
355
356 if (handled) {
357 acpi_irq_handled++;
358 return IRQ_HANDLED;
359 } else
360 return IRQ_NONE;
334} 361}
335 362
336acpi_status 363acpi_status
@@ -339,6 +366,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler,
339{ 366{
340 unsigned int irq; 367 unsigned int irq;
341 368
369 acpi_irq_stats_init();
370
342 /* 371 /*
343 * Ignore the GSI from the core, and use the value in our copy of the 372 * Ignore the GSI from the core, and use the value in our copy of the
344 * FADT. It may not be the same if an interrupt source override exists 373 * FADT. It may not be the same if an interrupt source override exists
@@ -653,25 +682,6 @@ static void acpi_os_execute_deferred(struct work_struct *work)
653 dpc->function(dpc->context); 682 dpc->function(dpc->context);
654 kfree(dpc); 683 kfree(dpc);
655 684
656 /* Yield cpu to notify thread */
657 cond_resched();
658
659 return;
660}
661
662static void acpi_os_execute_notify(struct work_struct *work)
663{
664 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
665
666 if (!dpc) {
667 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
668 return;
669 }
670
671 dpc->function(dpc->context);
672
673 kfree(dpc);
674
675 return; 685 return;
676} 686}
677 687
@@ -695,7 +705,7 @@ acpi_status acpi_os_execute(acpi_execute_type type,
695{ 705{
696 acpi_status status = AE_OK; 706 acpi_status status = AE_OK;
697 struct acpi_os_dpc *dpc; 707 struct acpi_os_dpc *dpc;
698 708 struct workqueue_struct *queue;
699 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 709 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
700 "Scheduling function [%p(%p)] for deferred execution.\n", 710 "Scheduling function [%p(%p)] for deferred execution.\n",
701 function, context)); 711 function, context));
@@ -719,20 +729,13 @@ acpi_status acpi_os_execute(acpi_execute_type type,
719 dpc->function = function; 729 dpc->function = function;
720 dpc->context = context; 730 dpc->context = context;
721 731
722 if (type == OSL_NOTIFY_HANDLER) { 732 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
723 INIT_WORK(&dpc->work, acpi_os_execute_notify); 733 queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq;
724 if (!queue_work(kacpi_notify_wq, &dpc->work)) { 734 if (!queue_work(queue, &dpc->work)) {
725 status = AE_ERROR; 735 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
726 kfree(dpc); 736 "Call to queue_work() failed.\n"));
727 } 737 status = AE_ERROR;
728 } else { 738 kfree(dpc);
729 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
730 if (!queue_work(kacpid_wq, &dpc->work)) {
731 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
732 "Call to queue_work() failed.\n"));
733 status = AE_ERROR;
734 kfree(dpc);
735 }
736 } 739 }
737 return_ACPI_STATUS(status); 740 return_ACPI_STATUS(status);
738} 741}
@@ -1084,6 +1087,128 @@ static int __init acpi_wake_gpes_always_on_setup(char *str)
1084 1087
1085__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup); 1088__setup("acpi_wake_gpes_always_on", acpi_wake_gpes_always_on_setup);
1086 1089
1090/* Check of resource interference between native drivers and ACPI
1091 * OperationRegions (SystemIO and System Memory only).
1092 * IO ports and memory declared in ACPI might be used by the ACPI subsystem
1093 * in arbitrary AML code and can interfere with legacy drivers.
1094 * acpi_enforce_resources= can be set to:
1095 *
1096 * - strict (2)
1097 * -> further driver trying to access the resources will not load
1098 * - lax (default) (1)
1099 * -> further driver trying to access the resources will load, but you
1100 * get a system message that something might go wrong...
1101 *
1102 * - no (0)
1103 * -> ACPI Operation Region resources will not be registered
1104 *
1105 */
1106#define ENFORCE_RESOURCES_STRICT 2
1107#define ENFORCE_RESOURCES_LAX 1
1108#define ENFORCE_RESOURCES_NO 0
1109
1110static unsigned int acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
1111
1112static int __init acpi_enforce_resources_setup(char *str)
1113{
1114 if (str == NULL || *str == '\0')
1115 return 0;
1116
1117 if (!strcmp("strict", str))
1118 acpi_enforce_resources = ENFORCE_RESOURCES_STRICT;
1119 else if (!strcmp("lax", str))
1120 acpi_enforce_resources = ENFORCE_RESOURCES_LAX;
1121 else if (!strcmp("no", str))
1122 acpi_enforce_resources = ENFORCE_RESOURCES_NO;
1123
1124 return 1;
1125}
1126
1127__setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
1128
1129/* Check for resource conflicts between ACPI OperationRegions and native
1130 * drivers */
1131int acpi_check_resource_conflict(struct resource *res)
1132{
1133 struct acpi_res_list *res_list_elem;
1134 int ioport;
1135 int clash = 0;
1136
1137 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1138 return 0;
1139 if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
1140 return 0;
1141
1142 ioport = res->flags & IORESOURCE_IO;
1143
1144 spin_lock(&acpi_res_lock);
1145 list_for_each_entry(res_list_elem, &resource_list_head,
1146 resource_list) {
1147 if (ioport && (res_list_elem->resource_type
1148 != ACPI_ADR_SPACE_SYSTEM_IO))
1149 continue;
1150 if (!ioport && (res_list_elem->resource_type
1151 != ACPI_ADR_SPACE_SYSTEM_MEMORY))
1152 continue;
1153
1154 if (res->end < res_list_elem->start
1155 || res_list_elem->end < res->start)
1156 continue;
1157 clash = 1;
1158 break;
1159 }
1160 spin_unlock(&acpi_res_lock);
1161
1162 if (clash) {
1163 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
1164 printk(KERN_INFO "%sACPI: %s resource %s [0x%llx-0x%llx]"
1165 " conflicts with ACPI region %s"
1166 " [0x%llx-0x%llx]\n",
1167 acpi_enforce_resources == ENFORCE_RESOURCES_LAX
1168 ? KERN_WARNING : KERN_ERR,
1169 ioport ? "I/O" : "Memory", res->name,
1170 (long long) res->start, (long long) res->end,
1171 res_list_elem->name,
1172 (long long) res_list_elem->start,
1173 (long long) res_list_elem->end);
1174 printk(KERN_INFO "ACPI: Device needs an ACPI driver\n");
1175 }
1176 if (acpi_enforce_resources == ENFORCE_RESOURCES_STRICT)
1177 return -EBUSY;
1178 }
1179 return 0;
1180}
1181EXPORT_SYMBOL(acpi_check_resource_conflict);
1182
1183int acpi_check_region(resource_size_t start, resource_size_t n,
1184 const char *name)
1185{
1186 struct resource res = {
1187 .start = start,
1188 .end = start + n - 1,
1189 .name = name,
1190 .flags = IORESOURCE_IO,
1191 };
1192
1193 return acpi_check_resource_conflict(&res);
1194}
1195EXPORT_SYMBOL(acpi_check_region);
1196
1197int acpi_check_mem_region(resource_size_t start, resource_size_t n,
1198 const char *name)
1199{
1200 struct resource res = {
1201 .start = start,
1202 .end = start + n - 1,
1203 .name = name,
1204 .flags = IORESOURCE_MEM,
1205 };
1206
1207 return acpi_check_resource_conflict(&res);
1208
1209}
1210EXPORT_SYMBOL(acpi_check_mem_region);
1211
1087/* 1212/*
1088 * Acquire a spinlock. 1213 * Acquire a spinlock.
1089 * 1214 *
@@ -1195,24 +1320,24 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1195 * 1320 *
1196 * Returns 0 on success 1321 * Returns 0 on success
1197 */ 1322 */
1198int acpi_dmi_dump(void) 1323static int acpi_dmi_dump(void)
1199{ 1324{
1200 1325
1201 if (!dmi_available) 1326 if (!dmi_available)
1202 return -1; 1327 return -1;
1203 1328
1204 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", 1329 printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
1205 dmi_get_slot(DMI_SYS_VENDOR)); 1330 dmi_get_system_info(DMI_SYS_VENDOR));
1206 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", 1331 printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
1207 dmi_get_slot(DMI_PRODUCT_NAME)); 1332 dmi_get_system_info(DMI_PRODUCT_NAME));
1208 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", 1333 printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
1209 dmi_get_slot(DMI_PRODUCT_VERSION)); 1334 dmi_get_system_info(DMI_PRODUCT_VERSION));
1210 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", 1335 printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
1211 dmi_get_slot(DMI_BOARD_NAME)); 1336 dmi_get_system_info(DMI_BOARD_NAME));
1212 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", 1337 printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
1213 dmi_get_slot(DMI_BIOS_VENDOR)); 1338 dmi_get_system_info(DMI_BIOS_VENDOR));
1214 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", 1339 printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
1215 dmi_get_slot(DMI_BIOS_DATE)); 1340 dmi_get_system_info(DMI_BIOS_DATE));
1216 1341
1217 return 0; 1342 return 0;
1218} 1343}
@@ -1285,10 +1410,46 @@ acpi_status
1285acpi_os_validate_address ( 1410acpi_os_validate_address (
1286 u8 space_id, 1411 u8 space_id,
1287 acpi_physical_address address, 1412 acpi_physical_address address,
1288 acpi_size length) 1413 acpi_size length,
1414 char *name)
1289{ 1415{
1416 struct acpi_res_list *res;
1417 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1418 return AE_OK;
1290 1419
1291 return AE_OK; 1420 switch (space_id) {
1421 case ACPI_ADR_SPACE_SYSTEM_IO:
1422 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1423 /* Only interference checks against SystemIO and SytemMemory
1424 are needed */
1425 res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
1426 if (!res)
1427 return AE_OK;
1428 /* ACPI names are fixed to 4 bytes, still better use strlcpy */
1429 strlcpy(res->name, name, 5);
1430 res->start = address;
1431 res->end = address + length - 1;
1432 res->resource_type = space_id;
1433 spin_lock(&acpi_res_lock);
1434 list_add(&res->resource_list, &resource_list_head);
1435 spin_unlock(&acpi_res_lock);
1436 pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, "
1437 "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
1438 ? "SystemIO" : "System Memory",
1439 (unsigned long long)res->start,
1440 (unsigned long long)res->end,
1441 res->name);
1442 break;
1443 case ACPI_ADR_SPACE_PCI_CONFIG:
1444 case ACPI_ADR_SPACE_EC:
1445 case ACPI_ADR_SPACE_SMBUS:
1446 case ACPI_ADR_SPACE_CMOS:
1447 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1448 case ACPI_ADR_SPACE_DATA_TABLE:
1449 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1450 break;
1451 }
1452 return AE_OK;
1292} 1453}
1293 1454
1294#endif 1455#endif