From patchwork Fri May 18 09:28:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qiang Yu X-Patchwork-Id: 10414089 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 66EF660365 for ; Mon, 21 May 2018 08:18:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D22827CEA for ; Mon, 21 May 2018 08:18:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4F7F727F8F; Mon, 21 May 2018 08:18:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4458C27CEA for ; Mon, 21 May 2018 08:18:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 64E8C8970E; Mon, 21 May 2018 08:18:12 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pl0-x241.google.com (mail-pl0-x241.google.com [IPv6:2607:f8b0:400e:c01::241]) by gabe.freedesktop.org (Postfix) with ESMTPS id DEB3C6ECC9 for ; Fri, 18 May 2018 09:30:57 +0000 (UTC) Received: by mail-pl0-x241.google.com with SMTP id c19-v6so4267313pls.6 for ; Fri, 18 May 2018 02:30:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gGj8adQOYAM4PQB+Ro8NLq2oc1XQp5FItXYqXDI+fds=; b=B1o3gxgLgFW1cUNcjJbXL+0JhgUEAZxDkcUPED9mH8t50GpPXDq4FSwvFHokq04KwO Y9os1HiJg7M3I8s303FURFeaeBeijl6WGLcYhv7sOtDN8MZt2ZD6z3wIfDzjx+cM966I in4nlzSRbRPKKc0fMZMz12kVYK2YLPEdxSjE2jsAADD1AgK/p37X4G0kQxv4UeFyBBCA 1m6r10SDaY/eyJW0Tcoeh901uVkUxZ9Bh2Y4h7fSWphYtoQqw0NARQNRlGPiI6qTI2Hu 45Sig7tlvyCTgbLNetBCKenV5iVYNNPla+jUmg967BtCeXHrXXthfrtHMsyBDHjYvpjV xTmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gGj8adQOYAM4PQB+Ro8NLq2oc1XQp5FItXYqXDI+fds=; b=l0cumNZBCNbErjOvLOOJU1G6e1UdArqOjNpQcBLXtyMMLS0Q/V+DerolCjOnOQa7TT yoxU5iCkkJ2yGy5GjsONMJqPmwiGrJD2oynfjBpaA3O92ICjYZZpgA1FVdfGI6ODvHpd TKGsOfmnxS9v41tXoODNU2zfQ/l2Qb5YWX/6PgZqkA4Xhdbkqy1QP9JNWEzRaImtjb+g kT/p5MnBoi4YPJV1Ys1x8YdjkdISe5j7Fou6a9PjGXVeta7ZtiQ+nmKVXPgmcI9LgETd yeFaDj5OLEJbHfPFxMpqPNFb2QiiqOcrivzEtDnt5NDDkZHu2+hQf7n0zd51NmVA1mtf G9jw== X-Gm-Message-State: ALKqPwd0AhM61DvW52+m/YTuva+55C7jRvheeqyhvX8P+N8O2s5yrpZl tUIZFrdTXeHvqkY50H5YzNsyvY7Tk84= X-Google-Smtp-Source: AB8JxZpB4OV/We2vS9cMiP3IWZUMPJbPMAwcfA0dblppyRUm6BHEPHWmK8IOLgdZBQs2jBAXoFUErA== X-Received: by 2002:a17:902:6b47:: with SMTP id g7-v6mr8778876plt.251.1526635857139; Fri, 18 May 2018 02:30:57 -0700 (PDT) Received: from localhost.localdomain (210-140-84-216.jp-east.compute.idcfcloud.com. [210.140.84.216]) by smtp.gmail.com with ESMTPSA id h191-v6sm10543832pgc.11.2018.05.18.02.30.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 May 2018 02:30:56 -0700 (PDT) From: Qiang Yu To: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org Subject: [PATCH RFC 20/24] drm/lima: add GEM related functions Date: Fri, 18 May 2018 17:28:11 +0800 Message-Id: <20180518092815.25280-21-yuq825@gmail.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180518092815.25280-1-yuq825@gmail.com> References: <20180518092815.25280-1-yuq825@gmail.com> X-Mailman-Approved-At: Mon, 21 May 2018 08:18:10 +0000 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Simon Shields , Marek Vasut , Connor Abbott , Neil Armstrong , Andrei Paulau <7134956@gmail.com>, Vasily Khoruzhick , Qiang Yu , Erico Nunes MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Lima Project Developers Signed-off-by: Qiang Yu Signed-off-by: Erico Nunes Signed-off-by: Heiko Stuebner --- drivers/gpu/drm/lima/lima_gem.c | 459 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/lima/lima_gem.h | 41 +++ 2 files changed, 500 insertions(+) create mode 100644 drivers/gpu/drm/lima/lima_gem.c create mode 100644 drivers/gpu/drm/lima/lima_gem.h diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c new file mode 100644 index 000000000000..1ad3f38ddfde --- /dev/null +++ b/drivers/gpu/drm/lima/lima_gem.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2017-2018 Lima Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +#include "lima_drv.h" +#include "lima_gem.h" +#include "lima_vm.h" +#include "lima_object.h" + +int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, + u32 size, u32 flags, u32 *handle) +{ + int err; + struct lima_bo *bo; + struct lima_device *ldev = to_lima_dev(dev); + + bo = lima_bo_create(ldev, size, flags, ttm_bo_type_device, NULL, NULL); + if (IS_ERR(bo)) + return PTR_ERR(bo); + + err = drm_gem_handle_create(file, &bo->gem, handle); + + /* drop reference from allocate - handle holds it now */ + drm_gem_object_put_unlocked(&bo->gem); + + return err; +} + +void lima_gem_free_object(struct drm_gem_object *obj) +{ + struct lima_bo *bo = to_lima_bo(obj); + + if (!list_empty(&bo->va)) + dev_err(obj->dev->dev, "lima gem free bo still has va\n"); + + lima_bo_unref(bo); +} + +int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file) +{ + struct lima_bo *bo = to_lima_bo(obj); + struct lima_drm_priv *priv = to_lima_drm_priv(file); + struct lima_vm *vm = priv->vm; + int err; + + err = lima_bo_reserve(bo, true); + if (err) + return err; + + err = lima_vm_bo_add(vm, bo); + + lima_bo_unreserve(bo); + return err; +} + +void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *file) +{ + struct lima_bo *bo = to_lima_bo(obj); + struct lima_device *dev = to_lima_dev(obj->dev); + struct lima_drm_priv *priv = to_lima_drm_priv(file); + struct lima_vm *vm = priv->vm; + + LIST_HEAD(list); + struct ttm_validate_buffer tv_bo, tv_pd; + struct ww_acquire_ctx ticket; + int r; + + tv_bo.bo = &bo->tbo; + tv_bo.shared = true; + list_add(&tv_bo.head, &list); + + tv_pd.bo = &vm->pd->tbo; + tv_pd.shared = true; + list_add(&tv_pd.head, &list); + + r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); + if (r) { + dev_err(dev->dev, "leeking bo va because we " + "fail to reserve bo (%d)\n", r); + return; + } + + lima_vm_bo_del(vm, bo); + + ttm_eu_backoff_reservation(&ticket, &list); +} + +int lima_gem_mmap_offset(struct drm_file *file, u32 handle, u64 *offset) +{ + struct drm_gem_object *obj; + struct lima_bo *bo; + + obj = drm_gem_object_lookup(file, handle); + if (!obj) + return -ENOENT; + + bo = to_lima_bo(obj); + *offset = drm_vma_node_offset_addr(&bo->tbo.vma_node); + + drm_gem_object_put_unlocked(obj); + return 0; +} + +int lima_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + struct drm_file *file_priv; + struct lima_device *dev; + + if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) + return -EINVAL; + + file_priv = filp->private_data; + dev = file_priv->minor->dev->dev_private; + if (dev == NULL) + return -EINVAL; + + return ttm_bo_mmap(filp, vma, &dev->mman.bdev); +} + +int lima_gem_va_map(struct drm_file *file, u32 handle, u32 flags, u32 va) +{ + struct lima_drm_priv *priv = to_lima_drm_priv(file); + struct lima_vm *vm = priv->vm; + struct drm_gem_object *obj; + struct lima_bo *bo; + struct lima_device *dev; + int err; + + LIST_HEAD(list); + struct ttm_validate_buffer tv_bo, tv_pd; + struct ww_acquire_ctx ticket; + + if (!PAGE_ALIGNED(va)) + return -EINVAL; + + obj = drm_gem_object_lookup(file, handle); + if (!obj) + return -ENOENT; + + bo = to_lima_bo(obj); + dev = to_lima_dev(obj->dev); + + /* carefully handle overflow when calculate range */ + if (va < dev->va_start || dev->va_end - obj->size < va) { + err = -EINVAL; + goto out; + } + + tv_bo.bo = &bo->tbo; + tv_bo.shared = true; + list_add(&tv_bo.head, &list); + + tv_pd.bo = &vm->pd->tbo; + tv_pd.shared = true; + list_add(&tv_pd.head, &list); + + err = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); + if (err) + goto out; + + err = lima_vm_bo_map(vm, bo, va); + + ttm_eu_backoff_reservation(&ticket, &list); +out: + drm_gem_object_put_unlocked(obj); + return err; +} + +int lima_gem_va_unmap(struct drm_file *file, u32 handle, u32 va) +{ + struct lima_drm_priv *priv = to_lima_drm_priv(file); + struct lima_vm *vm = priv->vm; + struct drm_gem_object *obj; + struct lima_bo *bo; + int err; + + LIST_HEAD(list); + struct ttm_validate_buffer tv_bo, tv_pd; + struct ww_acquire_ctx ticket; + + if (!PAGE_ALIGNED(va)) + return -EINVAL; + + obj = drm_gem_object_lookup(file, handle); + if (!obj) + return -ENOENT; + + bo = to_lima_bo(obj); + + tv_bo.bo = &bo->tbo; + tv_bo.shared = true; + list_add(&tv_bo.head, &list); + + tv_pd.bo = &vm->pd->tbo; + tv_pd.shared = true; + list_add(&tv_pd.head, &list); + + err = ttm_eu_reserve_buffers(&ticket, &list, false, NULL); + if (err) + goto out; + + err = lima_vm_bo_unmap(vm, bo, va); + + ttm_eu_backoff_reservation(&ticket, &list); +out: + drm_gem_object_put_unlocked(obj); + return err; +} + +static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo, + bool write, bool explicit) +{ + int i, err; + struct dma_fence *f; + u64 context = task->base.s_fence->finished.context; + + if (!write) { + err = reservation_object_reserve_shared(bo->tbo.resv); + if (err) + return err; + } + + /* explicit sync use user passed dep fence */ + if (explicit) + return 0; + + /* implicit sync use bo fence in resv obj */ + if (write) { + struct reservation_object_list *fobj = + reservation_object_get_list(bo->tbo.resv); + + if (fobj && fobj->shared_count > 0) { + for (i = 0; i < fobj->shared_count; i++) { + f = rcu_dereference_protected( + fobj->shared[i], + reservation_object_held(bo->tbo.resv)); + if (f->context != context) { + err = lima_sched_task_add_dep(task, f); + if (err) + return err; + } + } + } + } + + f = reservation_object_get_excl(bo->tbo.resv); + if (f) { + err = lima_sched_task_add_dep(task, f); + if (err) + return err; + } + + return 0; +} + +static int lima_gem_add_deps(struct lima_ctx_mgr *mgr, struct lima_submit *submit) +{ + int i, err = 0; + + for (i = 0; i < submit->nr_deps; i++) { + union drm_lima_gem_submit_dep *dep = submit->deps + i; + struct dma_fence *fence; + + if (dep->type == LIMA_SUBMIT_DEP_FENCE) { + fence = lima_ctx_get_native_fence( + mgr, dep->fence.ctx, dep->fence.pipe, + dep->fence.seq); + if (IS_ERR(fence)) { + err = PTR_ERR(fence); + break; + } + } + else if (dep->type == LIMA_SUBMIT_DEP_SYNC_FD) { + fence = sync_file_get_fence(dep->sync_fd.fd); + if (!fence) { + err = -EINVAL; + break; + } + } + else { + err = -EINVAL; + break; + } + + if (fence) { + err = lima_sched_task_add_dep(submit->task, fence); + dma_fence_put(fence); + if (err) + break; + } + } + + return err; +} + +static int lima_gem_get_sync_fd(struct dma_fence *fence) +{ + struct sync_file *sync_file; + int fd; + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) + return fd; + + sync_file = sync_file_create(fence); + if (!sync_file) { + put_unused_fd(fd); + return -ENOMEM; + } + + fd_install(fd, sync_file->file); + return fd; +} + +int lima_gem_submit(struct drm_file *file, struct lima_submit *submit) +{ + int i, err = 0; + struct lima_drm_priv *priv = to_lima_drm_priv(file); + struct lima_vm *vm = priv->vm; + + INIT_LIST_HEAD(&submit->validated); + INIT_LIST_HEAD(&submit->duplicates); + + for (i = 0; i < submit->nr_bos; i++) { + struct drm_gem_object *obj; + struct drm_lima_gem_submit_bo *bo = submit->bos + i; + struct ttm_validate_buffer *vb = submit->vbs + i; + + obj = drm_gem_object_lookup(file, bo->handle); + if (!obj) { + err = -ENOENT; + goto out0; + } + + vb->bo = &to_lima_bo(obj)->tbo; + vb->shared = !(bo->flags & LIMA_SUBMIT_BO_WRITE); + list_add_tail(&vb->head, &submit->validated); + } + + submit->vm_pd_vb.bo = &vm->pd->tbo; + submit->vm_pd_vb.shared = true; + list_add(&submit->vm_pd_vb.head, &submit->validated); + + err = ttm_eu_reserve_buffers(&submit->ticket, &submit->validated, + true, &submit->duplicates); + if (err) + goto out0; + + err = lima_sched_task_init( + submit->task, submit->ctx->context + submit->pipe, vm); + if (err) + goto out1; + + err = lima_gem_add_deps(&priv->ctx_mgr, submit); + if (err) + goto out2; + + for (i = 0; i < submit->nr_bos; i++) { + struct ttm_validate_buffer *vb = submit->vbs + i; + struct lima_bo *bo = ttm_to_lima_bo(vb->bo); + err = lima_gem_sync_bo( + submit->task, bo, !vb->shared, + submit->flags & LIMA_SUBMIT_FLAG_EXPLICIT_FENCE); + if (err) + goto out2; + } + + if (submit->flags & LIMA_SUBMIT_FLAG_SYNC_FD_OUT) { + int fd = lima_gem_get_sync_fd( + &submit->task->base.s_fence->finished); + if (fd < 0) { + err = fd; + goto out2; + } + submit->sync_fd = fd; + } + + submit->fence = lima_sched_context_queue_task( + submit->ctx->context + submit->pipe, submit->task, + &submit->done); + + ttm_eu_fence_buffer_objects(&submit->ticket, &submit->validated, + &submit->task->base.s_fence->finished); + +out2: + if (err) + lima_sched_task_fini(submit->task); +out1: + if (err) + ttm_eu_backoff_reservation(&submit->ticket, &submit->validated); +out0: + for (i = 0; i < submit->nr_bos; i++) { + struct ttm_validate_buffer *vb = submit->vbs + i; + if (!vb->bo) + break; + drm_gem_object_put_unlocked(&ttm_to_lima_bo(vb->bo)->gem); + } + return err; +} + +int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, u64 timeout_ns) +{ + bool write = op & LIMA_GEM_WAIT_WRITE; + struct drm_gem_object *obj; + struct lima_bo *bo; + signed long ret; + unsigned long timeout; + + obj = drm_gem_object_lookup(file, handle); + if (!obj) + return -ENOENT; + + bo = to_lima_bo(obj); + + timeout = timeout_ns ? lima_timeout_to_jiffies(timeout_ns) : 0; + + ret = lima_bo_reserve(bo, true); + if (ret) + goto out; + + /* must use long for result check because in 64bit arch int + * will overflow if timeout is too large and get <0 result + */ + ret = reservation_object_wait_timeout_rcu(bo->tbo.resv, write, true, timeout); + if (ret == 0) + ret = timeout ? -ETIMEDOUT : -EBUSY; + else if (ret > 0) + ret = 0; + + lima_bo_unreserve(bo); +out: + drm_gem_object_put_unlocked(obj); + return ret; +} diff --git a/drivers/gpu/drm/lima/lima_gem.h b/drivers/gpu/drm/lima/lima_gem.h new file mode 100644 index 000000000000..8e3c4110825d --- /dev/null +++ b/drivers/gpu/drm/lima/lima_gem.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017-2018 Lima Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __LIMA_GEM_H__ +#define __LIMA_GEM_H__ + +struct lima_bo; +struct lima_submit; + +struct lima_bo *lima_gem_create_bo(struct drm_device *dev, u32 size, u32 flags); +int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, + u32 size, u32 flags, u32 *handle); +void lima_gem_free_object(struct drm_gem_object *obj); +int lima_gem_object_open(struct drm_gem_object *obj, struct drm_file *file); +void lima_gem_object_close(struct drm_gem_object *obj, struct drm_file *file); +int lima_gem_mmap_offset(struct drm_file *file, u32 handle, u64 *offset); +int lima_gem_mmap(struct file *filp, struct vm_area_struct *vma); +int lima_gem_va_map(struct drm_file *file, u32 handle, u32 flags, u32 va); +int lima_gem_va_unmap(struct drm_file *file, u32 handle, u32 va); +int lima_gem_submit(struct drm_file *file, struct lima_submit *submit); +int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, u64 timeout_ns); + +#endif