list_del(&msm_obj->mm_list);
mutex_unlock(&priv->mm_lock);
- msm_gem_lock(obj);
-
/* object should not be on active list: */
GEM_WARN_ON(is_active(msm_obj));
put_iova_vmas(obj);
- /* dma_buf_detach() grabs resv lock, so we need to unlock
- * prior to drm_prime_gem_destroy
- */
- msm_gem_unlock(obj);
-
drm_prime_gem_destroy(obj, msm_obj->sgt);
} else {
msm_gem_vunmap(obj);
put_pages(obj);
put_iova_vmas(obj);
- msm_gem_unlock(obj);
}
drm_gem_object_release(obj);
static inline bool
msm_gem_is_locked(struct drm_gem_object *obj)
{
- return dma_resv_is_locked(obj->resv);
+ /*
+ * Destroying the object is a special case.. msm_gem_free_object()
+ * calls many things that WARN_ON if the obj lock is not held. But
+ * acquiring the obj lock in msm_gem_free_object() can cause a
+ * locking order inversion between reservation_ww_class_mutex and
+ * fs_reclaim.
+ *
+ * This deadlock is not actually possible, because no one should
+ * be already holding the lock when msm_gem_free_object() is called.
+ * Unfortunately lockdep is not aware of this detail. So when the
+ * refcount drops to zero, we pretend it is already locked.
+ */
+ return dma_resv_is_locked(obj->resv) || (kref_read(&obj->refcount) == 0);
}
static inline bool is_active(struct msm_gem_object *msm_obj)