diff options
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index f42793d1574d..27792f8c429d 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -700,14 +700,23 @@ retry: | |||
700 | 700 | ||
701 | static void iommu_poll_events(struct amd_iommu *iommu) | 701 | static void iommu_poll_events(struct amd_iommu *iommu) |
702 | { | 702 | { |
703 | u32 head, tail; | 703 | u32 head, tail, status; |
704 | unsigned long flags; | 704 | unsigned long flags; |
705 | 705 | ||
706 | /* enable event interrupts again */ | ||
707 | writel(MMIO_STATUS_EVT_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
708 | |||
709 | spin_lock_irqsave(&iommu->lock, flags); | 706 | spin_lock_irqsave(&iommu->lock, flags); |
710 | 707 | ||
708 | /* enable event interrupts again */ | ||
709 | do { | ||
710 | /* | ||
711 | * Workaround for Erratum ERBT1312 | ||
712 | * Clearing the EVT_INT bit may race in the hardware, so read | ||
713 | * it again and make sure it was really cleared | ||
714 | */ | ||
715 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
716 | writel(MMIO_STATUS_EVT_INT_MASK, | ||
717 | iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
718 | } while (status & MMIO_STATUS_EVT_INT_MASK); | ||
719 | |||
711 | head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); | 720 | head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); |
712 | tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); | 721 | tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); |
713 | 722 | ||
@@ -744,16 +753,25 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) | |||
744 | static void iommu_poll_ppr_log(struct amd_iommu *iommu) | 753 | static void iommu_poll_ppr_log(struct amd_iommu *iommu) |
745 | { | 754 | { |
746 | unsigned long flags; | 755 | unsigned long flags; |
747 | u32 head, tail; | 756 | u32 head, tail, status; |
748 | 757 | ||
749 | if (iommu->ppr_log == NULL) | 758 | if (iommu->ppr_log == NULL) |
750 | return; | 759 | return; |
751 | 760 | ||
752 | /* enable ppr interrupts again */ | ||
753 | writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
754 | |||
755 | spin_lock_irqsave(&iommu->lock, flags); | 761 | spin_lock_irqsave(&iommu->lock, flags); |
756 | 762 | ||
763 | /* enable ppr interrupts again */ | ||
764 | do { | ||
765 | /* | ||
766 | * Workaround for Erratum ERBT1312 | ||
767 | * Clearing the PPR_INT bit may race in the hardware, so read | ||
768 | * it again and make sure it was really cleared | ||
769 | */ | ||
770 | status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
771 | writel(MMIO_STATUS_PPR_INT_MASK, | ||
772 | iommu->mmio_base + MMIO_STATUS_OFFSET); | ||
773 | } while (status & MMIO_STATUS_PPR_INT_MASK); | ||
774 | |||
757 | head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); | 775 | head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); |
758 | tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); | 776 | tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); |
759 | 777 | ||