Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310510
b: refs/heads/master
c: eee5353
h: refs/heads/master
v: v3
  • Loading branch information
Joerg Roedel committed Jun 4, 2012
1 parent 00836b1 commit 7bb68b3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c1bf94ec1e12d76838ad485158aecf208ebd8fb9
refs/heads/master: eee53537c476c947bf7faa1c916d2f5a0ae8ec93
71 changes: 44 additions & 27 deletions trunk/drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,26 +547,12 @@ static void iommu_poll_events(struct amd_iommu *iommu)
spin_unlock_irqrestore(&iommu->lock, flags);
}

static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u32 head)
static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw)
{
struct amd_iommu_fault fault;
volatile u64 *raw;
int i;

INC_STATS_COUNTER(pri_requests);

raw = (u64 *)(iommu->ppr_log + head);

/*
* Hardware bug: Interrupt may arrive before the entry is written to
* memory. If this happens we need to wait for the entry to arrive.
*/
for (i = 0; i < LOOP_TIMEOUT; ++i) {
if (PPR_REQ_TYPE(raw[0]) != 0)
break;
udelay(1);
}

if (PPR_REQ_TYPE(raw[0]) != PPR_REQ_FAULT) {
pr_err_ratelimited("AMD-Vi: Unknown PPR request received\n");
return;
Expand All @@ -578,12 +564,6 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u32 head)
fault.tag = PPR_TAG(raw[0]);
fault.flags = PPR_FLAGS(raw[0]);

/*
* To detect the hardware bug we need to clear the entry
* to back to zero.
*/
raw[0] = raw[1] = 0;

atomic_notifier_call_chain(&ppr_notifier, 0, &fault);
}

Expand All @@ -595,25 +575,62 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu)
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);

head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);

while (head != tail) {
volatile u64 *raw;
u64 entry[2];
int i;

/* Handle PPR entry */
iommu_handle_ppr_entry(iommu, head);
raw = (u64 *)(iommu->ppr_log + head);

/*
* Hardware bug: Interrupt may arrive before the entry is
* written to memory. If this happens we need to wait for the
* entry to arrive.
*/
for (i = 0; i < LOOP_TIMEOUT; ++i) {
if (PPR_REQ_TYPE(raw[0]) != 0)
break;
udelay(1);
}

/* Avoid memcpy function-call overhead */
entry[0] = raw[0];
entry[1] = raw[1];

/* Update and refresh ring-buffer state*/
/*
* To detect the hardware bug we need to clear the entry
* back to zero.
*/
raw[0] = raw[1] = 0UL;

/* Update head pointer of hardware ring-buffer */
head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE;
writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);

/*
* Release iommu->lock because ppr-handling might need to
* re-aquire it
*/
spin_unlock_irqrestore(&iommu->lock, flags);

/* Handle PPR entry */
iommu_handle_ppr_entry(iommu, entry);

spin_lock_irqsave(&iommu->lock, flags);

/* Refresh ring-buffer information */
head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET);
tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET);
}

/* enable ppr interrupts again */
writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET);

spin_unlock_irqrestore(&iommu->lock, flags);
}

Expand Down

0 comments on commit 7bb68b3

Please sign in to comment.