diff options
-rw-r--r-- | xen/drivers/passthrough/amd/iommu_init.c | 46 | ||||
-rw-r--r-- | xen/drivers/passthrough/amd/iommu_map.c | 14 |
2 files changed, 35 insertions, 25 deletions
diff --git a/xen/drivers/passthrough/amd/iommu_init.c b/xen/drivers/passthrough/amd/iommu_init.c index fcb7e87f5f..b87b61301c 100644 --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -336,11 +336,9 @@ static void amd_iommu_reset_event_log(struct amd_iommu *iommu) /* read event log for debugging */ amd_iommu_read_event_log(iommu); - /*clear overflow bit */ - set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry, - IOMMU_STATUS_EVENT_OVERFLOW_MASK, - IOMMU_STATUS_EVENT_OVERFLOW_SHIFT, &entry); - writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET); + /* RW1C overflow bit */ + writel(IOMMU_STATUS_EVENT_OVERFLOW_MASK, + iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); /*reset event log base address */ iommu->event_log_head = 0; @@ -564,6 +562,11 @@ static void do_amd_iommu_irq(unsigned long data) int of; spin_lock_irqsave(&iommu->lock, flags); + + /* RW1C interrupt status bit */ + writel(IOMMU_STATUS_EVENT_LOG_INT_MASK, + iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); + amd_iommu_read_event_log(iommu); /* check event overflow */ @@ -575,13 +578,21 @@ static void do_amd_iommu_irq(unsigned long data) /* reset event log if event overflow */ if ( of ) amd_iommu_reset_event_log(iommu); + else + { + entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); + if ( !(entry & IOMMU_CONTROL_EVENT_LOG_INT_MASK) ) + { + entry |= IOMMU_CONTROL_EVENT_LOG_INT_MASK; + writel(entry, iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); + /* + * Re-schedule the tasklet to handle eventual log entries added + * between reading the log above and re-enabling the interrupt. + */ + tasklet_schedule(&amd_iommu_irq_tasklet); + } + } - /* reset interrupt status bit */ - entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_STATUS_EVENT_LOG_INT_MASK, - IOMMU_STATUS_EVENT_LOG_INT_SHIFT, &entry); - writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET); spin_unlock_irqrestore(&iommu->lock, flags); } } @@ -595,12 +606,13 @@ static void amd_iommu_page_fault(int irq, void *dev_id, spin_lock_irqsave(&iommu->lock, flags); - /* Silence interrupts from both event logging */ - entry = readl(iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); - set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry, - IOMMU_STATUS_EVENT_LOG_INT_MASK, - IOMMU_STATUS_EVENT_LOG_INT_SHIFT, &entry); - writel(entry, iommu->mmio_base+IOMMU_STATUS_MMIO_OFFSET); + /* + * Silence interrupts from both event and PPR by clearing the + * enable logging bits in the control register + */ + entry = readl(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); + entry &= ~IOMMU_CONTROL_EVENT_LOG_INT_MASK; + writel(entry, iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET); spin_unlock_irqrestore(&iommu->lock, flags); diff --git a/xen/drivers/passthrough/amd/iommu_map.c b/xen/drivers/passthrough/amd/iommu_map.c index a65e01ac1f..ea1f2733ce 100644 --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -131,11 +131,9 @@ void flush_command_buffer(struct amd_iommu *iommu) u32 cmd[4], status; int loop_count, comp_wait; - /* clear 'ComWaitInt' in status register (WIC) */ - set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0, - IOMMU_STATUS_COMP_WAIT_INT_MASK, - IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status); - writel(status, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); + /* RW1C 'ComWaitInt' in status register */ + writel(IOMMU_STATUS_COMP_WAIT_INT_MASK, + iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); /* send an empty COMPLETION_WAIT command to flush command buffer */ cmd[3] = cmd[2] = 0; @@ -159,9 +157,9 @@ void flush_command_buffer(struct amd_iommu *iommu) if ( comp_wait ) { - /* clear 'ComWaitInt' in status register (WIC) */ - status &= IOMMU_STATUS_COMP_WAIT_INT_MASK; - writel(status, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); + /* RW1C 'ComWaitInt' in status register */ + writel(IOMMU_STATUS_COMP_WAIT_INT_MASK, + iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); return; } AMD_IOMMU_DEBUG("Warning: ComWaitInt bit did not assert!\n"); |