diff options
-rw-r--r-- | arch/x86/include/asm/amd_iommu_proto.h | 6 | ||||
-rw-r--r-- | arch/x86/include/asm/amd_iommu_types.h | 9 | ||||
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 18 | ||||
-rw-r--r-- | include/linux/pci_ids.h | 3 |
4 files changed, 36 insertions, 0 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 ef2d5cd7d7e7..08616180deaf 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h | |||
@@ -414,6 +414,15 @@ struct amd_iommu { | |||
414 | 414 | ||
415 | /* default dma_ops domain for that IOMMU */ | 415 | /* default dma_ops domain for that IOMMU */ |
416 | 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]; | ||
417 | }; | 426 | }; |
418 | 427 | ||
419 | /* | 428 | /* |
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 85e9817ead43..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 | /* |
@@ -1120,6 +1127,16 @@ static void iommu_init_flags(struct amd_iommu *iommu) | |||
1120 | iommu_feature_enable(iommu, CONTROL_COHERENT_EN); | 1127 | iommu_feature_enable(iommu, CONTROL_COHERENT_EN); |
1121 | } | 1128 | } |
1122 | 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 | |||
1123 | /* | 1140 | /* |
1124 | * This function finally enables all IOMMUs found in the system after | 1141 | * This function finally enables all IOMMUs found in the system after |
1125 | * they have been initialized | 1142 | * they have been initialized |
@@ -1130,6 +1147,7 @@ static void enable_iommus(void) | |||
1130 | 1147 | ||
1131 | for_each_iommu(iommu) { | 1148 | for_each_iommu(iommu) { |
1132 | iommu_disable(iommu); | 1149 | iommu_disable(iommu); |
1150 | iommu_apply_quirks(iommu); | ||
1133 | iommu_init_flags(iommu); | 1151 | iommu_init_flags(iommu); |
1134 | iommu_set_device_table(iommu); | 1152 | iommu_set_device_table(iommu); |
1135 | iommu_enable_command_buffer(iommu); | 1153 | iommu_enable_command_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 | ||