aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-04-12 14:12:00 +0200
committerBen Hutchings <ben@decadent.org.uk>2012-06-10 14:41:31 +0100
commit322a3fe8c915cdf512a510ad1bd359f8e0ed9a86 (patch)
treebf0e5512dac79b1ddff0387f77d566c6b50d59e5 /drivers/iommu
parent563b3269570396946bc2b08e078c6556f9029a95 (diff)
downloadkernel_samsung_smdk4412-322a3fe8c915cdf512a510ad1bd359f8e0ed9a86.zip
kernel_samsung_smdk4412-322a3fe8c915cdf512a510ad1bd359f8e0ed9a86.tar.gz
kernel_samsung_smdk4412-322a3fe8c915cdf512a510ad1bd359f8e0ed9a86.tar.bz2
iommu/amd: Add workaround for event log erratum
commit 3d06fca8d2aa3543030e40b95f1d62f9f5a03540 upstream. Due to a recent erratum it can happen that the head pointer of the event-log is updated before the actual event-log entry is written. This patch implements the recommended workaround. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/amd_iommu.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 966a6e7..f1d5408 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -381,12 +381,27 @@ static void dump_command(unsigned long phys_addr)
static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
{
- u32 *event = __evt;
- int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
- int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
- int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
- int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
- u64 address = (u64)(((u64)event[3]) << 32) | event[2];
+ int type, devid, domid, flags;
+ volatile u32 *event = __evt;
+ int count = 0;
+ u64 address;
+
+retry:
+ type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
+ devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
+ domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
+ flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
+ address = (u64)(((u64)event[3]) << 32) | event[2];
+
+ if (type == 0) {
+ /* Did we hit the erratum? */
+ if (++count == LOOP_TIMEOUT) {
+ pr_err("AMD-Vi: No event written to event log\n");
+ return;
+ }
+ udelay(1);
+ goto retry;
+ }
printk(KERN_ERR "AMD-Vi: Event logged [");
@@ -439,6 +454,8 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
default:
printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
}
+
+ memset(__evt, 0, 4 * sizeof(u32));
}
static void iommu_poll_events(struct amd_iommu *iommu)