|
@@ -164,7 +164,6 @@ static struct i915_mmu_notifier *
|
|
i915_mmu_notifier_create(struct mm_struct *mm)
|
|
i915_mmu_notifier_create(struct mm_struct *mm)
|
|
{
|
|
{
|
|
struct i915_mmu_notifier *mn;
|
|
struct i915_mmu_notifier *mn;
|
|
- int ret;
|
|
|
|
|
|
|
|
mn = kmalloc(sizeof(*mn), GFP_KERNEL);
|
|
mn = kmalloc(sizeof(*mn), GFP_KERNEL);
|
|
if (mn == NULL)
|
|
if (mn == NULL)
|
|
@@ -179,14 +178,6 @@ i915_mmu_notifier_create(struct mm_struct *mm)
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
}
|
|
}
|
|
|
|
|
|
- /* Protected by mmap_sem (write-lock) */
|
|
|
|
- ret = __mmu_notifier_register(&mn->mn, mm);
|
|
|
|
- if (ret) {
|
|
|
|
- destroy_workqueue(mn->wq);
|
|
|
|
- kfree(mn);
|
|
|
|
- return ERR_PTR(ret);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
return mn;
|
|
return mn;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -210,23 +201,40 @@ i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj)
|
|
static struct i915_mmu_notifier *
|
|
static struct i915_mmu_notifier *
|
|
i915_mmu_notifier_find(struct i915_mm_struct *mm)
|
|
i915_mmu_notifier_find(struct i915_mm_struct *mm)
|
|
{
|
|
{
|
|
- struct i915_mmu_notifier *mn = mm->mn;
|
|
|
|
|
|
+ struct i915_mmu_notifier *mn;
|
|
|
|
+ int err = 0;
|
|
|
|
|
|
mn = mm->mn;
|
|
mn = mm->mn;
|
|
if (mn)
|
|
if (mn)
|
|
return mn;
|
|
return mn;
|
|
|
|
|
|
|
|
+ mn = i915_mmu_notifier_create(mm->mm);
|
|
|
|
+ if (IS_ERR(mn))
|
|
|
|
+ err = PTR_ERR(mn);
|
|
|
|
+
|
|
down_write(&mm->mm->mmap_sem);
|
|
down_write(&mm->mm->mmap_sem);
|
|
mutex_lock(&mm->i915->mm_lock);
|
|
mutex_lock(&mm->i915->mm_lock);
|
|
- if ((mn = mm->mn) == NULL) {
|
|
|
|
- mn = i915_mmu_notifier_create(mm->mm);
|
|
|
|
- if (!IS_ERR(mn))
|
|
|
|
- mm->mn = mn;
|
|
|
|
|
|
+ if (mm->mn == NULL && !err) {
|
|
|
|
+ /* Protected by mmap_sem (write-lock) */
|
|
|
|
+ err = __mmu_notifier_register(&mn->mn, mm->mm);
|
|
|
|
+ if (!err) {
|
|
|
|
+ /* Protected by mm_lock */
|
|
|
|
+ mm->mn = fetch_and_zero(&mn);
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ /* someone else raced and successfully installed the mmu
|
|
|
|
+ * notifier, we can cancel our own errors */
|
|
|
|
+ err = 0;
|
|
}
|
|
}
|
|
mutex_unlock(&mm->i915->mm_lock);
|
|
mutex_unlock(&mm->i915->mm_lock);
|
|
up_write(&mm->mm->mmap_sem);
|
|
up_write(&mm->mm->mmap_sem);
|
|
|
|
|
|
- return mn;
|
|
|
|
|
|
+ if (mn) {
|
|
|
|
+ destroy_workqueue(mn->wq);
|
|
|
|
+ kfree(mn);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return err ? ERR_PTR(err) : mm->mn;
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
static int
|