diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-27 15:22:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-27 15:22:21 -0400 |
commit | 6a6aa2b7e47c725b5256ff0f7462fe1247cabf5a (patch) | |
tree | dcd8e549193e7aedcdcfb34c13177eceda5b29f4 /arch/x86 | |
parent | f0619343ce782a731f55b8ba06d9a7e7d28a0fb8 (diff) | |
parent | 7329cf0201f48695862e334828a108aa7175e955 (diff) |
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86/amd-iommu: Fix rounding-bug in __unmap_single
x86/amd-iommu: Work around S3 BIOS bug
x86/amd-iommu: Set iommu configuration flags in enable-loop
x86, setup: Fix earlyprintk=serial,0x3f8,115200
x86, setup: Fix earlyprintk=serial,ttyS0,115200
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/boot/early_serial_console.c | 14 | ||||
-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 |
5 files changed, 79 insertions, 24 deletions
diff --git a/arch/x86/boot/early_serial_console.c b/arch/x86/boot/early_serial_console.c index 030f4b93e255..5df2869c874b 100644 --- a/arch/x86/boot/early_serial_console.c +++ b/arch/x86/boot/early_serial_console.c | |||
@@ -58,7 +58,19 @@ static void parse_earlyprintk(void) | |||
58 | if (arg[pos] == ',') | 58 | if (arg[pos] == ',') |
59 | pos++; | 59 | pos++; |
60 | 60 | ||
61 | if (!strncmp(arg, "ttyS", 4)) { | 61 | /* |
62 | * make sure we have | ||
63 | * "serial,0x3f8,115200" | ||
64 | * "serial,ttyS0,115200" | ||
65 | * "ttyS0,115200" | ||
66 | */ | ||
67 | if (pos == 7 && !strncmp(arg + pos, "0x", 2)) { | ||
68 | port = simple_strtoull(arg + pos, &e, 16); | ||
69 | if (port == 0 || arg + pos == e) | ||
70 | port = DEFAULT_SERIAL_PORT; | ||
71 | else | ||
72 | pos = e - arg; | ||
73 | } else if (!strncmp(arg + pos, "ttyS", 4)) { | ||
62 | static const int bases[] = { 0x3f8, 0x2f8 }; | 74 | static const int bases[] = { 0x3f8, 0x2f8 }; |
63 | int idx = 0; | 75 | int idx = 0; |
64 | 76 | ||
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); |