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.c242
1 files changed, 38 insertions, 204 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index f31c5c5f1b7e..fcc12d842bcc 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -83,19 +83,6 @@ static struct workqueue_struct *kacpi_notify_wq;
83struct workqueue_struct *kacpi_hotplug_wq; 83struct workqueue_struct *kacpi_hotplug_wq;
84EXPORT_SYMBOL(kacpi_hotplug_wq); 84EXPORT_SYMBOL(kacpi_hotplug_wq);
85 85
86struct acpi_res_list {
87 resource_size_t start;
88 resource_size_t end;
89 acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
90 char name[5]; /* only can have a length of 4 chars, make use of this
91 one instead of res->name, no need to kalloc then */
92 struct list_head resource_list;
93 int count;
94};
95
96static LIST_HEAD(resource_list_head);
97static DEFINE_SPINLOCK(acpi_res_lock);
98
99/* 86/*
100 * This list of permanent mappings is for memory that may be accessed from 87 * This list of permanent mappings is for memory that may be accessed from
101 * interrupt context, where we can't do the ioremap(). 88 * interrupt context, where we can't do the ioremap().
@@ -166,17 +153,21 @@ static u32 acpi_osi_handler(acpi_string interface, u32 supported)
166 return supported; 153 return supported;
167} 154}
168 155
169static void __init acpi_request_region (struct acpi_generic_address *addr, 156static void __init acpi_request_region (struct acpi_generic_address *gas,
170 unsigned int length, char *desc) 157 unsigned int length, char *desc)
171{ 158{
172 if (!addr->address || !length) 159 u64 addr;
160
161 /* Handle possible alignment issues */
162 memcpy(&addr, &gas->address, sizeof(addr));
163 if (!addr || !length)
173 return; 164 return;
174 165
175 /* Resources are never freed */ 166 /* Resources are never freed */
176 if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) 167 if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
177 request_region(addr->address, length, desc); 168 request_region(addr, length, desc);
178 else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 169 else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
179 request_mem_region(addr->address, length, desc); 170 request_mem_region(addr, length, desc);
180} 171}
181 172
182static int __init acpi_reserve_resources(void) 173static int __init acpi_reserve_resources(void)
@@ -427,35 +418,42 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
427 __acpi_unmap_table(virt, size); 418 __acpi_unmap_table(virt, size);
428} 419}
429 420
430static int acpi_os_map_generic_address(struct acpi_generic_address *addr) 421int acpi_os_map_generic_address(struct acpi_generic_address *gas)
431{ 422{
423 u64 addr;
432 void __iomem *virt; 424 void __iomem *virt;
433 425
434 if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 426 if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
435 return 0; 427 return 0;
436 428
437 if (!addr->address || !addr->bit_width) 429 /* Handle possible alignment issues */
430 memcpy(&addr, &gas->address, sizeof(addr));
431 if (!addr || !gas->bit_width)
438 return -EINVAL; 432 return -EINVAL;
439 433
440 virt = acpi_os_map_memory(addr->address, addr->bit_width / 8); 434 virt = acpi_os_map_memory(addr, gas->bit_width / 8);
441 if (!virt) 435 if (!virt)
442 return -EIO; 436 return -EIO;
443 437
444 return 0; 438 return 0;
445} 439}
440EXPORT_SYMBOL(acpi_os_map_generic_address);
446 441
447static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) 442void acpi_os_unmap_generic_address(struct acpi_generic_address *gas)
448{ 443{
444 u64 addr;
449 struct acpi_ioremap *map; 445 struct acpi_ioremap *map;
450 446
451 if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 447 if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
452 return; 448 return;
453 449
454 if (!addr->address || !addr->bit_width) 450 /* Handle possible alignment issues */
451 memcpy(&addr, &gas->address, sizeof(addr));
452 if (!addr || !gas->bit_width)
455 return; 453 return;
456 454
457 mutex_lock(&acpi_ioremap_lock); 455 mutex_lock(&acpi_ioremap_lock);
458 map = acpi_map_lookup(addr->address, addr->bit_width / 8); 456 map = acpi_map_lookup(addr, gas->bit_width / 8);
459 if (!map) { 457 if (!map) {
460 mutex_unlock(&acpi_ioremap_lock); 458 mutex_unlock(&acpi_ioremap_lock);
461 return; 459 return;
@@ -465,6 +463,7 @@ static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
465 463
466 acpi_os_map_cleanup(map); 464 acpi_os_map_cleanup(map);
467} 465}
466EXPORT_SYMBOL(acpi_os_unmap_generic_address);
468 467
469#ifdef ACPI_FUTURE_USAGE 468#ifdef ACPI_FUTURE_USAGE
470acpi_status 469acpi_status
@@ -1278,44 +1277,28 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
1278 * drivers */ 1277 * drivers */
1279int acpi_check_resource_conflict(const struct resource *res) 1278int acpi_check_resource_conflict(const struct resource *res)
1280{ 1279{
1281 struct acpi_res_list *res_list_elem; 1280 acpi_adr_space_type space_id;
1282 int ioport = 0, clash = 0; 1281 acpi_size length;
1282 u8 warn = 0;
1283 int clash = 0;
1283 1284
1284 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) 1285 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1285 return 0; 1286 return 0;
1286 if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM)) 1287 if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
1287 return 0; 1288 return 0;
1288 1289
1289 ioport = res->flags & IORESOURCE_IO; 1290 if (res->flags & IORESOURCE_IO)
1290 1291 space_id = ACPI_ADR_SPACE_SYSTEM_IO;
1291 spin_lock(&acpi_res_lock); 1292 else
1292 list_for_each_entry(res_list_elem, &resource_list_head, 1293 space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
1293 resource_list) {
1294 if (ioport && (res_list_elem->resource_type
1295 != ACPI_ADR_SPACE_SYSTEM_IO))
1296 continue;
1297 if (!ioport && (res_list_elem->resource_type
1298 != ACPI_ADR_SPACE_SYSTEM_MEMORY))
1299 continue;
1300 1294
1301 if (res->end < res_list_elem->start 1295 length = res->end - res->start + 1;
1302 || res_list_elem->end < res->start) 1296 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO)
1303 continue; 1297 warn = 1;
1304 clash = 1; 1298 clash = acpi_check_address_range(space_id, res->start, length, warn);
1305 break;
1306 }
1307 spin_unlock(&acpi_res_lock);
1308 1299
1309 if (clash) { 1300 if (clash) {
1310 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { 1301 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
1311 printk(KERN_WARNING "ACPI: resource %s %pR"
1312 " conflicts with ACPI region %s "
1313 "[%s 0x%zx-0x%zx]\n",
1314 res->name, res, res_list_elem->name,
1315 (res_list_elem->resource_type ==
1316 ACPI_ADR_SPACE_SYSTEM_IO) ? "io" : "mem",
1317 (size_t) res_list_elem->start,
1318 (size_t) res_list_elem->end);
1319 if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX) 1302 if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
1320 printk(KERN_NOTICE "ACPI: This conflict may" 1303 printk(KERN_NOTICE "ACPI: This conflict may"
1321 " cause random problems and system" 1304 " cause random problems and system"
@@ -1467,155 +1450,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1467 kmem_cache_free(cache, object); 1450 kmem_cache_free(cache, object);
1468 return (AE_OK); 1451 return (AE_OK);
1469} 1452}
1470
1471static inline int acpi_res_list_add(struct acpi_res_list *res)
1472{
1473 struct acpi_res_list *res_list_elem;
1474
1475 list_for_each_entry(res_list_elem, &resource_list_head,
1476 resource_list) {
1477
1478 if (res->resource_type == res_list_elem->resource_type &&
1479 res->start == res_list_elem->start &&
1480 res->end == res_list_elem->end) {
1481
1482 /*
1483 * The Region(addr,len) already exist in the list,
1484 * just increase the count
1485 */
1486
1487 res_list_elem->count++;
1488 return 0;
1489 }
1490 }
1491
1492 res->count = 1;
1493 list_add(&res->resource_list, &resource_list_head);
1494 return 1;
1495}
1496
1497static inline void acpi_res_list_del(struct acpi_res_list *res)
1498{
1499 struct acpi_res_list *res_list_elem;
1500
1501 list_for_each_entry(res_list_elem, &resource_list_head,
1502 resource_list) {
1503
1504 if (res->resource_type == res_list_elem->resource_type &&
1505 res->start == res_list_elem->start &&
1506 res->end == res_list_elem->end) {
1507
1508 /*
1509 * If the res count is decreased to 0,
1510 * remove and free it
1511 */
1512
1513 if (--res_list_elem->count == 0) {
1514 list_del(&res_list_elem->resource_list);
1515 kfree(res_list_elem);
1516 }
1517 return;
1518 }
1519 }
1520}
1521
1522acpi_status
1523acpi_os_invalidate_address(
1524 u8 space_id,
1525 acpi_physical_address address,
1526 acpi_size length)
1527{
1528 struct acpi_res_list res;
1529
1530 switch (space_id) {
1531 case ACPI_ADR_SPACE_SYSTEM_IO:
1532 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1533 /* Only interference checks against SystemIO and SystemMemory
1534 are needed */
1535 res.start = address;
1536 res.end = address + length - 1;
1537 res.resource_type = space_id;
1538 spin_lock(&acpi_res_lock);
1539 acpi_res_list_del(&res);
1540 spin_unlock(&acpi_res_lock);
1541 break;
1542 case ACPI_ADR_SPACE_PCI_CONFIG:
1543 case ACPI_ADR_SPACE_EC:
1544 case ACPI_ADR_SPACE_SMBUS:
1545 case ACPI_ADR_SPACE_CMOS:
1546 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1547 case ACPI_ADR_SPACE_DATA_TABLE:
1548 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1549 break;
1550 }
1551 return AE_OK;
1552}
1553
1554/******************************************************************************
1555 *
1556 * FUNCTION: acpi_os_validate_address
1557 *
1558 * PARAMETERS: space_id - ACPI space ID
1559 * address - Physical address
1560 * length - Address length
1561 *
1562 * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
1563 * should return AE_AML_ILLEGAL_ADDRESS.
1564 *
1565 * DESCRIPTION: Validate a system address via the host OS. Used to validate
1566 * the addresses accessed by AML operation regions.
1567 *
1568 *****************************************************************************/
1569
1570acpi_status
1571acpi_os_validate_address (
1572 u8 space_id,
1573 acpi_physical_address address,
1574 acpi_size length,
1575 char *name)
1576{
1577 struct acpi_res_list *res;
1578 int added;
1579 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1580 return AE_OK;
1581
1582 switch (space_id) {
1583 case ACPI_ADR_SPACE_SYSTEM_IO:
1584 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1585 /* Only interference checks against SystemIO and SystemMemory
1586 are needed */
1587 res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
1588 if (!res)
1589 return AE_OK;
1590 /* ACPI names are fixed to 4 bytes, still better use strlcpy */
1591 strlcpy(res->name, name, 5);
1592 res->start = address;
1593 res->end = address + length - 1;
1594 res->resource_type = space_id;
1595 spin_lock(&acpi_res_lock);
1596 added = acpi_res_list_add(res);
1597 spin_unlock(&acpi_res_lock);
1598 pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
1599 "name: %s\n", added ? "Added" : "Already exist",
1600 (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
1601 ? "SystemIO" : "System Memory",
1602 (unsigned long long)res->start,
1603 (unsigned long long)res->end,
1604 res->name);
1605 if (!added)
1606 kfree(res);
1607 break;
1608 case ACPI_ADR_SPACE_PCI_CONFIG:
1609 case ACPI_ADR_SPACE_EC:
1610 case ACPI_ADR_SPACE_SMBUS:
1611 case ACPI_ADR_SPACE_CMOS:
1612 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1613 case ACPI_ADR_SPACE_DATA_TABLE:
1614 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1615 break;
1616 }
1617 return AE_OK;
1618}
1619#endif 1453#endif
1620 1454
1621acpi_status __init acpi_os_initialize(void) 1455acpi_status __init acpi_os_initialize(void)