diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2012-04-12 08:12:00 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2012-04-12 08:16:14 -0400 |
commit | 3d06fca8d2aa3543030e40b95f1d62f9f5a03540 (patch) | |
tree | fcef864e872b18c00991cc1805c279f977e61fca /drivers/iommu | |
parent | a3b93121430c7b46c2895a7744261be107ccdf7f (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.c | 29 |
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 | ||
451 | static void iommu_print_event(struct amd_iommu *iommu, void *__evt) | 451 | static 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]; | 458 | retry: |
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 | ||
513 | static void iommu_poll_events(struct amd_iommu *iommu) | 530 | static void iommu_poll_events(struct amd_iommu *iommu) |