diff options
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 123 |
1 files changed, 79 insertions, 44 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index bdea288dc185..75653daf1de1 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -1424,10 +1424,40 @@ static struct syscore_ops amd_iommu_syscore_ops = { | |||
1424 | .resume = amd_iommu_resume, | 1424 | .resume = amd_iommu_resume, |
1425 | }; | 1425 | }; |
1426 | 1426 | ||
1427 | static void __init free_on_init_error(void) | ||
1428 | { | ||
1429 | amd_iommu_uninit_devices(); | ||
1430 | |||
1431 | free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, | ||
1432 | get_order(MAX_DOMAIN_ID/8)); | ||
1433 | |||
1434 | free_pages((unsigned long)amd_iommu_rlookup_table, | ||
1435 | get_order(rlookup_table_size)); | ||
1436 | |||
1437 | free_pages((unsigned long)amd_iommu_alias_table, | ||
1438 | get_order(alias_table_size)); | ||
1439 | |||
1440 | free_pages((unsigned long)amd_iommu_dev_table, | ||
1441 | get_order(dev_table_size)); | ||
1442 | |||
1443 | free_iommu_all(); | ||
1444 | |||
1445 | free_unity_maps(); | ||
1446 | |||
1447 | #ifdef CONFIG_GART_IOMMU | ||
1448 | /* | ||
1449 | * We failed to initialize the AMD IOMMU - try fallback to GART | ||
1450 | * if possible. | ||
1451 | */ | ||
1452 | gart_iommu_init(); | ||
1453 | |||
1454 | #endif | ||
1455 | } | ||
1456 | |||
1427 | /* | 1457 | /* |
1428 | * This is the core init function for AMD IOMMU hardware in the system. | 1458 | * This is the hardware init function for AMD IOMMU in the system. |
1429 | * This function is called from the generic x86 DMA layer initialization | 1459 | * This function is called either from amd_iommu_init or from the interrupt |
1430 | * code. | 1460 | * remapping setup code. |
1431 | * | 1461 | * |
1432 | * This function basically parses the ACPI table for AMD IOMMU (IVRS) | 1462 | * This function basically parses the ACPI table for AMD IOMMU (IVRS) |
1433 | * three times: | 1463 | * three times: |
@@ -1446,16 +1476,21 @@ static struct syscore_ops amd_iommu_syscore_ops = { | |||
1446 | * remapping requirements parsed out of the ACPI table in | 1476 | * remapping requirements parsed out of the ACPI table in |
1447 | * this last pass. | 1477 | * this last pass. |
1448 | * | 1478 | * |
1449 | * After that the hardware is initialized and ready to go. In the last | 1479 | * After everything is set up the IOMMUs are enabled and the necessary |
1450 | * step we do some Linux specific things like registering the driver in | 1480 | * hotplug and suspend notifiers are registered. |
1451 | * the dma_ops interface and initializing the suspend/resume support | ||
1452 | * functions. Finally it prints some information about AMD IOMMUs and | ||
1453 | * the driver state and enables the hardware. | ||
1454 | */ | 1481 | */ |
1455 | static int __init amd_iommu_init(void) | 1482 | int __init amd_iommu_init_hardware(void) |
1456 | { | 1483 | { |
1457 | int i, ret = 0; | 1484 | int i, ret = 0; |
1458 | 1485 | ||
1486 | if (!amd_iommu_detected) | ||
1487 | return -ENODEV; | ||
1488 | |||
1489 | if (amd_iommu_dev_table != NULL) { | ||
1490 | /* Hardware already initialized */ | ||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1459 | /* | 1494 | /* |
1460 | * First parse ACPI tables to find the largest Bus/Dev/Func | 1495 | * First parse ACPI tables to find the largest Bus/Dev/Func |
1461 | * we need to handle. Upon this information the shared data | 1496 | * we need to handle. Upon this information the shared data |
@@ -1472,9 +1507,8 @@ static int __init amd_iommu_init(void) | |||
1472 | alias_table_size = tbl_size(ALIAS_TABLE_ENTRY_SIZE); | 1507 | alias_table_size = tbl_size(ALIAS_TABLE_ENTRY_SIZE); |
1473 | rlookup_table_size = tbl_size(RLOOKUP_TABLE_ENTRY_SIZE); | 1508 | rlookup_table_size = tbl_size(RLOOKUP_TABLE_ENTRY_SIZE); |
1474 | 1509 | ||
1475 | ret = -ENOMEM; | ||
1476 | |||
1477 | /* Device table - directly used by all IOMMUs */ | 1510 | /* Device table - directly used by all IOMMUs */ |
1511 | ret = -ENOMEM; | ||
1478 | amd_iommu_dev_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | 1512 | amd_iommu_dev_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, |
1479 | get_order(dev_table_size)); | 1513 | get_order(dev_table_size)); |
1480 | if (amd_iommu_dev_table == NULL) | 1514 | if (amd_iommu_dev_table == NULL) |
@@ -1546,20 +1580,46 @@ static int __init amd_iommu_init(void) | |||
1546 | 1580 | ||
1547 | enable_iommus(); | 1581 | enable_iommus(); |
1548 | 1582 | ||
1583 | amd_iommu_init_notifier(); | ||
1584 | |||
1585 | register_syscore_ops(&amd_iommu_syscore_ops); | ||
1586 | |||
1587 | out: | ||
1588 | return ret; | ||
1589 | |||
1590 | free: | ||
1591 | free_on_init_error(); | ||
1592 | |||
1593 | return ret; | ||
1594 | } | ||
1595 | |||
1596 | /* | ||
1597 | * This is the core init function for AMD IOMMU hardware in the system. | ||
1598 | * This function is called from the generic x86 DMA layer initialization | ||
1599 | * code. | ||
1600 | * | ||
1601 | * The function calls amd_iommu_init_hardware() to setup and enable the | ||
1602 | * IOMMU hardware if this has not happened yet. After that the driver | ||
1603 | * registers for the DMA-API and for the IOMMU-API as necessary. | ||
1604 | */ | ||
1605 | static int __init amd_iommu_init(void) | ||
1606 | { | ||
1607 | int ret = 0; | ||
1608 | |||
1609 | ret = amd_iommu_init_hardware(); | ||
1610 | if (ret) | ||
1611 | goto out; | ||
1612 | |||
1549 | if (iommu_pass_through) | 1613 | if (iommu_pass_through) |
1550 | ret = amd_iommu_init_passthrough(); | 1614 | ret = amd_iommu_init_passthrough(); |
1551 | else | 1615 | else |
1552 | ret = amd_iommu_init_dma_ops(); | 1616 | ret = amd_iommu_init_dma_ops(); |
1553 | 1617 | ||
1554 | if (ret) | 1618 | if (ret) |
1555 | goto free_disable; | 1619 | goto free; |
1556 | 1620 | ||
1557 | amd_iommu_init_api(); | 1621 | amd_iommu_init_api(); |
1558 | 1622 | ||
1559 | amd_iommu_init_notifier(); | ||
1560 | |||
1561 | register_syscore_ops(&amd_iommu_syscore_ops); | ||
1562 | |||
1563 | if (iommu_pass_through) | 1623 | if (iommu_pass_through) |
1564 | goto out; | 1624 | goto out; |
1565 | 1625 | ||
@@ -1569,39 +1629,14 @@ static int __init amd_iommu_init(void) | |||
1569 | printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); | 1629 | printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); |
1570 | 1630 | ||
1571 | x86_platform.iommu_shutdown = disable_iommus; | 1631 | x86_platform.iommu_shutdown = disable_iommus; |
1632 | |||
1572 | out: | 1633 | out: |
1573 | return ret; | 1634 | return ret; |
1574 | 1635 | ||
1575 | free_disable: | ||
1576 | disable_iommus(); | ||
1577 | |||
1578 | free: | 1636 | free: |
1579 | amd_iommu_uninit_devices(); | 1637 | disable_iommus(); |
1580 | |||
1581 | free_pages((unsigned long)amd_iommu_pd_alloc_bitmap, | ||
1582 | get_order(MAX_DOMAIN_ID/8)); | ||
1583 | |||
1584 | free_pages((unsigned long)amd_iommu_rlookup_table, | ||
1585 | get_order(rlookup_table_size)); | ||
1586 | |||
1587 | free_pages((unsigned long)amd_iommu_alias_table, | ||
1588 | get_order(alias_table_size)); | ||
1589 | |||
1590 | free_pages((unsigned long)amd_iommu_dev_table, | ||
1591 | get_order(dev_table_size)); | ||
1592 | |||
1593 | free_iommu_all(); | ||
1594 | |||
1595 | free_unity_maps(); | ||
1596 | |||
1597 | #ifdef CONFIG_GART_IOMMU | ||
1598 | /* | ||
1599 | * We failed to initialize the AMD IOMMU - try fallback to GART | ||
1600 | * if possible. | ||
1601 | */ | ||
1602 | gart_iommu_init(); | ||
1603 | 1638 | ||
1604 | #endif | 1639 | free_on_init_error(); |
1605 | 1640 | ||
1606 | goto out; | 1641 | goto out; |
1607 | } | 1642 | } |