diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2012-06-11 11:45:25 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2012-07-17 06:14:56 -0400 |
commit | 02f3b3f5449cd0d9c4fb2c6f85f2973adefb7c72 (patch) | |
tree | fc5eccc0912ae08d5cc2c09c45558e8282d3747d /drivers/iommu/amd_iommu_init.c | |
parent | 98f1ad258254d89ffb550a36d59caf9127a9d53f (diff) |
iommu/amd: Use acpi_get_table instead of acpi_table_parse
This makes it easier to propagate errors while parsing the
IVRS table and makes the amd_iommu_init_err hack obsolete.
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.c | 118 |
1 files changed, 66 insertions, 52 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 55f2033ea69b..de7a6cedcc45 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/msi.h> | 26 | #include <linux/msi.h> |
27 | #include <linux/amd-iommu.h> | 27 | #include <linux/amd-iommu.h> |
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <linux/acpi.h> | ||
30 | #include <acpi/acpi.h> | ||
29 | #include <asm/pci-direct.h> | 31 | #include <asm/pci-direct.h> |
30 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
31 | #include <asm/gart.h> | 33 | #include <asm/gart.h> |
@@ -122,7 +124,7 @@ struct ivmd_header { | |||
122 | 124 | ||
123 | bool amd_iommu_dump; | 125 | bool amd_iommu_dump; |
124 | 126 | ||
125 | static int __initdata amd_iommu_detected; | 127 | static bool amd_iommu_detected; |
126 | static bool __initdata amd_iommu_disabled; | 128 | static bool __initdata amd_iommu_disabled; |
127 | 129 | ||
128 | u16 amd_iommu_last_bdf; /* largest PCI device id we have | 130 | u16 amd_iommu_last_bdf; /* largest PCI device id we have |
@@ -149,11 +151,6 @@ bool amd_iommu_v2_present __read_mostly; | |||
149 | bool amd_iommu_force_isolation __read_mostly; | 151 | bool amd_iommu_force_isolation __read_mostly; |
150 | 152 | ||
151 | /* | 153 | /* |
152 | * The ACPI table parsing functions set this variable on an error | ||
153 | */ | ||
154 | static int __initdata amd_iommu_init_err; | ||
155 | |||
156 | /* | ||
157 | * List of protection domains - used during resume | 154 | * List of protection domains - used during resume |
158 | */ | 155 | */ |
159 | LIST_HEAD(amd_iommu_pd_list); | 156 | LIST_HEAD(amd_iommu_pd_list); |
@@ -457,11 +454,9 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table) | |||
457 | */ | 454 | */ |
458 | for (i = 0; i < table->length; ++i) | 455 | for (i = 0; i < table->length; ++i) |
459 | checksum += p[i]; | 456 | checksum += p[i]; |
460 | if (checksum != 0) { | 457 | if (checksum != 0) |
461 | /* ACPI table corrupt */ | 458 | /* ACPI table corrupt */ |
462 | amd_iommu_init_err = -ENODEV; | 459 | return -ENODEV; |
463 | return 0; | ||
464 | } | ||
465 | 460 | ||
466 | p += IVRS_HEADER_LENGTH; | 461 | p += IVRS_HEADER_LENGTH; |
467 | 462 | ||
@@ -1087,16 +1082,12 @@ static int __init init_iommu_all(struct acpi_table_header *table) | |||
1087 | h->mmio_phys); | 1082 | h->mmio_phys); |
1088 | 1083 | ||
1089 | iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL); | 1084 | iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL); |
1090 | if (iommu == NULL) { | 1085 | if (iommu == NULL) |
1091 | amd_iommu_init_err = -ENOMEM; | 1086 | return -ENOMEM; |
1092 | return 0; | ||
1093 | } | ||
1094 | 1087 | ||
1095 | ret = init_iommu_one(iommu, h); | 1088 | ret = init_iommu_one(iommu, h); |
1096 | if (ret) { | 1089 | if (ret) |
1097 | amd_iommu_init_err = ret; | 1090 | return ret; |
1098 | return 0; | ||
1099 | } | ||
1100 | break; | 1091 | break; |
1101 | default: | 1092 | default: |
1102 | break; | 1093 | break; |
@@ -1477,9 +1468,15 @@ static void __init free_on_init_error(void) | |||
1477 | */ | 1468 | */ |
1478 | int __init amd_iommu_init_hardware(void) | 1469 | int __init amd_iommu_init_hardware(void) |
1479 | { | 1470 | { |
1471 | struct acpi_table_header *ivrs_base; | ||
1472 | acpi_size ivrs_size; | ||
1473 | acpi_status status; | ||
1480 | int i, ret = 0; | 1474 | int i, ret = 0; |
1481 | 1475 | ||
1482 | if (!amd_iommu_detected) | 1476 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) |
1477 | return -ENODEV; | ||
1478 | |||
1479 | if (amd_iommu_disabled || !amd_iommu_detected) | ||
1483 | return -ENODEV; | 1480 | return -ENODEV; |
1484 | 1481 | ||
1485 | if (amd_iommu_dev_table != NULL) { | 1482 | if (amd_iommu_dev_table != NULL) { |
@@ -1487,16 +1484,21 @@ int __init amd_iommu_init_hardware(void) | |||
1487 | return 0; | 1484 | return 0; |
1488 | } | 1485 | } |
1489 | 1486 | ||
1487 | status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size); | ||
1488 | if (status == AE_NOT_FOUND) | ||
1489 | return -ENODEV; | ||
1490 | else if (ACPI_FAILURE(status)) { | ||
1491 | const char *err = acpi_format_exception(status); | ||
1492 | pr_err("AMD-Vi: IVRS table error: %s\n", err); | ||
1493 | return -EINVAL; | ||
1494 | } | ||
1495 | |||
1490 | /* | 1496 | /* |
1491 | * First parse ACPI tables to find the largest Bus/Dev/Func | 1497 | * First parse ACPI tables to find the largest Bus/Dev/Func |
1492 | * we need to handle. Upon this information the shared data | 1498 | * we need to handle. Upon this information the shared data |
1493 | * structures for the IOMMUs in the system will be allocated | 1499 | * structures for the IOMMUs in the system will be allocated |
1494 | */ | 1500 | */ |
1495 | if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0) | 1501 | if (find_last_devid_acpi(ivrs_base)) |
1496 | return -ENODEV; | ||
1497 | |||
1498 | ret = amd_iommu_init_err; | ||
1499 | if (ret) | ||
1500 | goto out; | 1502 | goto out; |
1501 | 1503 | ||
1502 | dev_table_size = tbl_size(DEV_TABLE_ENTRY_SIZE); | 1504 | dev_table_size = tbl_size(DEV_TABLE_ENTRY_SIZE); |
@@ -1553,22 +1555,13 @@ int __init amd_iommu_init_hardware(void) | |||
1553 | * now the data structures are allocated and basically initialized | 1555 | * now the data structures are allocated and basically initialized |
1554 | * start the real acpi table scan | 1556 | * start the real acpi table scan |
1555 | */ | 1557 | */ |
1556 | ret = -ENODEV; | 1558 | ret = init_iommu_all(ivrs_base); |
1557 | if (acpi_table_parse("IVRS", init_iommu_all) != 0) | 1559 | if (ret) |
1558 | goto free; | ||
1559 | |||
1560 | if (amd_iommu_init_err) { | ||
1561 | ret = amd_iommu_init_err; | ||
1562 | goto free; | ||
1563 | } | ||
1564 | |||
1565 | if (acpi_table_parse("IVRS", init_memory_definitions) != 0) | ||
1566 | goto free; | 1560 | goto free; |
1567 | 1561 | ||
1568 | if (amd_iommu_init_err) { | 1562 | ret = init_memory_definitions(ivrs_base); |
1569 | ret = amd_iommu_init_err; | 1563 | if (ret) |
1570 | goto free; | 1564 | goto free; |
1571 | } | ||
1572 | 1565 | ||
1573 | ret = amd_iommu_init_devices(); | 1566 | ret = amd_iommu_init_devices(); |
1574 | if (ret) | 1567 | if (ret) |
@@ -1581,12 +1574,16 @@ int __init amd_iommu_init_hardware(void) | |||
1581 | register_syscore_ops(&amd_iommu_syscore_ops); | 1574 | register_syscore_ops(&amd_iommu_syscore_ops); |
1582 | 1575 | ||
1583 | out: | 1576 | out: |
1577 | /* Don't leak any ACPI memory */ | ||
1578 | early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); | ||
1579 | ivrs_base = NULL; | ||
1580 | |||
1584 | return ret; | 1581 | return ret; |
1585 | 1582 | ||
1586 | free: | 1583 | free: |
1587 | free_on_init_error(); | 1584 | free_on_init_error(); |
1588 | 1585 | ||
1589 | return ret; | 1586 | goto out; |
1590 | } | 1587 | } |
1591 | 1588 | ||
1592 | static int amd_iommu_enable_interrupts(void) | 1589 | static int amd_iommu_enable_interrupts(void) |
@@ -1604,6 +1601,26 @@ out: | |||
1604 | return ret; | 1601 | return ret; |
1605 | } | 1602 | } |
1606 | 1603 | ||
1604 | static bool detect_ivrs(void) | ||
1605 | { | ||
1606 | struct acpi_table_header *ivrs_base; | ||
1607 | acpi_size ivrs_size; | ||
1608 | acpi_status status; | ||
1609 | |||
1610 | status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size); | ||
1611 | if (status == AE_NOT_FOUND) | ||
1612 | return false; | ||
1613 | else if (ACPI_FAILURE(status)) { | ||
1614 | const char *err = acpi_format_exception(status); | ||
1615 | pr_err("AMD-Vi: IVRS table error: %s\n", err); | ||
1616 | return false; | ||
1617 | } | ||
1618 | |||
1619 | early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); | ||
1620 | |||
1621 | return true; | ||
1622 | } | ||
1623 | |||
1607 | /* | 1624 | /* |
1608 | * This is the core init function for AMD IOMMU hardware in the system. | 1625 | * This is the core init function for AMD IOMMU hardware in the system. |
1609 | * This function is called from the generic x86 DMA layer initialization | 1626 | * This function is called from the generic x86 DMA layer initialization |
@@ -1663,29 +1680,26 @@ free: | |||
1663 | * IOMMUs | 1680 | * IOMMUs |
1664 | * | 1681 | * |
1665 | ****************************************************************************/ | 1682 | ****************************************************************************/ |
1666 | static int __init early_amd_iommu_detect(struct acpi_table_header *table) | ||
1667 | { | ||
1668 | return 0; | ||
1669 | } | ||
1670 | |||
1671 | int __init amd_iommu_detect(void) | 1683 | int __init amd_iommu_detect(void) |
1672 | { | 1684 | { |
1685 | |||
1673 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) | 1686 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) |
1674 | return -ENODEV; | 1687 | return -ENODEV; |
1675 | 1688 | ||
1676 | if (amd_iommu_disabled) | 1689 | if (amd_iommu_disabled) |
1677 | return -ENODEV; | 1690 | return -ENODEV; |
1678 | 1691 | ||
1679 | if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) { | 1692 | if (!detect_ivrs()) |
1680 | iommu_detected = 1; | 1693 | return -ENODEV; |
1681 | amd_iommu_detected = 1; | ||
1682 | x86_init.iommu.iommu_init = amd_iommu_init; | ||
1683 | 1694 | ||
1684 | /* Make sure ACS will be enabled */ | 1695 | amd_iommu_detected = true; |
1685 | pci_request_acs(); | 1696 | iommu_detected = 1; |
1686 | return 1; | 1697 | x86_init.iommu.iommu_init = amd_iommu_init; |
1687 | } | 1698 | |
1688 | return -ENODEV; | 1699 | /* Make sure ACS will be enabled */ |
1700 | pci_request_acs(); | ||
1701 | |||
1702 | return 0; | ||
1689 | } | 1703 | } |
1690 | 1704 | ||
1691 | /**************************************************************************** | 1705 | /**************************************************************************** |