drm/i915: Add ww locking to vm_fault_gtt
We want to start requiring the reservation_lock instead of obj->mm.lock for pinning objects, take the ww lock inside vm_fault_gtt as a first step towards the legacy lock removal. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Thomas Hellström <thomas.hellstrom@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-23-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
This commit is contained in:
parent
15b6c92498
commit
3c0ffa277e
@ -283,37 +283,46 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
|
||||
struct intel_runtime_pm *rpm = &i915->runtime_pm;
|
||||
struct i915_ggtt *ggtt = &i915->ggtt;
|
||||
bool write = area->vm_flags & VM_WRITE;
|
||||
struct i915_gem_ww_ctx ww;
|
||||
intel_wakeref_t wakeref;
|
||||
struct i915_vma *vma;
|
||||
pgoff_t page_offset;
|
||||
int srcu;
|
||||
int ret;
|
||||
|
||||
/* Sanity check that we allow writing into this object */
|
||||
if (i915_gem_object_is_readonly(obj) && write)
|
||||
return VM_FAULT_SIGBUS;
|
||||
|
||||
/* We don't use vmf->pgoff since that has the fake offset */
|
||||
page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
|
||||
|
||||
trace_i915_gem_object_fault(obj, page_offset, true, write);
|
||||
|
||||
ret = i915_gem_object_pin_pages(obj);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
wakeref = intel_runtime_pm_get(rpm);
|
||||
|
||||
ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu);
|
||||
i915_gem_ww_ctx_init(&ww, true);
|
||||
retry:
|
||||
ret = i915_gem_object_lock(obj, &ww);
|
||||
if (ret)
|
||||
goto err_rpm;
|
||||
|
||||
/* Sanity check that we allow writing into this object */
|
||||
if (i915_gem_object_is_readonly(obj) && write) {
|
||||
ret = -EFAULT;
|
||||
goto err_rpm;
|
||||
}
|
||||
|
||||
ret = i915_gem_object_pin_pages(obj);
|
||||
if (ret)
|
||||
goto err_rpm;
|
||||
|
||||
ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu);
|
||||
if (ret)
|
||||
goto err_pages;
|
||||
|
||||
/* Now pin it into the GTT as needed */
|
||||
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
|
||||
PIN_MAPPABLE |
|
||||
PIN_NONBLOCK /* NOWARN */ |
|
||||
PIN_NOEVICT);
|
||||
if (IS_ERR(vma)) {
|
||||
vma = i915_gem_object_ggtt_pin_ww(obj, &ww, NULL, 0, 0,
|
||||
PIN_MAPPABLE |
|
||||
PIN_NONBLOCK /* NOWARN */ |
|
||||
PIN_NOEVICT);
|
||||
if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) {
|
||||
/* Use a partial view if it is bigger than available space */
|
||||
struct i915_ggtt_view view =
|
||||
compute_partial_view(obj, page_offset, MIN_CHUNK_PAGES);
|
||||
@ -328,11 +337,11 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf)
|
||||
* all hope that the hardware is able to track future writes.
|
||||
*/
|
||||
|
||||
vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags);
|
||||
if (IS_ERR(vma)) {
|
||||
vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags);
|
||||
if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) {
|
||||
flags = PIN_MAPPABLE;
|
||||
view.type = I915_GGTT_VIEW_PARTIAL;
|
||||
vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags);
|
||||
vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags);
|
||||
}
|
||||
|
||||
/* The entire mappable GGTT is pinned? Unexpected! */
|
||||
@ -389,10 +398,16 @@ err_unpin:
|
||||
__i915_vma_unpin(vma);
|
||||
err_reset:
|
||||
intel_gt_reset_unlock(ggtt->vm.gt, srcu);
|
||||
err_rpm:
|
||||
intel_runtime_pm_put(rpm, wakeref);
|
||||
err_pages:
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
err:
|
||||
err_rpm:
|
||||
if (ret == -EDEADLK) {
|
||||
ret = i915_gem_ww_ctx_backoff(&ww);
|
||||
if (!ret)
|
||||
goto retry;
|
||||
}
|
||||
i915_gem_ww_ctx_fini(&ww);
|
||||
intel_runtime_pm_put(rpm, wakeref);
|
||||
return i915_error_to_vmf_fault(ret);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user