From patchwork Thu Jan 11 22:24:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 10158799 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 0104760170 for ; Thu, 11 Jan 2018 22:24:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E527B2838F for ; Thu, 11 Jan 2018 22:24:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D9F6C286C5; Thu, 11 Jan 2018 22:24:54 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 0014B2838F for ; Thu, 11 Jan 2018 22:24:53 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 01E876E4AD; Thu, 11 Jan 2018 22:24:53 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qk0-x243.google.com (mail-qk0-x243.google.com [IPv6:2607:f8b0:400d:c09::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8BD436E488; Thu, 11 Jan 2018 22:24:51 +0000 (UTC) Received: by mail-qk0-x243.google.com with SMTP id q1so6370001qkb.9; Thu, 11 Jan 2018 14:24:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=SBkqz+GMjnYPd5VMNISrs4LWH+eE4b/ja7btfqyw4hY=; b=kZKIMQwetJQQb+r6WHv5SxnOOLUgzgzryBSQhKri0IGXDW69pcA+rAvrFDT3eiy56X njOsOx8orKE0msaoIS2LfJWr//H5+nSEGqXObfHaXRV638ciWtCsrvhF4BgG0bIiILOL cUj5NOtlI/ueIjYW2ijAqqlMNBPqs7GVjC2SztmVjX0ydyOw3evSnDsJ/vs5V+WT+DUy dVwZvznEtPJhIcKlpXRisZgrgPaqonuepBEDfP8zFvO1shYbKfeZEZWrm/q+0sF/T/lO H/R1NHIzNlRcKuRJ8t7xj0VnrshpSjKFVth4gTAcsAphZ9NXuM3fto7oovstTAsJDkeu xndw== 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; bh=SBkqz+GMjnYPd5VMNISrs4LWH+eE4b/ja7btfqyw4hY=; b=q6DwxqejH5Z1vWBvUlrXyLAPKEFc74qxrbCVe0zBpLhNdXplaaQ8sJ2p29QaNHLZ6u ExhdHiYlM2sWxxgCAIadGPoH/Dl3+h4JJsDtMfzbbyGwAwhyw9sc6GI3rLpFq2DuC96Y xcFsdyYsqp0BYCgSCVnIHtOZy9jcIbDg63BD89F4zE/c5cUK+Pau/cpUbM7Ftnp3ou5B ERp6XxIgISfWbNQ6kROg/a0j6svx1LYQhVL0yaPqa9ocexRBoPwg5Qlhsl62BIdgBYKs 4D4mxJWKQWBgMyRhmZWYGiBta+K9IjhvpgISsaFLO+mjRtrnTrHeVypgBr8415QsV53i pmEw== X-Gm-Message-State: AKwxytd9bbIJNzyWbXxP/026HkVwtCwVW4N1VHM2DAFbOWZYJvlvPGWX xan7paW3nMnhLBf5r4+1rT5S+Q== X-Google-Smtp-Source: ACJfBovc2FNA6HBViIvGkPwewrdvuVW0iW7E5iw+0tGtqCQJ3kCFK+o3LsP36oP03hgsMZgGeEXDhQ== X-Received: by 10.55.101.215 with SMTP id z206mr10714048qkb.62.1515709490147; Thu, 11 Jan 2018 14:24:50 -0800 (PST) Received: from localhost (p200300E41F21CF00227DB10B7BBDB590.dip0.t-ipconnect.de. [2003:e4:1f21:cf00:227d:b10b:7bbd:b590]) by smtp.gmail.com with ESMTPSA id h55sm13152310qta.75.2018.01.11.14.24.49 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 11 Jan 2018 14:24:49 -0800 (PST) From: Thierry Reding To: nouveau@lists.freedesktop.org Subject: [PATCH libdrm] nouveau: Support fence FDs Date: Thu, 11 Jan 2018 23:24:47 +0100 Message-Id: <20180111222447.29455-1-thierry.reding@gmail.com> X-Mailer: git-send-email 2.15.1 Cc: dri-devel@lists.freedesktop.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Reding Add a new nouveau_pushbuf_kick_fence() function that takes and emits a sync fence FD. The fence FD can be waited on, or merged with other fence FDs, or passed back to the kernel as a prerequisite for a subsequent HW operation. Based heavily on work by Lauri Peltonen Signed-off-by: Thierry Reding --- For the kernel patches that add the new IOCTL, see the series at: https://patchwork.freedesktop.org/series/36361/ include/drm/nouveau_drm.h | 23 ++++++++ nouveau/nouveau.h | 2 + nouveau/pushbuf.c | 130 ++++++++++++++++++++++++++++++++++------------ 3 files changed, 121 insertions(+), 34 deletions(-) diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h index cb077821c43f..e7f1a2aefd22 100644 --- a/include/drm/nouveau_drm.h +++ b/include/drm/nouveau_drm.h @@ -178,6 +178,28 @@ struct drm_nouveau_gem_pushbuf { __u64 gart_available; }; +#define NOUVEAU_GEM_PUSHBUF_FENCE_WAIT (1 << 0) +#define NOUVEAU_GEM_PUSHBUF_FENCE_EMIT (1 << 1) +#define NOUVEAU_GEM_PUSHBUF_FLAGS (NOUVEAU_GEM_PUSHBUF_FENCE_WAIT | \ + NOUVEAU_GEM_PUSHBUF_FENCE_EMIT) + +struct drm_nouveau_gem_pushbuf2 { + uint32_t channel; + uint32_t nr_buffers; + uint64_t buffers; + uint32_t nr_relocs; + uint32_t nr_push; + uint64_t relocs; + uint64_t push; + uint32_t suffix0; + uint32_t suffix1; + uint64_t vram_available; + uint64_t gart_available; + uint32_t flags; + int32_t fence; + uint64_t reserved; +}; + #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 #define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 @@ -212,6 +234,7 @@ struct drm_nouveau_sarea { #define DRM_NOUVEAU_GEM_CPU_PREP 0x42 #define DRM_NOUVEAU_GEM_CPU_FINI 0x43 #define DRM_NOUVEAU_GEM_INFO 0x44 +#define DRM_NOUVEAU_GEM_PUSHBUF2 0x45 #if defined(__cplusplus) } diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h index 335ce77dca77..70d680700faf 100644 --- a/nouveau/nouveau.h +++ b/nouveau/nouveau.h @@ -226,6 +226,8 @@ void nouveau_pushbuf_reloc(struct nouveau_pushbuf *, struct nouveau_bo *, int nouveau_pushbuf_validate(struct nouveau_pushbuf *); uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *, struct nouveau_bo *); int nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object *chan); +int nouveau_pushbuf_kick_fence(struct nouveau_pushbuf *, + struct nouveau_object *chan, int *fence); struct nouveau_bufctx * nouveau_pushbuf_bufctx(struct nouveau_pushbuf *, struct nouveau_bufctx *); diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c index 035e3019f2cd..f13804db7534 100644 --- a/nouveau/pushbuf.c +++ b/nouveau/pushbuf.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -77,7 +78,7 @@ nouveau_pushbuf(struct nouveau_pushbuf *push) } static int pushbuf_validate(struct nouveau_pushbuf *, bool); -static int pushbuf_flush(struct nouveau_pushbuf *); +static int pushbuf_flush(struct nouveau_pushbuf *, int *); static bool pushbuf_kref_fits(struct nouveau_pushbuf *push, struct nouveau_bo *bo, @@ -172,7 +173,7 @@ pushbuf_kref(struct nouveau_pushbuf *push, struct nouveau_bo *bo, */ fpush = cli_push_get(push->client, bo); if (fpush && fpush != push) - pushbuf_flush(fpush); + pushbuf_flush(fpush, NULL); kref = cli_kref_get(push->client, bo); if (kref) { @@ -307,7 +308,8 @@ pushbuf_dump(struct nouveau_pushbuf_krec *krec, int krec_id, int chid) } static int -pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) +pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan, + int *fence) { struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push); struct nouveau_pushbuf_krec *krec = nvpb->list; @@ -315,9 +317,9 @@ pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) struct nouveau_drm *drm = nouveau_drm(&dev->object); struct drm_nouveau_gem_pushbuf_bo_presumed *info; struct drm_nouveau_gem_pushbuf_bo *kref; - struct drm_nouveau_gem_pushbuf req; struct nouveau_fifo *fifo = chan->data; struct nouveau_bo *bo; + int fence_out = -1; int krec_id = 0; int ret = 0, i; @@ -330,35 +332,81 @@ pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) nouveau_pushbuf_data(push, NULL, 0, 0); while (krec && krec->nr_push) { - req.channel = fifo->channel; - req.nr_buffers = krec->nr_buffer; - req.buffers = (uint64_t)(unsigned long)krec->buffer; - req.nr_relocs = krec->nr_reloc; - req.nr_push = krec->nr_push; - req.relocs = (uint64_t)(unsigned long)krec->reloc; - req.push = (uint64_t)(unsigned long)krec->push; - req.suffix0 = nvpb->suffix0; - req.suffix1 = nvpb->suffix1; - req.vram_available = 0; /* for valgrind */ - req.gart_available = 0; - if (dbg_on(0)) pushbuf_dump(krec, krec_id++, fifo->channel); + /* TODO If fence is requested, force kickoff. */ + if (fence) { + struct drm_nouveau_gem_pushbuf2 req; + + memset(&req, 0, sizeof(req)); + req.channel = fifo->channel; + req.nr_buffers = krec->nr_buffer; + req.buffers = (uint64_t)(unsigned long)krec->buffer; + req.nr_relocs = krec->nr_reloc; + req.nr_push = krec->nr_push; + req.relocs = (uint64_t)(unsigned long)krec->reloc; + req.push = (uint64_t)(unsigned long)krec->push; + req.suffix0 = nvpb->suffix0; + req.suffix1 = nvpb->suffix1; + req.vram_available = 0; /* for valgrind */ + req.gart_available = 0; + req.flags = 0; + + if (*fence >= 0) + req.flags |= NOUVEAU_GEM_PUSHBUF_FENCE_WAIT; + + req.flags |= NOUVEAU_GEM_PUSHBUF_FENCE_EMIT; + + req.fence = *fence; + req.reserved = 0; + #ifndef SIMULATE - ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_PUSHBUF, - &req, sizeof(req)); - nvpb->suffix0 = req.suffix0; - nvpb->suffix1 = req.suffix1; - dev->vram_limit = (req.vram_available * - nouveau_device(dev)->vram_limit_percent) / 100; - dev->gart_limit = (req.gart_available * - nouveau_device(dev)->gart_limit_percent) / 100; + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_PUSHBUF2, + &req, sizeof(req)); + nvpb->suffix0 = req.suffix0; + nvpb->suffix1 = req.suffix1; + dev->vram_limit = (req.vram_available * + nouveau_device(dev)->vram_limit_percent) / 100; + dev->gart_limit = (req.gart_available * + nouveau_device(dev)->gart_limit_percent) / 100; #else - if (dbg_on(31)) - ret = -EINVAL; + if (dbg_on(31)) + ret = -EINVAL; #endif + if (!ret) + fence_out = req.fence; + } else { + struct drm_nouveau_gem_pushbuf req; + + req.channel = fifo->channel; + req.nr_buffers = krec->nr_buffer; + req.buffers = (uint64_t)(unsigned long)krec->buffer; + req.nr_relocs = krec->nr_reloc; + req.nr_push = krec->nr_push; + req.relocs = (uint64_t)(unsigned long)krec->reloc; + req.push = (uint64_t)(unsigned long)krec->push; + req.suffix0 = nvpb->suffix0; + req.suffix1 = nvpb->suffix1; + req.vram_available = 0; /* for valgrind */ + req.gart_available = 0; + +#ifndef SIMULATE + ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_PUSHBUF, + &req, sizeof(req)); + nvpb->suffix0 = req.suffix0; + nvpb->suffix1 = req.suffix1; + dev->vram_limit = (req.vram_available * + nouveau_device(dev)->vram_limit_percent) / 100; + dev->gart_limit = (req.gart_available * + nouveau_device(dev)->gart_limit_percent) / 100; +#else + if (dbg_on(31)) + ret = -EINVAL; +#endif + } + if (ret) { err("kernel rejected pushbuf: %s\n", strerror(-ret)); pushbuf_dump(krec, krec_id++, fifo->channel); @@ -388,11 +436,18 @@ pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan) krec = krec->next; } + if (!ret && fence) { + if (*fence >= 0) + close(*fence); + + *fence = fence_out; + } + return ret; } static int -pushbuf_flush(struct nouveau_pushbuf *push) +pushbuf_flush(struct nouveau_pushbuf *push, int *fence) { struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push); struct nouveau_pushbuf_krec *krec = nvpb->krec; @@ -402,7 +457,7 @@ pushbuf_flush(struct nouveau_pushbuf *push) int ret = 0, i; if (push->channel) { - ret = pushbuf_submit(push, push->channel); + ret = pushbuf_submit(push, push->channel, fence); } else { nouveau_pushbuf_data(push, NULL, 0, 0); krec->next = malloc(sizeof(*krec)); @@ -472,7 +527,7 @@ pushbuf_refn(struct nouveau_pushbuf *push, bool retry, if (ret) { pushbuf_refn_fail(push, sref, krec->nr_reloc); if (retry) { - pushbuf_flush(push); + pushbuf_flush(push, NULL); nouveau_pushbuf_space(push, 0, 0, 0); return pushbuf_refn(push, false, refs, nr); } @@ -524,7 +579,7 @@ pushbuf_validate(struct nouveau_pushbuf *push, bool retry) if (ret) { pushbuf_refn_fail(push, sref, srel); if (retry) { - pushbuf_flush(push); + pushbuf_flush(push, NULL); return pushbuf_validate(push, false); } } @@ -676,7 +731,7 @@ nouveau_pushbuf_space(struct nouveau_pushbuf *push, krec->nr_reloc + relocs >= NOUVEAU_GEM_MAX_RELOCS || krec->nr_push + pushes >= NOUVEAU_GEM_MAX_PUSH) { if (nvpb->bo && krec->nr_buffer) - pushbuf_flush(push); + pushbuf_flush(push, NULL); flushed = true; } @@ -772,10 +827,17 @@ nouveau_pushbuf_refd(struct nouveau_pushbuf *push, struct nouveau_bo *bo) } int -nouveau_pushbuf_kick(struct nouveau_pushbuf *push, struct nouveau_object *chan) +nouveau_pushbuf_kick_fence(struct nouveau_pushbuf *push, + struct nouveau_object *chan, int *fence) { if (!push->channel) - return pushbuf_submit(push, chan); - pushbuf_flush(push); + return pushbuf_submit(push, chan, fence); + pushbuf_flush(push, fence); return pushbuf_validate(push, false); } + +int +nouveau_pushbuf_kick(struct nouveau_pushbuf *pushbuf, struct nouveau_object *chan) +{ + return nouveau_pushbuf_kick_fence(pushbuf, chan, NULL); +}