aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu_init.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-03-01 09:57:53 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2012-03-01 10:14:48 -0500
commit8704a1ba4751fc5ffe2289765cb7222b3a1e20d5 (patch)
treee6379e9323e4b5339269f04fe9938b07a251ee52 /drivers/iommu/amd_iommu_init.c
parent6b21d18ed50c7d145220b0724ea7f2613abf0f95 (diff)
iommu/amd: Split amd_iommu_init function
The hardware-initializtion part of the AMD IOMMU driver is split out into a seperate function. This function can now be called either from amd_iommu_init() itself or any other place if the hardware needs to be ready earlier. This will be used to implement interrupt remapping for AMD. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'drivers/iommu/amd_iommu_init.c')
-rw-r--r--drivers/iommu/amd_iommu_init.c123
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
1427static 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 */
1455static int __init amd_iommu_init(void) 1482int __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
1587out:
1588 return ret;
1589
1590free:
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 */
1605static 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
1572out: 1633out:
1573 return ret; 1634 return ret;
1574 1635
1575free_disable:
1576 disable_iommus();
1577
1578free: 1636free:
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}