aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/amd_iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-09-09 10:41:05 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-19 06:59:16 -0400
commit90008ee4b811c944455752dcb72b291a5ba81b53 (patch)
tree2c54f65efbabd7d9decbff49e12199eed00082b7 /arch/x86/kernel/amd_iommu.c
parenta80dc3e0e0dc8393158de317d66ae0f345dc58f9 (diff)
AMD IOMMU: add event handling code
This patch adds code for polling and printing out events generated by the AMD IOMMU. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/amd_iommu.c')
-rw-r--r--arch/x86/kernel/amd_iommu.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0e494b9d5f20..0cb8fd2359f5 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -55,9 +55,94 @@ static int iommu_has_npcache(struct amd_iommu *iommu)
55 * 55 *
56 ****************************************************************************/ 56 ****************************************************************************/
57 57
58static void iommu_print_event(void *__evt)
59{
60 u32 *event = __evt;
61 int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
62 int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK;
63 int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK;
64 int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK;
65 u64 address = (u64)(((u64)event[3]) << 32) | event[2];
66
67 printk(KERN_ERR "AMD IOMMU: Event logged [");
68
69 switch (type) {
70 case EVENT_TYPE_ILL_DEV:
71 printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
72 "address=0x%016llx flags=0x%04x]\n",
73 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
74 address, flags);
75 break;
76 case EVENT_TYPE_IO_FAULT:
77 printk("IO_PAGE_FAULT device=%02x:%02x.%x "
78 "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
79 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
80 domid, address, flags);
81 break;
82 case EVENT_TYPE_DEV_TAB_ERR:
83 printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
84 "address=0x%016llx flags=0x%04x]\n",
85 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
86 address, flags);
87 break;
88 case EVENT_TYPE_PAGE_TAB_ERR:
89 printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
90 "domain=0x%04x address=0x%016llx flags=0x%04x]\n",
91 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
92 domid, address, flags);
93 break;
94 case EVENT_TYPE_ILL_CMD:
95 printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address);
96 break;
97 case EVENT_TYPE_CMD_HARD_ERR:
98 printk("COMMAND_HARDWARE_ERROR address=0x%016llx "
99 "flags=0x%04x]\n", address, flags);
100 break;
101 case EVENT_TYPE_IOTLB_INV_TO:
102 printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
103 "address=0x%016llx]\n",
104 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
105 address);
106 break;
107 case EVENT_TYPE_INV_DEV_REQ:
108 printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
109 "address=0x%016llx flags=0x%04x]\n",
110 PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
111 address, flags);
112 break;
113 default:
114 printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
115 }
116}
117
118static void iommu_poll_events(struct amd_iommu *iommu)
119{
120 u32 head, tail;
121 unsigned long flags;
122
123 spin_lock_irqsave(&iommu->lock, flags);
124
125 head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
126 tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET);
127
128 while (head != tail) {
129 iommu_print_event(iommu->evt_buf + head);
130 head = (head + EVENT_ENTRY_SIZE) % iommu->evt_buf_size;
131 }
132
133 writel(head, iommu->mmio_base + MMIO_EVT_HEAD_OFFSET);
134
135 spin_unlock_irqrestore(&iommu->lock, flags);
136}
137
58irqreturn_t amd_iommu_int_handler(int irq, void *data) 138irqreturn_t amd_iommu_int_handler(int irq, void *data)
59{ 139{
60 return IRQ_NONE; 140 struct amd_iommu *iommu;
141
142 list_for_each_entry(iommu, &amd_iommu_list, list)
143 iommu_poll_events(iommu);
144
145 return IRQ_HANDLED;
61} 146}
62 147
63/**************************************************************************** 148/****************************************************************************