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.c126
1 files changed, 96 insertions, 30 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 5691f165a952..56071b67bed5 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -58,6 +58,7 @@ struct acpi_os_dpc {
58 acpi_osd_exec_callback function; 58 acpi_osd_exec_callback function;
59 void *context; 59 void *context;
60 struct work_struct work; 60 struct work_struct work;
61 int wait;
61}; 62};
62 63
63#ifdef CONFIG_ACPI_CUSTOM_DSDT 64#ifdef CONFIG_ACPI_CUSTOM_DSDT
@@ -88,6 +89,7 @@ struct acpi_res_list {
88 char name[5]; /* only can have a length of 4 chars, make use of this 89 char name[5]; /* only can have a length of 4 chars, make use of this
89 one instead of res->name, no need to kalloc then */ 90 one instead of res->name, no need to kalloc then */
90 struct list_head resource_list; 91 struct list_head resource_list;
92 int count;
91}; 93};
92 94
93static LIST_HEAD(resource_list_head); 95static LIST_HEAD(resource_list_head);
@@ -697,31 +699,12 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */
697static void acpi_os_execute_deferred(struct work_struct *work) 699static void acpi_os_execute_deferred(struct work_struct *work)
698{ 700{
699 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); 701 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
700 if (!dpc) {
701 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
702 return;
703 }
704
705 dpc->function(dpc->context);
706 kfree(dpc);
707
708 return;
709}
710
711static void acpi_os_execute_hp_deferred(struct work_struct *work)
712{
713 struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
714 if (!dpc) {
715 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
716 return;
717 }
718 702
719 acpi_os_wait_events_complete(NULL); 703 if (dpc->wait)
704 acpi_os_wait_events_complete(NULL);
720 705
721 dpc->function(dpc->context); 706 dpc->function(dpc->context);
722 kfree(dpc); 707 kfree(dpc);
723
724 return;
725} 708}
726 709
727/******************************************************************************* 710/*******************************************************************************
@@ -745,15 +728,11 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
745 acpi_status status = AE_OK; 728 acpi_status status = AE_OK;
746 struct acpi_os_dpc *dpc; 729 struct acpi_os_dpc *dpc;
747 struct workqueue_struct *queue; 730 struct workqueue_struct *queue;
748 work_func_t func;
749 int ret; 731 int ret;
750 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 732 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
751 "Scheduling function [%p(%p)] for deferred execution.\n", 733 "Scheduling function [%p(%p)] for deferred execution.\n",
752 function, context)); 734 function, context));
753 735
754 if (!function)
755 return AE_BAD_PARAMETER;
756
757 /* 736 /*
758 * Allocate/initialize DPC structure. Note that this memory will be 737 * Allocate/initialize DPC structure. Note that this memory will be
759 * freed by the callee. The kernel handles the work_struct list in a 738 * freed by the callee. The kernel handles the work_struct list in a
@@ -778,8 +757,8 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
778 */ 757 */
779 queue = hp ? kacpi_hotplug_wq : 758 queue = hp ? kacpi_hotplug_wq :
780 (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); 759 (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
781 func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; 760 dpc->wait = hp ? 1 : 0;
782 INIT_WORK(&dpc->work, func); 761 INIT_WORK(&dpc->work, acpi_os_execute_deferred);
783 ret = queue_work(queue, &dpc->work); 762 ret = queue_work(queue, &dpc->work);
784 763
785 if (!ret) { 764 if (!ret) {
@@ -1358,6 +1337,89 @@ acpi_os_validate_interface (char *interface)
1358 return AE_SUPPORT; 1337 return AE_SUPPORT;
1359} 1338}
1360 1339
1340static inline int acpi_res_list_add(struct acpi_res_list *res)
1341{
1342 struct acpi_res_list *res_list_elem;
1343
1344 list_for_each_entry(res_list_elem, &resource_list_head,
1345 resource_list) {
1346
1347 if (res->resource_type == res_list_elem->resource_type &&
1348 res->start == res_list_elem->start &&
1349 res->end == res_list_elem->end) {
1350
1351 /*
1352 * The Region(addr,len) already exist in the list,
1353 * just increase the count
1354 */
1355
1356 res_list_elem->count++;
1357 return 0;
1358 }
1359 }
1360
1361 res->count = 1;
1362 list_add(&res->resource_list, &resource_list_head);
1363 return 1;
1364}
1365
1366static inline void acpi_res_list_del(struct acpi_res_list *res)
1367{
1368 struct acpi_res_list *res_list_elem;
1369
1370 list_for_each_entry(res_list_elem, &resource_list_head,
1371 resource_list) {
1372
1373 if (res->resource_type == res_list_elem->resource_type &&
1374 res->start == res_list_elem->start &&
1375 res->end == res_list_elem->end) {
1376
1377 /*
1378 * If the res count is decreased to 0,
1379 * remove and free it
1380 */
1381
1382 if (--res_list_elem->count == 0) {
1383 list_del(&res_list_elem->resource_list);
1384 kfree(res_list_elem);
1385 }
1386 return;
1387 }
1388 }
1389}
1390
1391acpi_status
1392acpi_os_invalidate_address(
1393 u8 space_id,
1394 acpi_physical_address address,
1395 acpi_size length)
1396{
1397 struct acpi_res_list res;
1398
1399 switch (space_id) {
1400 case ACPI_ADR_SPACE_SYSTEM_IO:
1401 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1402 /* Only interference checks against SystemIO and SytemMemory
1403 are needed */
1404 res.start = address;
1405 res.end = address + length - 1;
1406 res.resource_type = space_id;
1407 spin_lock(&acpi_res_lock);
1408 acpi_res_list_del(&res);
1409 spin_unlock(&acpi_res_lock);
1410 break;
1411 case ACPI_ADR_SPACE_PCI_CONFIG:
1412 case ACPI_ADR_SPACE_EC:
1413 case ACPI_ADR_SPACE_SMBUS:
1414 case ACPI_ADR_SPACE_CMOS:
1415 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1416 case ACPI_ADR_SPACE_DATA_TABLE:
1417 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1418 break;
1419 }
1420 return AE_OK;
1421}
1422
1361/****************************************************************************** 1423/******************************************************************************
1362 * 1424 *
1363 * FUNCTION: acpi_os_validate_address 1425 * FUNCTION: acpi_os_validate_address
@@ -1382,6 +1444,7 @@ acpi_os_validate_address (
1382 char *name) 1444 char *name)
1383{ 1445{
1384 struct acpi_res_list *res; 1446 struct acpi_res_list *res;
1447 int added;
1385 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) 1448 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1386 return AE_OK; 1449 return AE_OK;
1387 1450
@@ -1399,14 +1462,17 @@ acpi_os_validate_address (
1399 res->end = address + length - 1; 1462 res->end = address + length - 1;
1400 res->resource_type = space_id; 1463 res->resource_type = space_id;
1401 spin_lock(&acpi_res_lock); 1464 spin_lock(&acpi_res_lock);
1402 list_add(&res->resource_list, &resource_list_head); 1465 added = acpi_res_list_add(res);
1403 spin_unlock(&acpi_res_lock); 1466 spin_unlock(&acpi_res_lock);
1404 pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, " 1467 pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
1405 "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO) 1468 "name: %s\n", added ? "Added" : "Already exist",
1469 (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
1406 ? "SystemIO" : "System Memory", 1470 ? "SystemIO" : "System Memory",
1407 (unsigned long long)res->start, 1471 (unsigned long long)res->start,
1408 (unsigned long long)res->end, 1472 (unsigned long long)res->end,
1409 res->name); 1473 res->name);
1474 if (!added)
1475 kfree(res);
1410 break; 1476 break;
1411 case ACPI_ADR_SPACE_PCI_CONFIG: 1477 case ACPI_ADR_SPACE_PCI_CONFIG:
1412 case ACPI_ADR_SPACE_EC: 1478 case ACPI_ADR_SPACE_EC: