From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753674AbcAEUob (ORCPT ); Tue, 5 Jan 2016 15:44:31 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:44670 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752610AbcAETqb (ORCPT ); Tue, 5 Jan 2016 14:46:31 -0500 From: Kamal Mostafa To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Cc: Chris Wilson , Daniel Vetter , Kamal Mostafa Subject: [PATCH 4.2.y-ckt 036/211] drm/i915: Only update the current userptr worker Date: Tue, 5 Jan 2016 11:42:24 -0800 Message-Id: <1452023119-25647-37-git-send-email-kamal@canonical.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1452023119-25647-1-git-send-email-kamal@canonical.com> References: <1452023119-25647-1-git-send-email-kamal@canonical.com> X-Extended-Stable: 4.2 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.2.8-ckt1 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Chris Wilson commit 68d6c840595849c0d29f6c52bc75b44ded66b41f upstream. The userptr worker allows for a slight race condition where upon there may two or more threads calling get_user_pages for the same object. When we have the array of pages, then we serialise the update of the object. However, the worker should only overwrite the obj->userptr.work pointer if and only if it is the active one. Currently we clear it for a secondary worker with the effect that we may rarely force a second lookup. v2: Rebase and rename a variable to avoid 80cols v3: Mention v2 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Daniel Vetter [ kamal: 4.2-stable prereq for e4b946b "drm/i915: Fix userptr deadlock with aliased GTT mmappings" ] Signed-off-by: Kamal Mostafa --- drivers/gpu/drm/i915/i915_gem_userptr.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index a96b900..203a569 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -571,25 +571,25 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) struct get_pages_work *work = container_of(_work, typeof(*work), work); struct drm_i915_gem_object *obj = work->obj; struct drm_device *dev = obj->base.dev; - const int num_pages = obj->base.size >> PAGE_SHIFT; + const int npages = obj->base.size >> PAGE_SHIFT; struct page **pvec; int pinned, ret; ret = -ENOMEM; pinned = 0; - pvec = kmalloc(num_pages*sizeof(struct page *), + pvec = kmalloc(npages*sizeof(struct page *), GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); if (pvec == NULL) - pvec = drm_malloc_ab(num_pages, sizeof(struct page *)); + pvec = drm_malloc_ab(npages, sizeof(struct page *)); if (pvec != NULL) { struct mm_struct *mm = obj->userptr.mm->mm; down_read(&mm->mmap_sem); - while (pinned < num_pages) { + while (pinned < npages) { ret = get_user_pages(work->task, mm, obj->userptr.ptr + pinned * PAGE_SIZE, - num_pages - pinned, + npages - pinned, !obj->userptr.read_only, 0, pvec + pinned, NULL); if (ret < 0) @@ -601,20 +601,20 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) } mutex_lock(&dev->struct_mutex); - if (obj->userptr.work != &work->work) { - ret = 0; - } else if (pinned == num_pages) { - ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages); - if (ret == 0) { - list_add_tail(&obj->global_list, &to_i915(dev)->mm.unbound_list); - obj->get_page.sg = obj->pages->sgl; - obj->get_page.last = 0; - - pinned = 0; + if (obj->userptr.work == &work->work) { + if (pinned == npages) { + ret = __i915_gem_userptr_set_pages(obj, pvec, npages); + if (ret == 0) { + list_add_tail(&obj->global_list, + &to_i915(dev)->mm.unbound_list); + obj->get_page.sg = obj->pages->sgl; + obj->get_page.last = 0; + pinned = 0; + } } + obj->userptr.work = ERR_PTR(ret); } - obj->userptr.work = ERR_PTR(ret); obj->userptr.workers--; drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); -- 1.9.1