diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2008-12-02 14:34:41 -0500 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2009-01-03 08:11:54 -0500 |
commit | 8d201968e15f56ae2837b0d0b64d3fff098857b0 (patch) | |
tree | c2f57f4c599e8f401b3ddc2614840014be4a34e4 | |
parent | a2acfb75792511a35586db80a38b8e4701a97730 (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>
-rw-r--r-- | arch/x86/kernel/amd_iommu.c | 68 |
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 | */ | ||
202 | static 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 | */ | ||
227 | static 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 | */ |
205 | static int iommu_completion_wait(struct amd_iommu *iommu) | 245 | static 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 | ||
242 | out: | 264 | out: |
243 | spin_unlock_irqrestore(&iommu->lock, flags); | 265 | spin_unlock_irqrestore(&iommu->lock, flags); |