aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/drivers/passthrough/amd/iommu_init.c46
-rw-r--r--xen/drivers/passthrough/amd/iommu_map.c14
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");