From patchwork Fri Mar 10 04:32:18 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 9614613 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 188D360414 for ; Fri, 10 Mar 2017 04:35:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 07BCE285A9 for ; Fri, 10 Mar 2017 04:35:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EDFC0286EF; Fri, 10 Mar 2017 04:35:09 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 79B41285A9 for ; Fri, 10 Mar 2017 04:35:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=mzWiSzmtiFC/5xlTbPwI6IRpDcMoGsQ1jmR2Kf6dUYM=; b=uOros37TiBgxZfpMLhUt1Tcpic nIdFxNZVzYKxOIAOv/kz3qit3MploWiwWNy+A6Pv//gCbwgnmFS2wWvTlY8r1fPyoG/vFGcsKoGta +WYa4lOY6le0q0ffjgX7cbJvinSk1C0JXqT7f6bJuKeqD8fLUE0o6ZmdAeoqRfUZ0LUYU5UPIn+SX 6+/Y5000x8hW46uc2zhsJTsdEv3VcrYsVW+wcj5XrGv8pFPAEJRMFZiXcEOKEvIFUIUHKUEaY8a6q Kinqg24zBko2Pz50GAzGg/m4EgB3Tr6tJe/noOWMHBWWcAPfU/tIW8+8yilj18HC8Afb39rZls9va 0uv6+B5Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cmCGh-0007dE-VW; Fri, 10 Mar 2017 04:35:08 +0000 Received: from mail-qk0-x234.google.com ([2607:f8b0:400d:c09::234]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cmCG9-0006jd-Lw for linux-arm-kernel@lists.infradead.org; Fri, 10 Mar 2017 04:34:37 +0000 Received: by mail-qk0-x234.google.com with SMTP id 1so151492313qkl.3 for ; Thu, 09 Mar 2017 20:34:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=A4Xu7zmUN12xNMXFFs7AOtek9bDyfFFp/xw29Wc7qeU=; b=WmPaQuLUn0HJc1w8Ju3DtrGhfuylbyUXxc16nzTV3QGhUXLIf8pMPZ5aSVcKUhreWl 7voaaMyw0p2zSy2oEBg7ZHW6kbHg8wXWR03140Q9Ak8aEHERKMdO36WfM6pcCGlv0/V3 Z8js3R3aQuBRD4M735YJWvUUN7jQL2xu8FM0o= 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=A4Xu7zmUN12xNMXFFs7AOtek9bDyfFFp/xw29Wc7qeU=; b=Y79mQlHe4vKcWoRFz+S+bn97H2HQoIKPFuBpSfjZYtru+lG38Z9xCrGpzj7VWoC6uY lKZzkseHwoZR+9LWEKiEMP2T3scK9I6bnj4idUsl6kVow4NP9N1tmqqYuYXcg5TPXR6B sbu+UZ2pQwsKeyl05uf4R8YZLCCAXWwCEfULeI2tWe0n2NgW5VpxnC2D/on1LrZVWD5L KyEtO/84MP7alqS5NfHH0hVQrUS4T1ltsFlXzYGhHUVHpx9rZE7SDUbnaIXr5ikE6NVO oiU88wfE9jfhXOLs4uelVGv3TWD8bHkTz2OSOaZlkiWR7ntTODpfHLt2WUxkypt1IsEc onPw== X-Gm-Message-State: AMke39m+tWmuJQUNWdSI31OeLIYiZr8r7DNWfBWvKeuB6MRV2N1cN9mp3I31pnu5K8+BalQo X-Received: by 10.55.17.206 with SMTP id 75mr18442245qkr.156.1489120452732; Thu, 09 Mar 2017 20:34:12 -0800 (PST) Received: from boxwood.roam.corp.google.com (cpe-75-189-128-87.nc.res.rr.com. [75.189.128.87]) by smtp.gmail.com with ESMTPSA id n19sm5697731qtn.35.2017.03.09.20.34.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 09 Mar 2017 20:34:11 -0800 (PST) From: Sean Paul To: linux-rockchip@lists.infradead.org, dri-devel@lists.freedesktop.org Subject: [PATCH 03/41] drm/rockchip: support prime import sg table Date: Thu, 9 Mar 2017 23:32:18 -0500 Message-Id: <20170310043305.17216-4-seanpaul@chromium.org> X-Mailer: git-send-email 2.12.0.246.ga2ecc84866-goog In-Reply-To: <20170310043305.17216-1-seanpaul@chromium.org> References: <20170310043305.17216-1-seanpaul@chromium.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170309_203434_017623_3629D626 X-CRM114-Status: GOOD ( 18.69 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: David Airlie , Mark Yao , Heiko Stuebner , linux-arm-kernel@lists.infradead.org, Haixia Shi MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Haixia Shi The prime fd to handle ioctl was not used with rockchip before. Support was added in order to pass graphics_Gbm and to support potential uses within Chrome OS (e.g. zero-copy video decode, camera). Signed-off-by: Haixia Shi Tested-by: Heiko Stuebner --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 1 + drivers/gpu/drm/rockchip/rockchip_drm_gem.c | 118 ++++++++++++++++++++++++++-- drivers/gpu/drm/rockchip/rockchip_drm_gem.h | 5 +- 3 files changed, 115 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index ccf456938792..1e371b7a1506 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -238,6 +238,7 @@ static struct drm_driver rockchip_drm_driver = { .gem_prime_import = drm_gem_prime_import, .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, + .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table, .gem_prime_vmap = rockchip_gem_prime_vmap, .gem_prime_vunmap = rockchip_gem_prime_vunmap, .gem_prime_mmap = rockchip_gem_mmap_buf, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index df9e57064f19..5dffe276d2a7 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -16,6 +16,8 @@ #include #include #include + +#include #include #include "rockchip_drm_drv.h" @@ -308,12 +310,10 @@ static void rockchip_gem_release_object(struct rockchip_gem_object *rk_obj) } struct rockchip_gem_object * - rockchip_gem_create_object(struct drm_device *drm, unsigned int size, - bool alloc_kmap) + rockchip_gem_alloc_object(struct drm_device *drm, unsigned int size) { struct rockchip_gem_object *rk_obj; struct drm_gem_object *obj; - int ret; size = round_up(size, PAGE_SIZE); @@ -325,6 +325,20 @@ struct rockchip_gem_object * drm_gem_object_init(drm, obj, size); + return rk_obj; +} + +struct rockchip_gem_object * +rockchip_gem_create_object(struct drm_device *drm, unsigned int size, + bool alloc_kmap) +{ + struct rockchip_gem_object *rk_obj; + int ret; + + rk_obj = rockchip_gem_alloc_object(drm, size); + if (IS_ERR(rk_obj)) + return rk_obj; + ret = rockchip_gem_alloc_buf(rk_obj, alloc_kmap); if (ret) goto err_free_rk_obj; @@ -342,11 +356,21 @@ struct rockchip_gem_object * */ void rockchip_gem_free_object(struct drm_gem_object *obj) { - struct rockchip_gem_object *rk_obj; - - rk_obj = to_rockchip_obj(obj); + struct drm_device *drm = obj->dev; + struct rockchip_drm_private *private = drm->dev_private; + struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); - rockchip_gem_free_buf(rk_obj); + if (obj->import_attach) { + if (private->domain) { + rockchip_gem_iommu_unmap(rk_obj); + } else { + dma_unmap_sg(drm->dev, rk_obj->sgt->sgl, + rk_obj->sgt->nents, DMA_BIDIRECTIONAL); + } + drm_prime_gem_destroy(obj, rk_obj->sgt); + } else { + rockchip_gem_free_buf(rk_obj); + } rockchip_gem_release_object(rk_obj); } @@ -476,6 +500,86 @@ struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj) return sgt; } +static unsigned long rockchip_sg_get_contiguous_size(struct sg_table *sgt, + int count) +{ + struct scatterlist *s; + dma_addr_t expected = sg_dma_address(sgt->sgl); + unsigned int i; + unsigned long size = 0; + + for_each_sg(sgt->sgl, s, count, i) { + if (sg_dma_address(s) != expected) + break; + expected = sg_dma_address(s) + sg_dma_len(s); + size += sg_dma_len(s); + } + return size; +} + +static int +rockchip_gem_iommu_map_sg(struct drm_device *drm, + struct dma_buf_attachment *attach, + struct sg_table *sg, + struct rockchip_gem_object *rk_obj) +{ + rk_obj->sgt = sg; + return rockchip_gem_iommu_map(rk_obj); +} + +static int +rockchip_gem_dma_map_sg(struct drm_device *drm, + struct dma_buf_attachment *attach, + struct sg_table *sg, + struct rockchip_gem_object *rk_obj) +{ + int count = dma_map_sg(drm->dev, sg->sgl, sg->nents, + DMA_BIDIRECTIONAL); + if (!count) + return -EINVAL; + + if (rockchip_sg_get_contiguous_size(sg, count) < attach->dmabuf->size) { + DRM_ERROR("failed to map sg_table to contiguous linear address.\n"); + dma_unmap_sg(drm->dev, sg->sgl, sg->nents, + DMA_BIDIRECTIONAL); + return -EINVAL; + } + + rk_obj->dma_addr = sg_dma_address(sg->sgl); + rk_obj->sgt = sg; + return 0; +} + +struct drm_gem_object * +rockchip_gem_prime_import_sg_table(struct drm_device *drm, + struct dma_buf_attachment *attach, + struct sg_table *sg) +{ + struct rockchip_drm_private *private = drm->dev_private; + struct rockchip_gem_object *rk_obj; + int ret; + + rk_obj = rockchip_gem_alloc_object(drm, attach->dmabuf->size); + if (IS_ERR(rk_obj)) + return ERR_CAST(rk_obj); + + if (private->domain) + ret = rockchip_gem_iommu_map_sg(drm, attach, sg, rk_obj); + else + ret = rockchip_gem_dma_map_sg(drm, attach, sg, rk_obj); + + if (ret < 0) { + DRM_ERROR("failed to import sg table: %d\n", ret); + goto err_free_rk_obj; + } + + return &rk_obj->base; + +err_free_rk_obj: + rockchip_gem_release_object(rk_obj); + return ERR_PTR(ret); +} + void *rockchip_gem_prime_vmap(struct drm_gem_object *obj) { struct rockchip_gem_object *rk_obj = to_rockchip_obj(obj); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h index 3f6ea4d18a5c..89209a5f5e2c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.h @@ -36,8 +36,9 @@ struct rockchip_gem_object { struct sg_table *rockchip_gem_prime_get_sg_table(struct drm_gem_object *obj); struct drm_gem_object * -rockchip_gem_prime_import_sg_table(struct drm_device *dev, size_t size, - struct sg_table *sgt); +rockchip_gem_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sg); void *rockchip_gem_prime_vmap(struct drm_gem_object *obj); void rockchip_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);