irqreturn_t amd_iommu_int_thread(int irq, void *data)
{
- --- struct amd_iommu *iommu;
+ +++ struct amd_iommu *iommu = (struct amd_iommu *) data;
+ +++ u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
- --- for_each_iommu(iommu) {
- --- iommu_poll_events(iommu);
- --- iommu_poll_ppr_log(iommu);
- --- }
+ +++ while (status & (MMIO_STATUS_EVT_INT_MASK | MMIO_STATUS_PPR_INT_MASK)) {
+ +++ /* Enable EVT and PPR interrupts again */
+ +++ writel((MMIO_STATUS_EVT_INT_MASK | MMIO_STATUS_PPR_INT_MASK),
+ +++ iommu->mmio_base + MMIO_STATUS_OFFSET);
+ +
+ +++ if (status & MMIO_STATUS_EVT_INT_MASK) {
+ +++ pr_devel("AMD-Vi: Processing IOMMU Event Log\n");
+ +++ iommu_poll_events(iommu);
+ +++ }
+ + +
+ +++ if (status & MMIO_STATUS_PPR_INT_MASK) {
+ +++ pr_devel("AMD-Vi: Processing IOMMU PPR Log\n");
+ +++ iommu_poll_ppr_log(iommu);
+ +++ }
+++
+ +++ /*
+ +++ * Hardware bug: ERBT1312
+ +++ * When re-enabling interrupt (by writing 1
+ +++ * to clear the bit), the hardware might also try to set
+ +++ * the interrupt bit in the event status register.
+ +++ * In this scenario, the bit will be set, and disable
+ +++ * subsequent interrupts.
+ +++ *
+ +++ * Workaround: The IOMMU driver should read back the
+ +++ * status register and check if the interrupt bits are cleared.
+ +++ * If not, driver will need to go through the interrupt handler
+ +++ * again and re-clear the bits
+ +++ */
+ +++ status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
+ +++ }
return IRQ_HANDLED;
}