From e9d709dc7ce4a72ab4c193b008e68829992c54cd Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 18 Apr 2013 17:55:04 +0200 Subject: [PATCH] --- yaml --- r: 373567 b: refs/heads/master c: d3263bc29706e42f74d8800807c2dedf320d77f1 h: refs/heads/master i: 373565: 4146a50875a00c422c2944bd1abbae825fd1fbe3 373563: f2eaaac4fd75ada3944b12f70c2d1f8eb1fe8783 373559: 5900b7e7ae8dd3f7b124a89538e0c78ce97d3a51 373551: 212879f1c49ed37df1370a5006e0e680f75a732d 373535: 887dbfcf2fd525c578c3ccc347f254a1ccac96a3 373503: 74e2e03db4996e478715cbb55d610786a525ba67 v: v3 --- [refs] | 2 +- trunk/drivers/iommu/amd_iommu.c | 34 +++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/[refs] b/[refs] index 390661ec1e07..d4555ddb4e2d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7d8bfa26f236bc9528415402dda6b498a0682e42 +refs/heads/master: d3263bc29706e42f74d8800807c2dedf320d77f1 diff --git a/trunk/drivers/iommu/amd_iommu.c b/trunk/drivers/iommu/amd_iommu.c index f42793d1574d..27792f8c429d 100644 --- a/trunk/drivers/iommu/amd_iommu.c +++ b/trunk/drivers/iommu/amd_iommu.c @@ -700,14 +700,23 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) 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);