diff options
Diffstat (limited to 'arch/x86/kernel/amd_iommu_init.c')
-rw-r--r-- | arch/x86/kernel/amd_iommu_init.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 238989ec077d..c1b17e97252e 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -260,6 +260,14 @@ static void iommu_enable(struct amd_iommu *iommu) | |||
260 | 260 | ||
261 | static void iommu_disable(struct amd_iommu *iommu) | 261 | static void iommu_disable(struct amd_iommu *iommu) |
262 | { | 262 | { |
263 | /* Disable command buffer */ | ||
264 | iommu_feature_disable(iommu, CONTROL_CMDBUF_EN); | ||
265 | |||
266 | /* Disable event logging and event interrupts */ | ||
267 | iommu_feature_disable(iommu, CONTROL_EVT_INT_EN); | ||
268 | iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN); | ||
269 | |||
270 | /* Disable IOMMU hardware itself */ | ||
263 | iommu_feature_disable(iommu, CONTROL_IOMMU_EN); | 271 | iommu_feature_disable(iommu, CONTROL_IOMMU_EN); |
264 | } | 272 | } |
265 | 273 | ||
@@ -464,6 +472,8 @@ static u8 * __init alloc_event_buffer(struct amd_iommu *iommu) | |||
464 | if (iommu->evt_buf == NULL) | 472 | if (iommu->evt_buf == NULL) |
465 | return NULL; | 473 | return NULL; |
466 | 474 | ||
475 | iommu->evt_buf_size = EVT_BUFFER_SIZE; | ||
476 | |||
467 | return iommu->evt_buf; | 477 | return iommu->evt_buf; |
468 | } | 478 | } |
469 | 479 | ||
@@ -478,6 +488,10 @@ static void iommu_enable_event_buffer(struct amd_iommu *iommu) | |||
478 | memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET, | 488 | memcpy_toio(iommu->mmio_base + MMIO_EVT_BUF_OFFSET, |
479 | &entry, sizeof(entry)); | 489 | &entry, sizeof(entry)); |
480 | 490 | ||
491 | /* set head and tail to zero manually */ | ||
492 | writel(0x00, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); | ||
493 | writel(0x00, iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); | ||
494 | |||
481 | iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN); | 495 | iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN); |
482 | } | 496 | } |
483 | 497 | ||
@@ -679,6 +693,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
679 | 693 | ||
680 | devid = e->devid; | 694 | devid = e->devid; |
681 | devid_to = e->ext >> 8; | 695 | devid_to = e->ext >> 8; |
696 | set_dev_entry_from_acpi(iommu, devid , e->flags, 0); | ||
682 | set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); | 697 | set_dev_entry_from_acpi(iommu, devid_to, e->flags, 0); |
683 | amd_iommu_alias_table[devid] = devid_to; | 698 | amd_iommu_alias_table[devid] = devid_to; |
684 | break; | 699 | break; |
@@ -737,11 +752,13 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu, | |||
737 | 752 | ||
738 | devid = e->devid; | 753 | devid = e->devid; |
739 | for (dev_i = devid_start; dev_i <= devid; ++dev_i) { | 754 | for (dev_i = devid_start; dev_i <= devid; ++dev_i) { |
740 | if (alias) | 755 | if (alias) { |
741 | amd_iommu_alias_table[dev_i] = devid_to; | 756 | amd_iommu_alias_table[dev_i] = devid_to; |
742 | set_dev_entry_from_acpi(iommu, | 757 | set_dev_entry_from_acpi(iommu, |
743 | amd_iommu_alias_table[dev_i], | 758 | devid_to, flags, ext_flags); |
744 | flags, ext_flags); | 759 | } |
760 | set_dev_entry_from_acpi(iommu, dev_i, | ||
761 | flags, ext_flags); | ||
745 | } | 762 | } |
746 | break; | 763 | break; |
747 | default: | 764 | default: |
@@ -1042,6 +1059,7 @@ static void enable_iommus(void) | |||
1042 | struct amd_iommu *iommu; | 1059 | struct amd_iommu *iommu; |
1043 | 1060 | ||
1044 | for_each_iommu(iommu) { | 1061 | for_each_iommu(iommu) { |
1062 | iommu_disable(iommu); | ||
1045 | iommu_set_device_table(iommu); | 1063 | iommu_set_device_table(iommu); |
1046 | iommu_enable_command_buffer(iommu); | 1064 | iommu_enable_command_buffer(iommu); |
1047 | iommu_enable_event_buffer(iommu); | 1065 | iommu_enable_event_buffer(iommu); |
@@ -1066,12 +1084,6 @@ static void disable_iommus(void) | |||
1066 | 1084 | ||
1067 | static int amd_iommu_resume(struct sys_device *dev) | 1085 | static int amd_iommu_resume(struct sys_device *dev) |
1068 | { | 1086 | { |
1069 | /* | ||
1070 | * Disable IOMMUs before reprogramming the hardware registers. | ||
1071 | * IOMMU is still enabled from the resume kernel. | ||
1072 | */ | ||
1073 | disable_iommus(); | ||
1074 | |||
1075 | /* re-load the hardware */ | 1087 | /* re-load the hardware */ |
1076 | enable_iommus(); | 1088 | enable_iommus(); |
1077 | 1089 | ||
@@ -1079,8 +1091,8 @@ static int amd_iommu_resume(struct sys_device *dev) | |||
1079 | * we have to flush after the IOMMUs are enabled because a | 1091 | * we have to flush after the IOMMUs are enabled because a |
1080 | * disabled IOMMU will never execute the commands we send | 1092 | * disabled IOMMU will never execute the commands we send |
1081 | */ | 1093 | */ |
1082 | amd_iommu_flush_all_domains(); | ||
1083 | amd_iommu_flush_all_devices(); | 1094 | amd_iommu_flush_all_devices(); |
1095 | amd_iommu_flush_all_domains(); | ||
1084 | 1096 | ||
1085 | return 0; | 1097 | return 0; |
1086 | } | 1098 | } |
@@ -1273,6 +1285,11 @@ free: | |||
1273 | goto out; | 1285 | goto out; |
1274 | } | 1286 | } |
1275 | 1287 | ||
1288 | void amd_iommu_shutdown(void) | ||
1289 | { | ||
1290 | disable_iommus(); | ||
1291 | } | ||
1292 | |||
1276 | /**************************************************************************** | 1293 | /**************************************************************************** |
1277 | * | 1294 | * |
1278 | * Early detect code. This code runs at IOMMU detection time in the DMA | 1295 | * Early detect code. This code runs at IOMMU detection time in the DMA |