aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/amd_iommu.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2008-12-02 14:34:41 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2009-01-03 08:11:54 -0500
commit8d201968e15f56ae2837b0d0b64d3fff098857b0 (patch)
treec2f57f4c599e8f401b3ddc2614840014be4a34e4 /arch/x86/kernel/amd_iommu.c
parenta2acfb75792511a35586db80a38b8e4701a97730 (diff)
AMD IOMMU: refactor completion wait handling into separate functions
Impact: split one function into three The separate functions are required synchronize commands across all hardware IOMMUs in the system. Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Diffstat (limited to 'arch/x86/kernel/amd_iommu.c')
-rw-r--r--arch/x86/kernel/amd_iommu.c68
1 files changed, 45 insertions, 23 deletions
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
index 0922d5fe633c..2280ef86651f 100644
--- a/arch/x86/kernel/amd_iommu.c
+++ b/arch/x86/kernel/amd_iommu.c
@@ -196,6 +196,46 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
196} 196}
197 197
198/* 198/*
199 * This function waits until an IOMMU has completed a completion
200 * wait command
201 */
202static void __iommu_wait_for_completion(struct amd_iommu *iommu)
203{
204 int ready = 0;
205 unsigned status = 0;
206 unsigned long i = 0;
207
208 while (!ready && (i < EXIT_LOOP_COUNT)) {
209 ++i;
210 /* wait for the bit to become one */
211 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
212 ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
213 }
214
215 /* set bit back to zero */
216 status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
217 writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
218
219 if (unlikely(i == EXIT_LOOP_COUNT))
220 panic("AMD IOMMU: Completion wait loop failed\n");
221}
222
223/*
224 * This function queues a completion wait command into the command
225 * buffer of an IOMMU
226 */
227static int __iommu_completion_wait(struct amd_iommu *iommu)
228{
229 struct iommu_cmd cmd;
230
231 memset(&cmd, 0, sizeof(cmd));
232 cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
233 CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
234
235 return __iommu_queue_command(iommu, &cmd);
236}
237
238/*
199 * This function is called whenever we need to ensure that the IOMMU has 239 * This function is called whenever we need to ensure that the IOMMU has
200 * completed execution of all commands we sent. It sends a 240 * completed execution of all commands we sent. It sends a
201 * COMPLETION_WAIT command and waits for it to finish. The IOMMU informs 241 * COMPLETION_WAIT command and waits for it to finish. The IOMMU informs
@@ -204,40 +244,22 @@ static int iommu_queue_command(struct amd_iommu *iommu, struct iommu_cmd *cmd)
204 */ 244 */
205static int iommu_completion_wait(struct amd_iommu *iommu) 245static int iommu_completion_wait(struct amd_iommu *iommu)
206{ 246{
207 int ret = 0, ready = 0; 247 int ret = 0;
208 unsigned status = 0; 248 unsigned long flags;
209 struct iommu_cmd cmd;
210 unsigned long flags, i = 0;
211
212 memset(&cmd, 0, sizeof(cmd));
213 cmd.data[0] = CMD_COMPL_WAIT_INT_MASK;
214 CMD_SET_TYPE(&cmd, CMD_COMPL_WAIT);
215 249
216 spin_lock_irqsave(&iommu->lock, flags); 250 spin_lock_irqsave(&iommu->lock, flags);
217 251
218 if (!iommu->need_sync) 252 if (!iommu->need_sync)
219 goto out; 253 goto out;
220 254
221 iommu->need_sync = 0; 255 ret = __iommu_completion_wait(iommu);
222 256
223 ret = __iommu_queue_command(iommu, &cmd); 257 iommu->need_sync = 0;
224 258
225 if (ret) 259 if (ret)
226 goto out; 260 goto out;
227 261
228 while (!ready && (i < EXIT_LOOP_COUNT)) { 262 __iommu_wait_for_completion(iommu);
229 ++i;
230 /* wait for the bit to become one */
231 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
232 ready = status & MMIO_STATUS_COM_WAIT_INT_MASK;
233 }
234
235 /* set bit back to zero */
236 status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;
237 writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET);
238
239 if (unlikely(i == EXIT_LOOP_COUNT))
240 panic("AMD IOMMU: Completion wait loop failed\n");
241 263
242out: 264out:
243 spin_unlock_irqrestore(&iommu->lock, flags); 265 spin_unlock_irqrestore(&iommu->lock, flags);