aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2012-04-12 08:12:00 -0400
committerJoerg Roedel <joerg.roedel@amd.com>2012-04-12 08:16:14 -0400
commit3d06fca8d2aa3543030e40b95f1d62f9f5a03540 (patch)
treefcef864e872b18c00991cc1805c279f977e61fca /drivers/iommu
parenta3b93121430c7b46c2895a7744261be107ccdf7f (diff)
iommu/amd: Add workaround for event log erratum
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. Cc: stable@vger.kernel.org # all stable kernels Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
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 08f3eecb87a2..d90a421e9cac 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -450,12 +450,27 @@ static void dump_command(unsigned long phys_addr)
450 450
451static void iommu_print_event(struct amd_iommu *iommu, void *__evt) 451static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
452{ 452{
453 u32 *event = __evt; 453 int type, devid, domid, flags;
454 int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; 454 volatile u32 *event = __evt;
455 int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; 455 int count = 0;
456 int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; 456 u64 address;
457 int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; 457
458 u64 address = (u64)(((u64)event[3]) << 32) | event[2]; 458retry:
459 type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
460 devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
461 domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
462 flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
463 address = (u64)(((u64)event[3]) << 32) | event[2];
464
465 if (type == 0) {
466 /* Did we hit the erratum? */
467 if (++count == LOOP_TIMEOUT) {
468 pr_err("AMD-Vi: No event written to event log\n");
469 return;
470 }
471 udelay(1);
472 goto retry;
473 }
459 474
460 printk(KERN_ERR "AMD-Vi: Event logged ["); 475 printk(KERN_ERR "AMD-Vi: Event logged [");
461 476
@@ -508,6 +523,8 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)
508 default: 523 default:
509 printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); 524 printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
510 } 525 }
526
527 memset(__evt, 0, 4 * sizeof(u32));
511} 528}
512 529
513static void iommu_poll_events(struct amd_iommu *iommu) 530static void iommu_poll_events(struct amd_iommu *iommu)