diff options
| author | Ingo Molnar <mingo@elte.hu> | 2010-09-24 05:19:53 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2010-09-24 05:19:53 -0400 |
| commit | 7329cf0201f48695862e334828a108aa7175e955 (patch) | |
| tree | 9ebea4a0394d14a00b98cc4ee6f726588956c168 | |
| parent | 74b3c444a963ba55aef89b33a1bcaada9a4c206f (diff) | |
| parent | 04e0463e088b41060c08c255eb0d3278a504f094 (diff) | |
Merge branch 'amd-iommu/2.6.36' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu into x86/urgent
| -rw-r--r-- | arch/x86/include/asm/amd_iommu_proto.h | 6 | ||||
| -rw-r--r-- | arch/x86/include/asm/amd_iommu_types.h | 12 | ||||
| -rw-r--r-- | arch/x86/kernel/amd_iommu.c | 4 | ||||
| -rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 67 | ||||
| -rw-r--r-- | include/linux/pci_ids.h | 3 |
5 files changed, 69 insertions, 23 deletions
diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h index d2544f1d705d..cb030374b90a 100644 --- a/arch/x86/include/asm/amd_iommu_proto.h +++ b/arch/x86/include/asm/amd_iommu_proto.h | |||
| @@ -38,4 +38,10 @@ static inline void amd_iommu_stats_init(void) { } | |||
| 38 | 38 | ||
| 39 | #endif /* !CONFIG_AMD_IOMMU_STATS */ | 39 | #endif /* !CONFIG_AMD_IOMMU_STATS */ |
| 40 | 40 | ||
| 41 | static inline bool is_rd890_iommu(struct pci_dev *pdev) | ||
| 42 | { | ||
| 43 | return (pdev->vendor == PCI_VENDOR_ID_ATI) && | ||
| 44 | (pdev->device == PCI_DEVICE_ID_RD890_IOMMU); | ||
| 45 | } | ||
| 46 | |||
| 41 | #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ | 47 | #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ |
diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 7014e88bc779..08616180deaf 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h | |||
| @@ -368,6 +368,9 @@ struct amd_iommu { | |||
| 368 | /* capabilities of that IOMMU read from ACPI */ | 368 | /* capabilities of that IOMMU read from ACPI */ |
| 369 | u32 cap; | 369 | u32 cap; |
| 370 | 370 | ||
| 371 | /* flags read from acpi table */ | ||
| 372 | u8 acpi_flags; | ||
| 373 | |||
| 371 | /* | 374 | /* |
| 372 | * Capability pointer. There could be more than one IOMMU per PCI | 375 | * Capability pointer. There could be more than one IOMMU per PCI |
| 373 | * device function if there are more than one AMD IOMMU capability | 376 | * device function if there are more than one AMD IOMMU capability |
| @@ -411,6 +414,15 @@ struct amd_iommu { | |||
| 411 | 414 | ||
| 412 | /* default dma_ops domain for that IOMMU */ | 415 | /* default dma_ops domain for that IOMMU */ |
| 413 | struct dma_ops_domain *default_dom; | 416 | struct dma_ops_domain *default_dom; |
| 417 | |||
| 418 | /* | ||
| 419 | * This array is required to work around a potential BIOS bug. | ||
| 420 | * The BIOS may miss to restore parts of the PCI configuration | ||
| 421 | * space when the system resumes from S3. The result is that the | ||
| 422 | * IOMMU does not execute commands anymore which leads to system | ||
| 423 | * failure. | ||
| 424 | */ | ||
| 425 | u32 cache_cfg[4]; | ||
| 414 | }; | 426 | }; |
| 415 | 427 | ||
| 416 | /* | 428 | /* |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index fa044e1e30a2..679b6450382b 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
| @@ -1953,6 +1953,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, | |||
| 1953 | size_t size, | 1953 | size_t size, |
| 1954 | int dir) | 1954 | int dir) |
| 1955 | { | 1955 | { |
| 1956 | dma_addr_t flush_addr; | ||
| 1956 | dma_addr_t i, start; | 1957 | dma_addr_t i, start; |
| 1957 | unsigned int pages; | 1958 | unsigned int pages; |
| 1958 | 1959 | ||
| @@ -1960,6 +1961,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, | |||
| 1960 | (dma_addr + size > dma_dom->aperture_size)) | 1961 | (dma_addr + size > dma_dom->aperture_size)) |
| 1961 | return; | 1962 | return; |
| 1962 | 1963 | ||
| 1964 | flush_addr = dma_addr; | ||
| 1963 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); | 1965 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); |
| 1964 | dma_addr &= PAGE_MASK; | 1966 | dma_addr &= PAGE_MASK; |
| 1965 | start = dma_addr; | 1967 | start = dma_addr; |
| @@ -1974,7 +1976,7 @@ static void __unmap_single(struct dma_ops_domain *dma_dom, | |||
| 1974 | dma_ops_free_addresses(dma_dom, dma_addr, pages); | 1976 | dma_ops_free_addresses(dma_dom, dma_addr, pages); |
| 1975 | 1977 | ||
| 1976 | if (amd_iommu_unmap_flush || dma_dom->need_flush) { | 1978 | if (amd_iommu_unmap_flush || dma_dom->need_flush) { |
| 1977 | iommu_flush_pages(&dma_dom->domain, dma_addr, size); | 1979 | iommu_flush_pages(&dma_dom->domain, flush_addr, size); |
| 1978 | dma_dom->need_flush = false; | 1980 | dma_dom->need_flush = false; |
| 1979 | } | 1981 | } |
| 1980 | } | 1982 | } |
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 3cc63e2b8dd4..5a170cbbbed8 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
| @@ -632,6 +632,13 @@ static void __init init_iommu_from_pci(struct amd_iommu *iommu) | |||
| 632 | iommu->last_device = calc_devid(MMIO_GET_BUS(range), | 632 | iommu->last_device = calc_devid(MMIO_GET_BUS(range), |
| 633 | MMIO_GET_LD(range)); | 633 | MMIO_GET_LD(range)); |
| 634 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); | 634 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); |
| 635 | |||
| 636 | if (is_rd890_iommu(iommu->dev)) { | ||
| 637 | pci_read_config_dword(iommu->dev, 0xf0, &iommu->cache_cfg[0]); | ||
| 638 | pci_read_config_dword(iommu->dev, 0xf4, &iommu->cache_cfg[1]); | ||
| 639 | pci_read_config_dword(iommu->dev, 0xf8, &iommu->cache_cfg[2]); | ||
| 640 | pci_read_config_dword(iommu->dev, 0xfc, &iommu->cache_cfg[3]); | ||
| 641 | } | ||
| 635 | } | 642 | } |
| 636 | 643 | ||
| 637 | /* | 644 | /* |
| @@ -649,29 +656,9 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
| 649 | struct ivhd_entry *e; | 656 | struct ivhd_entry *e; |
| 650 | 657 | ||
| 651 | /* | 658 | /* |
| 652 | * First set the recommended feature enable bits from ACPI | 659 | * First save the recommended feature enable bits from ACPI |
| 653 | * into the IOMMU control registers | ||
| 654 | */ | 660 | */ |
| 655 | h->flags & IVHD_FLAG_HT_TUN_EN_MASK ? | 661 | iommu->acpi_flags = h->flags; |
| 656 | iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : | ||
| 657 | iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); | ||
| 658 | |||
| 659 | h->flags & IVHD_FLAG_PASSPW_EN_MASK ? | ||
| 660 | iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : | ||
| 661 | iommu_feature_disable(iommu, CONTROL_PASSPW_EN); | ||
| 662 | |||
| 663 | h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ? | ||
| 664 | iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : | ||
| 665 | iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); | ||
| 666 | |||
| 667 | h->flags & IVHD_FLAG_ISOC_EN_MASK ? | ||
| 668 | iommu_feature_enable(iommu, CONTROL_ISOC_EN) : | ||
| 669 | iommu_feature_disable(iommu, CONTROL_ISOC_EN); | ||
| 670 | |||
| 671 | /* | ||
| 672 | * make IOMMU memory accesses cache coherent | ||
| 673 | */ | ||
| 674 | iommu_feature_enable(iommu, CONTROL_COHERENT_EN); | ||
| 675 | 662 | ||
| 676 | /* | 663 | /* |
| 677 | * Done. Now parse the device entries | 664 | * Done. Now parse the device entries |
| @@ -1116,6 +1103,40 @@ static void init_device_table(void) | |||
| 1116 | } | 1103 | } |
| 1117 | } | 1104 | } |
| 1118 | 1105 | ||
| 1106 | static void iommu_init_flags(struct amd_iommu *iommu) | ||
| 1107 | { | ||
| 1108 | iommu->acpi_flags & IVHD_FLAG_HT_TUN_EN_MASK ? | ||
| 1109 | iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : | ||
| 1110 | iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); | ||
| 1111 | |||
| 1112 | iommu->acpi_flags & IVHD_FLAG_PASSPW_EN_MASK ? | ||
| 1113 | iommu_feature_enable(iommu, CONTROL_PASSPW_EN) : | ||
| 1114 | iommu_feature_disable(iommu, CONTROL_PASSPW_EN); | ||
| 1115 | |||
| 1116 | iommu->acpi_flags & IVHD_FLAG_RESPASSPW_EN_MASK ? | ||
| 1117 | iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) : | ||
| 1118 | iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN); | ||
| 1119 | |||
| 1120 | iommu->acpi_flags & IVHD_FLAG_ISOC_EN_MASK ? | ||
| 1121 | iommu_feature_enable(iommu, CONTROL_ISOC_EN) : | ||
| 1122 | iommu_feature_disable(iommu, CONTROL_ISOC_EN); | ||
| 1123 | |||
| 1124 | /* | ||
| 1125 | * make IOMMU memory accesses cache coherent | ||
| 1126 | */ | ||
| 1127 | iommu_feature_enable(iommu, CONTROL_COHERENT_EN); | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | static void iommu_apply_quirks(struct amd_iommu *iommu) | ||
| 1131 | { | ||
| 1132 | if (is_rd890_iommu(iommu->dev)) { | ||
| 1133 | pci_write_config_dword(iommu->dev, 0xf0, iommu->cache_cfg[0]); | ||
| 1134 | pci_write_config_dword(iommu->dev, 0xf4, iommu->cache_cfg[1]); | ||
| 1135 | pci_write_config_dword(iommu->dev, 0xf8, iommu->cache_cfg[2]); | ||
| 1136 | pci_write_config_dword(iommu->dev, 0xfc, iommu->cache_cfg[3]); | ||
| 1137 | } | ||
| 1138 | } | ||
| 1139 | |||
| 1119 | /* | 1140 | /* |
| 1120 | * This function finally enables all IOMMUs found in the system after | 1141 | * This function finally enables all IOMMUs found in the system after |
| 1121 | * they have been initialized | 1142 | * they have been initialized |
| @@ -1126,6 +1147,8 @@ static void enable_iommus(void) | |||
| 1126 | 1147 | ||
| 1127 | for_each_iommu(iommu) { | 1148 | for_each_iommu(iommu) { |
| 1128 | iommu_disable(iommu); | 1149 | iommu_disable(iommu); |
| 1150 | iommu_apply_quirks(iommu); | ||
| 1151 | iommu_init_flags(iommu); | ||
| 1129 | iommu_set_device_table(iommu); | 1152 | iommu_set_device_table(iommu); |
| 1130 | iommu_enable_command_buffer(iommu); | 1153 | iommu_enable_command_buffer(iommu); |
| 1131 | iommu_enable_event_buffer(iommu); | 1154 | iommu_enable_event_buffer(iommu); |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 10d33309e9a6..570fddeb0388 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -393,6 +393,9 @@ | |||
| 393 | #define PCI_DEVICE_ID_VLSI_82C147 0x0105 | 393 | #define PCI_DEVICE_ID_VLSI_82C147 0x0105 |
| 394 | #define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 | 394 | #define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 |
| 395 | 395 | ||
| 396 | /* AMD RD890 Chipset */ | ||
| 397 | #define PCI_DEVICE_ID_RD890_IOMMU 0x5a23 | ||
| 398 | |||
| 396 | #define PCI_VENDOR_ID_ADL 0x1005 | 399 | #define PCI_VENDOR_ID_ADL 0x1005 |
| 397 | #define PCI_DEVICE_ID_ADL_2301 0x2301 | 400 | #define PCI_DEVICE_ID_ADL_2301 0x2301 |
| 398 | 401 | ||
