Commit 7329cf0201f48695862e334828a108aa7175e955
Exists in
master
and in
4 other branches
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
Showing 5 changed files Side-by-side Diff
arch/x86/include/asm/amd_iommu_proto.h
... | ... | @@ -38,5 +38,11 @@ |
38 | 38 | |
39 | 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 | 47 | #endif /* _ASM_X86_AMD_IOMMU_PROTO_H */ |
arch/x86/include/asm/amd_iommu_types.h
... | ... | @@ -368,6 +368,9 @@ |
368 | 368 | /* capabilities of that IOMMU read from ACPI */ |
369 | 369 | u32 cap; |
370 | 370 | |
371 | + /* flags read from acpi table */ | |
372 | + u8 acpi_flags; | |
373 | + | |
371 | 374 | /* |
372 | 375 | * Capability pointer. There could be more than one IOMMU per PCI |
373 | 376 | * device function if there are more than one AMD IOMMU capability |
... | ... | @@ -411,6 +414,15 @@ |
411 | 414 | |
412 | 415 | /* default dma_ops domain for that IOMMU */ |
413 | 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 | /* |
arch/x86/kernel/amd_iommu.c
... | ... | @@ -1953,6 +1953,7 @@ |
1953 | 1953 | size_t size, |
1954 | 1954 | int dir) |
1955 | 1955 | { |
1956 | + dma_addr_t flush_addr; | |
1956 | 1957 | dma_addr_t i, start; |
1957 | 1958 | unsigned int pages; |
1958 | 1959 | |
... | ... | @@ -1960,6 +1961,7 @@ |
1960 | 1961 | (dma_addr + size > dma_dom->aperture_size)) |
1961 | 1962 | return; |
1962 | 1963 | |
1964 | + flush_addr = dma_addr; | |
1963 | 1965 | pages = iommu_num_pages(dma_addr, size, PAGE_SIZE); |
1964 | 1966 | dma_addr &= PAGE_MASK; |
1965 | 1967 | start = dma_addr; |
... | ... | @@ -1974,7 +1976,7 @@ |
1974 | 1976 | dma_ops_free_addresses(dma_dom, dma_addr, pages); |
1975 | 1977 | |
1976 | 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 | 1980 | dma_dom->need_flush = false; |
1979 | 1981 | } |
1980 | 1982 | } |
arch/x86/kernel/amd_iommu_init.c
... | ... | @@ -632,6 +632,13 @@ |
632 | 632 | iommu->last_device = calc_devid(MMIO_GET_BUS(range), |
633 | 633 | MMIO_GET_LD(range)); |
634 | 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 | /* |
638 | 645 | |
639 | 646 | |
640 | 647 | |
... | ... | @@ -649,31 +656,11 @@ |
649 | 656 | struct ivhd_entry *e; |
650 | 657 | |
651 | 658 | /* |
652 | - * First set the recommended feature enable bits from ACPI | |
653 | - * into the IOMMU control registers | |
659 | + * First save the recommended feature enable bits from ACPI | |
654 | 660 | */ |
655 | - h->flags & IVHD_FLAG_HT_TUN_EN_MASK ? | |
656 | - iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) : | |
657 | - iommu_feature_disable(iommu, CONTROL_HT_TUN_EN); | |
661 | + iommu->acpi_flags = h->flags; | |
658 | 662 | |
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 | 663 | /* |
672 | - * make IOMMU memory accesses cache coherent | |
673 | - */ | |
674 | - iommu_feature_enable(iommu, CONTROL_COHERENT_EN); | |
675 | - | |
676 | - /* | |
677 | 664 | * Done. Now parse the device entries |
678 | 665 | */ |
679 | 666 | p += sizeof(struct ivhd_header); |
... | ... | @@ -1116,6 +1103,40 @@ |
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 | 1141 | * This function finally enables all IOMMUs found in the system after |
1121 | 1142 | * they have been initialized |
... | ... | @@ -1126,6 +1147,8 @@ |
1126 | 1147 | |
1127 | 1148 | for_each_iommu(iommu) { |
1128 | 1149 | iommu_disable(iommu); |
1150 | + iommu_apply_quirks(iommu); | |
1151 | + iommu_init_flags(iommu); | |
1129 | 1152 | iommu_set_device_table(iommu); |
1130 | 1153 | iommu_enable_command_buffer(iommu); |
1131 | 1154 | iommu_enable_event_buffer(iommu); |
include/linux/pci_ids.h
... | ... | @@ -393,6 +393,9 @@ |
393 | 393 | #define PCI_DEVICE_ID_VLSI_82C147 0x0105 |
394 | 394 | #define PCI_DEVICE_ID_VLSI_VAS96011 0x0702 |
395 | 395 | |
396 | +/* AMD RD890 Chipset */ | |
397 | +#define PCI_DEVICE_ID_RD890_IOMMU 0x5a23 | |
398 | + | |
396 | 399 | #define PCI_VENDOR_ID_ADL 0x1005 |
397 | 400 | #define PCI_DEVICE_ID_ADL_2301 0x2301 |
398 | 401 |