aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/amd_iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2009-09-03 09:01:43 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2009-09-03 09:55:34 -0400
commita345b23b79f1900e7d87c3165182504419180de4 (patch)
tree4dc0b858369520bc2125ba9bde9f388edc0777dd /arch/x86/kernel/amd_iommu.c
parent93f1cc67cf3196174412adca87321b25c1c986b0 (diff)
x86/amd-iommu: Reset command buffer on ILLEGAL_COMMAND_ERROR
On an ILLEGAL_COMMAND_ERROR the IOMMU stops executing further commands. This patch changes the code to handle this case better by resetting the command buffer in the IOMMU. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'arch/x86/kernel/amd_iommu.c')
-rw-r--r--arch/x86/kernel/amd_iommu.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 2dc093370d2d..2333d615f5ee 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -61,6 +61,7 @@ static u64* alloc_pte(struct protection_domain *dom,
61static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, 61static void dma_ops_reserve_addresses(struct dma_ops_domain *dom,
62 unsigned long start_page, 62 unsigned long start_page,
63 unsigned int pages); 63 unsigned int pages);
64static void reset_iommu_command_buffer(struct amd_iommu *iommu);
64 65
65#ifndef BUS_NOTIFY_UNBOUND_DRIVER 66#ifndef BUS_NOTIFY_UNBOUND_DRIVER
66#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005 67#define BUS_NOTIFY_UNBOUND_DRIVER 0x0005
@@ -156,7 +157,7 @@ static void dump_command(unsigned long phys_addr)
156 pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]); 157 pr_err("AMD-Vi: CMD[%d]: %08x\n", i, cmd->data[i]);
157} 158}
158 159
159static void iommu_print_event(void *__evt) 160static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
160{ 161{
161 u32 *event = __evt; 162 u32 *event = __evt;
162 int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; 163 int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
@@ -195,6 +196,7 @@ static void iommu_print_event(void *__evt)
195 break; 196 break;
196 case EVENT_TYPE_ILL_CMD: 197 case EVENT_TYPE_ILL_CMD:
197 printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); 198 printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
199 reset_iommu_command_buffer(iommu);
198 dump_command(address); 200 dump_command(address);
199 break; 201 break;
200 case EVENT_TYPE_CMD_HARD_ERR: 202 case EVENT_TYPE_CMD_HARD_ERR:
@@ -229,7 +231,7 @@ static void iommu_poll_events(struct amd_iommu *iommu)
229 tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); 231 tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
230 232
231 while (head != tail) { 233 while (head != tail) {
232 iommu_print_event(iommu->evt_buf + head); 234 iommu_print_event(iommu, iommu->evt_buf + head);
233 head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size; 235 head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
234 } 236 }
235 237
@@ -547,6 +549,15 @@ void amd_iommu_flush_all_devices(void)
547 } 549 }
548} 550}
549 551
552static void reset_iommu_command_buffer(struct amd_iommu *iommu)
553{
554 pr_err("AMD-Vi: Resetting IOMMU command buffer\n");
555
556 amd_iommu_reset_cmd_buffer(iommu);
557 flush_all_devices_for_iommu(iommu);
558 flush_all_domains_on_iommu(iommu);
559}
560
550/**************************************************************************** 561/****************************************************************************
551 * 562 *
552 * The functions below are used the create the page table mappings for 563 * The functions below are used the create the page table mappings for