|
@@ -700,14 +700,23 @@ retry:
|
|
|
|
|
|
static void iommu_poll_events(struct amd_iommu *iommu)
|
|
|
{
|
|
|
- u32 head, tail;
|
|
|
+ u32 head, tail, status;
|
|
|
unsigned long flags;
|
|
|
|
|
|
- /* enable event interrupts again */
|
|
|
- writel(MMIO_STATUS_EVT_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET);
|
|
|
-
|
|
|
spin_lock_irqsave(&iommu->lock, flags);
|
|
|
|
|
|
+ /* enable event interrupts again */
|
|
|
+ do {
|
|
|
+ /*
|
|
|
+ * Workaround for Erratum ERBT1312
|
|
|
+ * Clearing the EVT_INT bit may race in the hardware, so read
|
|
|
+ * it again and make sure it was really cleared
|
|
|
+ */
|
|
|
+ status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
|
|
|
+ writel(MMIO_STATUS_EVT_INT_MASK,
|
|
|
+ iommu->mmio_base + MMIO_STATUS_OFFSET);
|
|
|
+ } while (status & MMIO_STATUS_EVT_INT_MASK);
|
|
|
+
|
|
|
head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
|
|
|
tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
|
|
|
|
|
@@ -744,16 +753,25 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw)
|
|
|
static void iommu_poll_ppr_log(struct amd_iommu *iommu)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
- u32 head, tail;
|
|
|
+ u32 head, tail, status;
|
|
|
|
|
|
if (iommu->ppr_log == NULL)
|
|
|
return;
|
|
|
|
|
|
- /* enable ppr interrupts again */
|
|
|
- writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET);
|
|
|
-
|
|
|
spin_lock_irqsave(&iommu->lock, flags);
|
|
|
|
|
|
+ /* enable ppr interrupts again */
|
|
|
+ do {
|
|
|
+ /*
|
|
|
+ * Workaround for Erratum ERBT1312
|
|
|
+ * Clearing the PPR_INT bit may race in the hardware, so read
|
|
|
+ * it again and make sure it was really cleared
|
|
|
+ */
|
|
|
+ status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
|
|
|
+ writel(MMIO_STATUS_PPR_INT_MASK,
|
|
|
+ iommu->mmio_base + MMIO_STATUS_OFFSET);
|
|
|
+ } while (status & MMIO_STATUS_PPR_INT_MASK);
|
|
|
+
|
|
|
head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
|
|
|
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);
|
|
|
|