aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu_init.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-06-12 09:59:30 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-07-17 06:17:12 -0400
commit2c0ae1720c09c6f8fc8c6bcece29dc80b08ca1af (patch)
treea1e50ae85a9f0055639be9bd1226d93dde68e1ea /drivers/iommu/amd_iommu_init.c
parentb9b1ce707d81ec63c04e4fd8c34699ada950e6dc (diff)
iommu/amd: Convert iommu initialization to state machine
This step makes it very easy to keep track about the current intialization state of the iommu driver. With this change we can initialize the IOMMU hardware to a point where it can remap interrupts and later resume the initializion to enable dma remapping. 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.c173
1 files changed, 109 insertions, 64 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 53828b61e9ac..500e7f15f5c2 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -187,7 +187,23 @@ static u32 dev_table_size; /* size of the device table */
187static u32 alias_table_size; /* size of the alias table */ 187static u32 alias_table_size; /* size of the alias table */
188static u32 rlookup_table_size; /* size if the rlookup table */ 188static u32 rlookup_table_size; /* size if the rlookup table */
189 189
190enum iommu_init_state {
191 IOMMU_START_STATE,
192 IOMMU_IVRS_DETECTED,
193 IOMMU_ACPI_FINISHED,
194 IOMMU_ENABLED,
195 IOMMU_PCI_INIT,
196 IOMMU_INTERRUPTS_EN,
197 IOMMU_DMA_OPS,
198 IOMMU_INITIALIZED,
199 IOMMU_NOT_FOUND,
200 IOMMU_INIT_ERROR,
201};
202
203static enum iommu_init_state init_state = IOMMU_START_STATE;
204
190static int amd_iommu_enable_interrupts(void); 205static int amd_iommu_enable_interrupts(void);
206static int __init iommu_go_to_state(enum iommu_init_state state);
191 207
192static inline void update_last_devid(u16 devid) 208static inline void update_last_devid(u16 devid)
193{ 209{
@@ -1104,7 +1120,7 @@ static void print_iommu_info(void)
1104 } 1120 }
1105} 1121}
1106 1122
1107static int amd_iommu_init_pci(void) 1123static int __init amd_iommu_init_pci(void)
1108{ 1124{
1109 struct amd_iommu *iommu; 1125 struct amd_iommu *iommu;
1110 int ret = 0; 1126 int ret = 0;
@@ -1516,11 +1532,6 @@ static int __init early_amd_iommu_init(void)
1516 if (!amd_iommu_detected) 1532 if (!amd_iommu_detected)
1517 return -ENODEV; 1533 return -ENODEV;
1518 1534
1519 if (amd_iommu_dev_table != NULL) {
1520 /* Hardware already initialized */
1521 return 0;
1522 }
1523
1524 status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size); 1535 status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size);
1525 if (status == AE_NOT_FOUND) 1536 if (status == AE_NOT_FOUND)
1526 return -ENODEV; 1537 return -ENODEV;
@@ -1535,7 +1546,8 @@ static int __init early_amd_iommu_init(void)
1535 * we need to handle. Upon this information the shared data 1546 * we need to handle. Upon this information the shared data
1536 * structures for the IOMMUs in the system will be allocated 1547 * structures for the IOMMUs in the system will be allocated
1537 */ 1548 */
1538 if (find_last_devid_acpi(ivrs_base)) 1549 ret = find_last_devid_acpi(ivrs_base);
1550 if (ret)
1539 goto out; 1551 goto out;
1540 1552
1541 dev_table_size = tbl_size(DEV_TABLE_ENTRY_SIZE); 1553 dev_table_size = tbl_size(DEV_TABLE_ENTRY_SIZE);
@@ -1556,20 +1568,20 @@ static int __init early_amd_iommu_init(void)
1556 amd_iommu_alias_table = (void *)__get_free_pages(GFP_KERNEL, 1568 amd_iommu_alias_table = (void *)__get_free_pages(GFP_KERNEL,
1557 get_order(alias_table_size)); 1569 get_order(alias_table_size));
1558 if (amd_iommu_alias_table == NULL) 1570 if (amd_iommu_alias_table == NULL)
1559 goto free; 1571 goto out;
1560 1572
1561 /* IOMMU rlookup table - find the IOMMU for a specific device */ 1573 /* IOMMU rlookup table - find the IOMMU for a specific device */
1562 amd_iommu_rlookup_table = (void *)__get_free_pages( 1574 amd_iommu_rlookup_table = (void *)__get_free_pages(
1563 GFP_KERNEL | __GFP_ZERO, 1575 GFP_KERNEL | __GFP_ZERO,
1564 get_order(rlookup_table_size)); 1576 get_order(rlookup_table_size));
1565 if (amd_iommu_rlookup_table == NULL) 1577 if (amd_iommu_rlookup_table == NULL)
1566 goto free; 1578 goto out;
1567 1579
1568 amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages( 1580 amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(
1569 GFP_KERNEL | __GFP_ZERO, 1581 GFP_KERNEL | __GFP_ZERO,
1570 get_order(MAX_DOMAIN_ID/8)); 1582 get_order(MAX_DOMAIN_ID/8));
1571 if (amd_iommu_pd_alloc_bitmap == NULL) 1583 if (amd_iommu_pd_alloc_bitmap == NULL)
1572 goto free; 1584 goto out;
1573 1585
1574 /* init the device table */ 1586 /* init the device table */
1575 init_device_table(); 1587 init_device_table();
@@ -1594,11 +1606,11 @@ static int __init early_amd_iommu_init(void)
1594 */ 1606 */
1595 ret = init_iommu_all(ivrs_base); 1607 ret = init_iommu_all(ivrs_base);
1596 if (ret) 1608 if (ret)
1597 goto free; 1609 goto out;
1598 1610
1599 ret = init_memory_definitions(ivrs_base); 1611 ret = init_memory_definitions(ivrs_base);
1600 if (ret) 1612 if (ret)
1601 goto free; 1613 goto out;
1602 1614
1603out: 1615out:
1604 /* Don't leak any ACPI memory */ 1616 /* Don't leak any ACPI memory */
@@ -1606,30 +1618,6 @@ out:
1606 ivrs_base = NULL; 1618 ivrs_base = NULL;
1607 1619
1608 return ret; 1620 return ret;
1609
1610free:
1611 free_on_init_error();
1612
1613 goto out;
1614}
1615
1616int __init amd_iommu_init_hardware(void)
1617{
1618 int ret = 0;
1619
1620 ret = early_amd_iommu_init();
1621 if (ret)
1622 return ret;
1623
1624 ret = amd_iommu_init_pci();
1625 if (ret)
1626 return ret;
1627
1628 enable_iommus();
1629
1630 register_syscore_ops(&amd_iommu_syscore_ops);
1631
1632 return ret;
1633} 1621}
1634 1622
1635static int amd_iommu_enable_interrupts(void) 1623static int amd_iommu_enable_interrupts(void)
@@ -1686,44 +1674,99 @@ static int amd_iommu_init_dma(void)
1686 return 0; 1674 return 0;
1687} 1675}
1688 1676
1689/* 1677/****************************************************************************
1690 * This is the core init function for AMD IOMMU hardware in the system.
1691 * This function is called from the generic x86 DMA layer initialization
1692 * code.
1693 * 1678 *
1694 * The function calls amd_iommu_init_hardware() to setup and enable the 1679 * AMD IOMMU Initialization State Machine
1695 * IOMMU hardware if this has not happened yet. After that the driver 1680 *
1696 * registers for the DMA-API and for the IOMMU-API as necessary. 1681 ****************************************************************************/
1697 */ 1682
1698static int __init amd_iommu_init(void) 1683static int __init state_next(void)
1699{ 1684{
1700 int ret = 0; 1685 int ret = 0;
1701 1686
1702 ret = amd_iommu_init_hardware(); 1687 switch (init_state) {
1703 if (ret) 1688 case IOMMU_START_STATE:
1704 goto out; 1689 if (!detect_ivrs()) {
1705 1690 init_state = IOMMU_NOT_FOUND;
1706 ret = amd_iommu_enable_interrupts(); 1691 ret = -ENODEV;
1707 if (ret) 1692 } else {
1708 goto free; 1693 init_state = IOMMU_IVRS_DETECTED;
1694 }
1695 break;
1696 case IOMMU_IVRS_DETECTED:
1697 ret = early_amd_iommu_init();
1698 init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
1699 break;
1700 case IOMMU_ACPI_FINISHED:
1701 early_enable_iommus();
1702 register_syscore_ops(&amd_iommu_syscore_ops);
1703 x86_platform.iommu_shutdown = disable_iommus;
1704 init_state = IOMMU_ENABLED;
1705 break;
1706 case IOMMU_ENABLED:
1707 ret = amd_iommu_init_pci();
1708 init_state = ret ? IOMMU_INIT_ERROR : IOMMU_PCI_INIT;
1709 enable_iommus_v2();
1710 break;
1711 case IOMMU_PCI_INIT:
1712 ret = amd_iommu_enable_interrupts();
1713 init_state = ret ? IOMMU_INIT_ERROR : IOMMU_INTERRUPTS_EN;
1714 break;
1715 case IOMMU_INTERRUPTS_EN:
1716 ret = amd_iommu_init_dma();
1717 init_state = ret ? IOMMU_INIT_ERROR : IOMMU_DMA_OPS;
1718 break;
1719 case IOMMU_DMA_OPS:
1720 init_state = IOMMU_INITIALIZED;
1721 break;
1722 case IOMMU_INITIALIZED:
1723 /* Nothing to do */
1724 break;
1725 case IOMMU_NOT_FOUND:
1726 case IOMMU_INIT_ERROR:
1727 /* Error states => do nothing */
1728 ret = -EINVAL;
1729 break;
1730 default:
1731 /* Unknown state */
1732 BUG();
1733 }
1709 1734
1710 ret = amd_iommu_init_dma(); 1735 return ret;
1711 if (ret) 1736}
1712 goto free;
1713 1737
1714 amd_iommu_init_api(); 1738static int __init iommu_go_to_state(enum iommu_init_state state)
1739{
1740 int ret = 0;
1715 1741
1716 x86_platform.iommu_shutdown = disable_iommus; 1742 while (init_state != state) {
1743 ret = state_next();
1744 if (init_state == IOMMU_NOT_FOUND ||
1745 init_state == IOMMU_INIT_ERROR)
1746 break;
1747 }
1717 1748
1718out:
1719 return ret; 1749 return ret;
1750}
1720 1751
1721free:
1722 disable_iommus();
1723 1752
1724 free_on_init_error();
1725 1753
1726 goto out; 1754/*
1755 * This is the core init function for AMD IOMMU hardware in the system.
1756 * This function is called from the generic x86 DMA layer initialization
1757 * code.
1758 */
1759static int __init amd_iommu_init(void)
1760{
1761 int ret;
1762
1763 ret = iommu_go_to_state(IOMMU_INITIALIZED);
1764 if (ret) {
1765 disable_iommus();
1766 free_on_init_error();
1767 }
1768
1769 return ret;
1727} 1770}
1728 1771
1729/**************************************************************************** 1772/****************************************************************************
@@ -1735,6 +1778,7 @@ free:
1735 ****************************************************************************/ 1778 ****************************************************************************/
1736int __init amd_iommu_detect(void) 1779int __init amd_iommu_detect(void)
1737{ 1780{
1781 int ret;
1738 1782
1739 if (no_iommu || (iommu_detected && !gart_iommu_aperture)) 1783 if (no_iommu || (iommu_detected && !gart_iommu_aperture))
1740 return -ENODEV; 1784 return -ENODEV;
@@ -1742,8 +1786,9 @@ int __init amd_iommu_detect(void)
1742 if (amd_iommu_disabled) 1786 if (amd_iommu_disabled)
1743 return -ENODEV; 1787 return -ENODEV;
1744 1788
1745 if (!detect_ivrs()) 1789 ret = iommu_go_to_state(IOMMU_IVRS_DETECTED);
1746 return -ENODEV; 1790 if (ret)
1791 return ret;
1747 1792
1748 amd_iommu_detected = true; 1793 amd_iommu_detected = true;
1749 iommu_detected = 1; 1794 iommu_detected = 1;