diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c index d655055f2cc9..c505cdbc0e6b 100644 --- a/sys/dev/drm2/i915/i915_gem.c +++ b/sys/dev/drm2/i915/i915_gem.c @@ -1371,6 +1371,23 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, } else DRM_LOCK(dev); + /* + * Since the object lock was dropped, other thread might have + * faulted on the same GTT address and instantiated the + * mapping for the page. Recheck. + */ + VM_OBJECT_WLOCK(vm_obj); + m = vm_page_lookup(vm_obj, OFF_TO_IDX(offset)); + if (m != NULL) { + if ((m->flags & VPO_BUSY) != 0) { + DRM_UNLOCK(dev); + vm_page_sleep(m, "915pee"); + goto retry; + } + goto have_page; + } else + VM_OBJECT_WUNLOCK(vm_obj); + /* Now bind it into the GTT if needed */ if (!obj->map_and_fenceable) { ret = i915_gem_object_unbind(obj); @@ -1424,8 +1441,9 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, goto retry; } m->valid = VM_PAGE_BITS_ALL; - *mres = m; vm_page_insert(m, vm_obj, OFF_TO_IDX(offset)); +have_page: + *mres = m; vm_page_busy(m); CTR4(KTR_DRM, "fault %p %jx %x phys %x", gem_obj, offset, prot,