aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/utdelete.c6
-rw-r--r--drivers/acpi/osl.c94
2 files changed, 97 insertions, 3 deletions
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index bc1710315088..96e26e70c63d 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -215,6 +215,12 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
215 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 215 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
216 "***** Region %p\n", object)); 216 "***** Region %p\n", object));
217 217
218 /* Invalidate the region address/length via the host OS */
219
220 acpi_os_invalidate_address(object->region.space_id,
221 object->region.address,
222 (acpi_size) object->region.length);
223
218 second_desc = acpi_ns_get_secondary_object(object); 224 second_desc = acpi_ns_get_secondary_object(object);
219 if (second_desc) { 225 if (second_desc) {
220 /* 226 /*
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 5691f165a952..c5b4f1ed9b71 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -88,6 +88,7 @@ struct acpi_res_list {
88 char name[5]; /* only can have a length of 4 chars, make use of this 88 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 */ 89 one instead of res->name, no need to kalloc then */
90 struct list_head resource_list; 90 struct list_head resource_list;
91 int count;
91}; 92};
92 93
93static LIST_HEAD(resource_list_head); 94static LIST_HEAD(resource_list_head);
@@ -1358,6 +1359,89 @@ acpi_os_validate_interface (char *interface)
1358 return AE_SUPPORT; 1359 return AE_SUPPORT;
1359} 1360}
1360 1361
1362static inline int acpi_res_list_add(struct acpi_res_list *res)
1363{
1364 struct acpi_res_list *res_list_elem;
1365
1366 list_for_each_entry(res_list_elem, &resource_list_head,
1367 resource_list) {
1368
1369 if (res->resource_type == res_list_elem->resource_type &&
1370 res->start == res_list_elem->start &&
1371 res->end == res_list_elem->end) {
1372
1373 /*
1374 * The Region(addr,len) already exist in the list,
1375 * just increase the count
1376 */
1377
1378 res_list_elem->count++;
1379 return 0;
1380 }
1381 }
1382
1383 res->count = 1;
1384 list_add(&res->resource_list, &resource_list_head);
1385 return 1;
1386}
1387
1388static inline void acpi_res_list_del(struct acpi_res_list *res)
1389{
1390 struct acpi_res_list *res_list_elem;
1391
1392 list_for_each_entry(res_list_elem, &resource_list_head,
1393 resource_list) {
1394
1395 if (res->resource_type == res_list_elem->resource_type &&
1396 res->start == res_list_elem->start &&
1397 res->end == res_list_elem->end) {
1398
1399 /*
1400 * If the res count is decreased to 0,
1401 * remove and free it
1402 */
1403
1404 if (--res_list_elem->count == 0) {
1405 list_del(&res_list_elem->resource_list);
1406 kfree(res_list_elem);
1407 }
1408 return;
1409 }
1410 }
1411}
1412
1413acpi_status
1414acpi_os_invalidate_address(
1415 u8 space_id,
1416 acpi_physical_address address,
1417 acpi_size length)
1418{
1419 struct acpi_res_list res;
1420
1421 switch (space_id) {
1422 case ACPI_ADR_SPACE_SYSTEM_IO:
1423 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1424 /* Only interference checks against SystemIO and SytemMemory
1425 are needed */
1426 res.start = address;
1427 res.end = address + length - 1;
1428 res.resource_type = space_id;
1429 spin_lock(&acpi_res_lock);
1430 acpi_res_list_del(&res);
1431 spin_unlock(&acpi_res_lock);
1432 break;
1433 case ACPI_ADR_SPACE_PCI_CONFIG:
1434 case ACPI_ADR_SPACE_EC:
1435 case ACPI_ADR_SPACE_SMBUS:
1436 case ACPI_ADR_SPACE_CMOS:
1437 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1438 case ACPI_ADR_SPACE_DATA_TABLE:
1439 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1440 break;
1441 }
1442 return AE_OK;
1443}
1444
1361/****************************************************************************** 1445/******************************************************************************
1362 * 1446 *
1363 * FUNCTION: acpi_os_validate_address 1447 * FUNCTION: acpi_os_validate_address
@@ -1382,6 +1466,7 @@ acpi_os_validate_address (
1382 char *name) 1466 char *name)
1383{ 1467{
1384 struct acpi_res_list *res; 1468 struct acpi_res_list *res;
1469 int added;
1385 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) 1470 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1386 return AE_OK; 1471 return AE_OK;
1387 1472
@@ -1399,14 +1484,17 @@ acpi_os_validate_address (
1399 res->end = address + length - 1; 1484 res->end = address + length - 1;
1400 res->resource_type = space_id; 1485 res->resource_type = space_id;
1401 spin_lock(&acpi_res_lock); 1486 spin_lock(&acpi_res_lock);
1402 list_add(&res->resource_list, &resource_list_head); 1487 added = acpi_res_list_add(res);
1403 spin_unlock(&acpi_res_lock); 1488 spin_unlock(&acpi_res_lock);
1404 pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, " 1489 pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
1405 "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO) 1490 "name: %s\n", added ? "Added" : "Already exist",
1491 (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
1406 ? "SystemIO" : "System Memory", 1492 ? "SystemIO" : "System Memory",
1407 (unsigned long long)res->start, 1493 (unsigned long long)res->start,
1408 (unsigned long long)res->end, 1494 (unsigned long long)res->end,
1409 res->name); 1495 res->name);
1496 if (!added)
1497 kfree(res);
1410 break; 1498 break;
1411 case ACPI_ADR_SPACE_PCI_CONFIG: 1499 case ACPI_ADR_SPACE_PCI_CONFIG:
1412 case ACPI_ADR_SPACE_EC: 1500 case ACPI_ADR_SPACE_EC: