diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2011-11-10 09:41:40 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2011-12-12 08:54:37 -0500 |
commit | 1a29ac014a68e5da8f96d5d8d142b5956eb00b7c (patch) | |
tree | c0b88ba4f1771eb89e8252bdc0542f60e1e5da03 /drivers/iommu/amd_iommu_init.c | |
parent | 62f71abbc64d686064a4caa10a3249c26776995e (diff) |
iommu/amd: Setup PPR log when supported by IOMMU
Allocate and enable a log buffer for peripheral page faults
when the IOMMU supports this feature.
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 | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index fb4afd6d357d..60716cefa7af 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -583,6 +583,46 @@ static void __init free_event_buffer(struct amd_iommu *iommu) | |||
583 | free_pages((unsigned long)iommu->evt_buf, get_order(EVT_BUFFER_SIZE)); | 583 | free_pages((unsigned long)iommu->evt_buf, get_order(EVT_BUFFER_SIZE)); |
584 | } | 584 | } |
585 | 585 | ||
586 | /* allocates the memory where the IOMMU will log its events to */ | ||
587 | static u8 * __init alloc_ppr_log(struct amd_iommu *iommu) | ||
588 | { | ||
589 | iommu->ppr_log = (u8 *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | ||
590 | get_order(PPR_LOG_SIZE)); | ||
591 | |||
592 | if (iommu->ppr_log == NULL) | ||
593 | return NULL; | ||
594 | |||
595 | return iommu->ppr_log; | ||
596 | } | ||
597 | |||
598 | static void iommu_enable_ppr_log(struct amd_iommu *iommu) | ||
599 | { | ||
600 | u64 entry; | ||
601 | |||
602 | if (iommu->ppr_log == NULL) | ||
603 | return; | ||
604 | |||
605 | entry = (u64)virt_to_phys(iommu->ppr_log) | PPR_LOG_SIZE_512; | ||
606 | |||
607 | memcpy_toio(iommu->mmio_base + MMIO_PPR_LOG_OFFSET, | ||
608 | &entry, sizeof(entry)); | ||
609 | |||
610 | /* set head and tail to zero manually */ | ||
611 | writel(0x00, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); | ||
612 | writel(0x00, iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); | ||
613 | |||
614 | iommu_feature_enable(iommu, CONTROL_PPFLOG_EN); | ||
615 | iommu_feature_enable(iommu, CONTROL_PPR_EN); | ||
616 | } | ||
617 | |||
618 | static void __init free_ppr_log(struct amd_iommu *iommu) | ||
619 | { | ||
620 | if (iommu->ppr_log == NULL) | ||
621 | return; | ||
622 | |||
623 | free_pages((unsigned long)iommu->ppr_log, get_order(PPR_LOG_SIZE)); | ||
624 | } | ||
625 | |||
586 | /* sets a specific bit in the device table entry. */ | 626 | /* sets a specific bit in the device table entry. */ |
587 | static void set_dev_entry_bit(u16 devid, u8 bit) | 627 | static void set_dev_entry_bit(u16 devid, u8 bit) |
588 | { | 628 | { |
@@ -914,6 +954,7 @@ static void __init free_iommu_one(struct amd_iommu *iommu) | |||
914 | { | 954 | { |
915 | free_command_buffer(iommu); | 955 | free_command_buffer(iommu); |
916 | free_event_buffer(iommu); | 956 | free_event_buffer(iommu); |
957 | free_ppr_log(iommu); | ||
917 | iommu_unmap_mmio_space(iommu); | 958 | iommu_unmap_mmio_space(iommu); |
918 | } | 959 | } |
919 | 960 | ||
@@ -977,6 +1018,12 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
977 | init_iommu_from_acpi(iommu, h); | 1018 | init_iommu_from_acpi(iommu, h); |
978 | init_iommu_devices(iommu); | 1019 | init_iommu_devices(iommu); |
979 | 1020 | ||
1021 | if (iommu_feature(iommu, FEATURE_PPR)) { | ||
1022 | iommu->ppr_log = alloc_ppr_log(iommu); | ||
1023 | if (!iommu->ppr_log) | ||
1024 | return -ENOMEM; | ||
1025 | } | ||
1026 | |||
980 | if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) | 1027 | if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) |
981 | amd_iommu_np_cache = true; | 1028 | amd_iommu_np_cache = true; |
982 | 1029 | ||
@@ -1063,6 +1110,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu) | |||
1063 | iommu->int_enabled = true; | 1110 | iommu->int_enabled = true; |
1064 | iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); | 1111 | iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); |
1065 | 1112 | ||
1113 | if (iommu->ppr_log != NULL) | ||
1114 | iommu_feature_enable(iommu, CONTROL_PPFINT_EN); | ||
1115 | |||
1066 | return 0; | 1116 | return 0; |
1067 | } | 1117 | } |
1068 | 1118 | ||
@@ -1287,6 +1337,7 @@ static void enable_iommus(void) | |||
1287 | iommu_set_device_table(iommu); | 1337 | iommu_set_device_table(iommu); |
1288 | iommu_enable_command_buffer(iommu); | 1338 | iommu_enable_command_buffer(iommu); |
1289 | iommu_enable_event_buffer(iommu); | 1339 | iommu_enable_event_buffer(iommu); |
1340 | iommu_enable_ppr_log(iommu); | ||
1290 | iommu_set_exclusion_range(iommu); | 1341 | iommu_set_exclusion_range(iommu); |
1291 | iommu_init_msi(iommu); | 1342 | iommu_init_msi(iommu); |
1292 | iommu_enable(iommu); | 1343 | iommu_enable(iommu); |