From patchwork Fri Aug 22 03:12:30 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Widawsky X-Patchwork-Id: 4761151 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 57A3A9F377 for ; Fri, 22 Aug 2014 03:14:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 39DC820173 for ; Fri, 22 Aug 2014 03:14:16 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 0596D201BB for ; Fri, 22 Aug 2014 03:14:15 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C6C8C6E893; Thu, 21 Aug 2014 20:14:12 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 7C5AF6E87C for ; Thu, 21 Aug 2014 20:14:09 -0700 (PDT) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP; 21 Aug 2014 20:14:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,862,1389772800"; d="scan'208";a="375576235" Received: from unknown (HELO ironside.intel.com) ([10.255.12.192]) by FMSMGA003.fm.intel.com with ESMTP; 21 Aug 2014 20:10:14 -0700 From: Ben Widawsky To: Intel GFX Date: Thu, 21 Aug 2014 20:12:30 -0700 Message-Id: <1408677155-1840-68-git-send-email-benjamin.widawsky@intel.com> X-Mailer: git-send-email 2.0.4 In-Reply-To: <1408677155-1840-1-git-send-email-benjamin.widawsky@intel.com> References: <1408677155-1840-1-git-send-email-benjamin.widawsky@intel.com> Cc: Ben Widawsky , Ben Widawsky Subject: [Intel-gfx] [PATCH 67/68] drm/i915: Provide a soft_pin hook X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch is a proof of concept hack which repurposes the MSB of the size field in created. Userptr already has the gup code, and all we need to do is reuse it. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_drv.h | 12 ++++- drivers/gpu/drm/i915/i915_gem.c | 86 +++++++++++++++++++++++++++--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +- drivers/gpu/drm/i915/i915_gem_gtt.h | 1 + drivers/gpu/drm/i915/i915_gem_userptr.c | 7 +-- include/uapi/drm/i915_drm.h | 3 +- 6 files changed, 100 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 00d9ab3..cfad8c1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2298,8 +2298,14 @@ void *i915_gem_object_alloc(struct drm_device *dev); void i915_gem_object_free(struct drm_i915_gem_object *obj); void i915_gem_object_init(struct drm_i915_gem_object *obj, const struct drm_i915_gem_object_ops *ops); -struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, - size_t size); +struct drm_i915_gem_object *_i915_gem_alloc_object(struct drm_device *dev, + size_t size, + bool user_obj); +#define i915_gem_alloc_object(dev, size) _i915_gem_alloc_object(dev, size, false) +int i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj, unsigned flags); +int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj); +void i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj); +#define i915_is_soft_pinned(vma) ((vma)->obj->ops->get_pages == i915_gem_userptr_get_pages) void i915_init_vm(struct drm_i915_private *dev_priv, struct i915_address_space *vm); void i915_gem_free_object(struct drm_gem_object *obj); @@ -2311,11 +2317,13 @@ void i915_gem_vma_destroy(struct i915_vma *vma); #define PIN_ALIASING (1<<3) #define PIN_GLOBAL_ALIASED (PIN_ALIASING | PIN_GLOBAL) #define PIN_OFFSET_BIAS (1<<4) +#define PIN_SOFT (1<<5) #define PIN_OFFSET_MASK (PAGE_MASK) int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, struct i915_address_space *vm, uint32_t alignment, uint64_t flags); +int i915_vma_softpin(struct i915_vma *vma, uint64_t start, uint64_t size); int __must_check i915_vma_unbind(struct i915_vma *vma); int i915_gem_object_put_pages(struct drm_i915_gem_object *obj); void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6413f3a..75d2454 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -347,21 +347,33 @@ static int i915_gem_create(struct drm_file *file, struct drm_device *dev, uint64_t size, + uint64_t loc, uint32_t *handle_p) { struct drm_i915_gem_object *obj; int ret; u32 handle; + bool user_obj = false; + + if (size & BIT_ULL(63)) { + if (!HAS_48B_PPGTT(dev) || !USES_FULL_PPGTT(dev)) + return -EINVAL; + size &= ~BIT_ULL(63); + user_obj = true; + } size = roundup(size, PAGE_SIZE); if (size == 0) return -EINVAL; /* Allocate the new object */ - obj = i915_gem_alloc_object(dev, size); + obj = _i915_gem_alloc_object(dev, size, user_obj); if (obj == NULL) return -ENOMEM; + if (user_obj) + obj->userptr.ptr = loc; + ret = drm_gem_handle_create(file, &obj->base, &handle); /* drop reference from allocate - handle holds it now */ drm_gem_object_unreference_unlocked(&obj->base); @@ -380,7 +392,7 @@ i915_gem_dumb_create(struct drm_file *file, /* have to work out size/pitch and return them */ args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); args->size = args->pitch * args->height; - return i915_gem_create(file, dev, + return i915_gem_create(file, dev, 0, args->size, &args->handle); } @@ -392,9 +404,10 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_gem_create *args = data; + uint64_t location = ((uint64_t)args->handle) << 32 | args->pad; return i915_gem_create(file, dev, - args->size, &args->handle); + args->size, location, &args->handle); } static inline int @@ -3038,7 +3051,10 @@ int i915_vma_unbind(struct i915_vma *vma) if (i915_is_ggtt(vma->vm)) obj->map_and_fenceable = true; - drm_mm_remove_node(&vma->node); + if (i915_is_soft_pinned(vma)) + vma->node.allocated = 0; + else + drm_mm_remove_node(&vma->node); i915_gem_vma_destroy(vma); /* Since the unbound list is global, only move to that list if @@ -3544,6 +3560,8 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) goto err_unpin; + BUG_ON(i915_is_soft_pinned(vma)); + search_free: ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node, size, alignment, @@ -4227,6 +4245,43 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, return 0; } +int i915_vma_softpin(struct i915_vma *vma, uint64_t start, uint64_t size) +{ + struct drm_i915_private *dev_priv = to_i915(vma->vm->dev); + struct drm_i915_gem_object *obj = vma->obj; + int ret; + + BUG_ON(!i915_is_soft_pinned(vma)); + ret = i915_gem_object_get_pages(obj); + if (ret) + return ret; + + i915_gem_object_pin_pages(obj); + + ret = i915_gem_gtt_prepare_object(obj); + if (ret) + goto err_release_pages; + + vma->node.allocated = 1; + + list_move_tail(&obj->global_list, &dev_priv->mm.bound_list); + list_add_tail(&vma->mm_list, &vma->vm->inactive_list); + + vma->node.start = start; + vma->node.size = size; + trace_i915_vma_bind(vma, PIN_SOFT); + i915_gem_vma_bind(vma, obj->cache_level, SOFT_PINNED); + vma->pin_count++; + + return 0; + +err_release_pages: + i915_gem_vma_destroy(vma); + i915_gem_object_unpin_pages(obj); + + return ret; +} + void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj) { @@ -4473,8 +4528,16 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { .put_pages = i915_gem_object_put_pages_gtt, }; -struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, - size_t size) +/* Soft pinned objects are those which have user pages, and an offset defined by + * userspace + */ +static const struct drm_i915_gem_object_ops i915_gem_soft_pin_object_ops = { + .get_pages = i915_gem_userptr_get_pages, + .put_pages = i915_gem_userptr_put_pages, +}; + +struct drm_i915_gem_object *_i915_gem_alloc_object(struct drm_device *dev, + size_t size, bool user_obj) { struct drm_i915_gem_object *obj; struct address_space *mapping; @@ -4499,7 +4562,16 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, mapping = file_inode(obj->base.filp)->i_mapping; mapping_set_gfp_mask(mapping, mask); - i915_gem_object_init(obj, &i915_gem_object_ops); + if (user_obj) { + i915_gem_object_init(obj, &i915_gem_soft_pin_object_ops); + obj->userptr.mm = get_task_mm(current); + if (i915_gem_userptr_init__mmu_notifier(obj, 0)) { + i915_gem_object_free(obj); + drm_gem_object_unreference_unlocked(&obj->base); + return NULL; + } + } else + i915_gem_object_init(obj, &i915_gem_object_ops); obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->base.read_domains = I915_GEM_DOMAIN_CPU; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index fdd68d6..c1761f0 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -571,7 +571,10 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma, if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS) flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS; - ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags); + if (i915_is_soft_pinned(vma)) + ret = i915_vma_softpin(vma, entry->offset, vma->obj->base.size); + else + ret = i915_gem_object_pin(obj, vma->vm, entry->alignment, flags); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 92acd95..e4ab4ba 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -185,6 +185,7 @@ struct i915_vma { /* Only use this if you know you want a strictly aliased binding */ #define ALIASING_BIND (1<<1) #define PTE_READ_ONLY (1<<2) +#define SOFT_PINNED (1<<3) /* Just debug for now */ int (*bind_vma)(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index fe69fc8..ff7aea6 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -341,7 +341,7 @@ i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj) obj->userptr.mn = NULL; } -static int +int i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj, unsigned flags) { @@ -519,7 +519,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) kfree(work); } -static int +int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) { const int num_pages = obj->base.size >> PAGE_SHIFT; @@ -598,6 +598,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) get_task_struct(work->task); INIT_WORK(&work->work, __i915_gem_userptr_get_pages_worker); + WARN_ON(!obj->userptr.ptr); schedule_work(&work->work); } else ret = -ENOMEM; @@ -621,7 +622,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) return ret; } -static void +void i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj) { struct scatterlist *sg; diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index ff57f07..413a4fb 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -662,7 +662,8 @@ struct drm_i915_gem_exec_object2 { #define EXEC_OBJECT_NEEDS_FENCE (1<<0) #define EXEC_OBJECT_NEEDS_GTT (1<<1) #define EXEC_OBJECT_WRITE (1<<2) -#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_WRITE<<1) +#define EXEC_OBJECT_SOFT_PINNED (1<<3) +#define __EXEC_OBJECT_UNKNOWN_FLAGS -(EXEC_OBJECT_SOFT_PINNED<<1) __u64 flags; __u64 rsvd1;