[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen stable-4.1] iommu/amd: Fix logic for clearing the IOMMU interrupt bits
commit 0d57d46c71ded043c14b39660c7eeddb96c650a9 Author: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> AuthorDate: Thu Jul 11 15:09:49 2013 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Jul 11 15:09:49 2013 +0200 iommu/amd: Fix logic for clearing the IOMMU interrupt bits The IOMMU interrupt bits in the IOMMU status registers are "read-only, and write-1-to-clear (RW1C). Therefore, the existing logic which reads the register, set the bit, and then writing back the values could accidentally clear certain bits if it has been set. The correct logic would just be writing only the value which only set the interrupt bits, and leave the rest to zeros. This patch also, clean up #define masks as Jan has suggested. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> With iommu_interrupt_handler() properly having got switched its readl() from status to control register, the subsequent writel() needed to be switched too (and the RW1C comment there was bogus). Some of the cleanup went too far - undone. Further, with iommu_interrupt_handler() now actually disabling the interrupt sources, they also need to get re-enabled by the tasklet once it finished processing the respective log. This also implies re-running the tasklet so that log entries added between reading the log and re- enabling the interrupt will get handled in a timely manner. Finally, guest write emulation to the status register needs to be done with the RW1C (and RO for all other bits) semantics in mind too. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Tim Deegan <tim@xxxxxxx> Acked-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> master commit: 2823a0c7dfc979db316787e1dd42a8845e5825c0 master date: 2013-07-02 08:49:43 +0200 --- xen/drivers/passthrough/amd/iommu_init.c | 46 +++++++++++++++++++----------- 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 fcb7e87..b87b613 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 a65e01a..ea1f273 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"); -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.1 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |