summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom-at-vmware-dot-com>2009-03-23 09:10:52 +0100
committerThomas Hellstrom <thellstrom-at-vmware-dot-com>2009-03-23 09:11:48 +0100
commitfeb4a2b2de94f2cba3cf15be871439809e68a78d (patch)
treedc03282077e60b12649fa978708e0a695be9a2e3
parent7f38882b15dd048b1453123526fcb0e2d27c01a8 (diff)
ttm: Work around a locking order reversal in fault().
Signed-off-by: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
-rw-r--r--linux-core/ttm/ttm_bo_vm.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/linux-core/ttm/ttm_bo_vm.c b/linux-core/ttm/ttm_bo_vm.c
index 3a89b3e0..d2dbf421 100644
--- a/linux-core/ttm/ttm_bo_vm.c
+++ b/linux-core/ttm/ttm_bo_vm.c
@@ -95,9 +95,18 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
unsigned long address = (unsigned long)vmf->virtual_address;
int retval = VM_FAULT_NOPAGE;
- ret = ttm_bo_reserve(bo, true, false, false, 0);
- if (unlikely(ret != 0))
+ /*
+ * Work around locking order reversal in fault / nopfn
+ * between mmap_sem and bo_reserve: Perform a trylock operation
+ * for reserve, and if it fails, retry the fault after scheduling.
+ */
+
+ ret = ttm_bo_reserve(bo, true, true, false, 0);
+ if (unlikely(ret != 0)) {
+ if (ret == -EBUSY)
+ set_need_resched();
return VM_FAULT_NOPAGE;
+ }
mutex_lock(&bo->mutex);
@@ -230,9 +239,18 @@ static unsigned long ttm_bo_vm_nopfn(struct vm_area_struct *vma,
bool is_iomem;
unsigned long retval = NOPFN_REFAULT;
- ret = ttm_bo_reserve(bo, true, false, false, 0);
- if (unlikely(ret != 0))
+ /*
+ * Work around locking order reversal in fault / nopfn
+ * between mmap_sem and bo_reserve: Perform a trylock operation
+ * for reserve, and if it fails, retry the fault after scheduling.
+ */
+
+ ret = ttm_bo_reserve(bo, true, true, false, 0);
+ if (unlikely(ret != 0)) {
+ if (ret == -EBUSY)
+ set_need_resched();
return NOPFN_REFAULT;
+ }
mutex_lock(&bo->mutex);