From patchwork Tue May 6 13:26:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mika Kuoppala X-Patchwork-Id: 4121231 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 83BD7BFF02 for ; Tue, 6 May 2014 13:26:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 56C7E2020F for ; Tue, 6 May 2014 13:26:24 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 19957201DE for ; Tue, 6 May 2014 13:26:23 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2FB016EB5B; Tue, 6 May 2014 06:26:22 -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 0DE556EB5A for ; Tue, 6 May 2014 06:26:20 -0700 (PDT) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 06 May 2014 06:26:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.97,997,1389772800"; d="scan'208";a="534333133" Received: from rosetta.fi.intel.com (HELO rosetta) ([10.237.72.66]) by fmsmga002.fm.intel.com with ESMTP; 06 May 2014 06:26:16 -0700 Received: by rosetta (Postfix, from userid 1000) id 88985800B6; Tue, 6 May 2014 16:26:16 +0300 (EEST) From: Mika Kuoppala To: intel-gfx@lists.freedesktop.org Date: Tue, 6 May 2014 16:26:05 +0300 Message-Id: <1399382766-25116-2-git-send-email-mika.kuoppala@intel.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1399382766-25116-1-git-send-email-mika.kuoppala@intel.com> References: <1399382766-25116-1-git-send-email-mika.kuoppala@intel.com> MIME-Version: 1.0 Cc: ben@bwidawsk.net, miku@iki.fi, kristen@linux.intel.com Subject: [Intel-gfx] =?utf-8?q?=5BPATCH_v2_1/2=5D_drm/i915=3A_add_render_s?= =?utf-8?q?tate_initialization?= 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: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-4.8 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 HW guys say that it is not a cool idea to let device go into rc6 without proper 3d pipeline state. For each new uninitialized context, generate a valid null render state to be run on context creation. This patch introduces a skeleton with empty states. v2: - No need to vmap (Chris Wilson) - use .c files for state (Daniel Vetter) - no need to flush as i915_add_request does it - remove parameter for batch alloc size - don't wait for the init (Ben Widawsky) Tested-by: Kristen Carlson Accardi (v1) Signed-off-by: Mika Kuoppala --- drivers/gpu/drm/i915/Makefile | 6 + drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_gem_context.c | 6 + drivers/gpu/drm/i915/i915_gem_render_state.c | 186 +++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_renderstate.h | 48 +++++++ drivers/gpu/drm/i915/intel_renderstate_gen6.c | 10 ++ drivers/gpu/drm/i915/intel_renderstate_gen7.c | 10 ++ drivers/gpu/drm/i915/intel_renderstate_gen8.c | 10 ++ 8 files changed, 278 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_gem_render_state.c create mode 100644 drivers/gpu/drm/i915/intel_renderstate.h create mode 100644 drivers/gpu/drm/i915/intel_renderstate_gen6.c create mode 100644 drivers/gpu/drm/i915/intel_renderstate_gen7.c create mode 100644 drivers/gpu/drm/i915/intel_renderstate_gen8.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index b1445b7..2446916 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -18,6 +18,7 @@ i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o # GEM code i915-y += i915_cmd_parser.o \ i915_gem_context.o \ + i915_gem_render_state.o \ i915_gem_debug.o \ i915_gem_dmabuf.o \ i915_gem_evict.o \ @@ -32,6 +33,11 @@ i915-y += i915_cmd_parser.o \ intel_ringbuffer.o \ intel_uncore.o +# autogenerated null render state +i915-y += intel_renderstate_gen6.o \ + intel_renderstate_gen7.o \ + intel_renderstate_gen8.o + # modesetting core code i915-y += intel_bios.o \ intel_display.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3fc2e3d..a2fc605 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2336,6 +2336,8 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file); +/* i915_gem_render_state.c */ +int i915_gem_render_state_init(struct intel_ring_buffer *ring); /* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index f77b4c1..f7ad59e 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -699,6 +699,12 @@ static int do_switch(struct intel_ring_buffer *ring, /* obj is kept alive until the next request by its active ref */ i915_gem_object_ggtt_unpin(from->obj); i915_gem_context_unreference(from); + } else { + if (to->is_initialized == false) { + ret = i915_gem_render_state_init(ring); + if (ret) + DRM_ERROR("init render state: %d\n", ret); + } } to->is_initialized = true; diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c new file mode 100644 index 0000000..48907ab --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -0,0 +1,186 @@ +/* + * Copyright © 2014 Intel Corporation + * + * 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 (including the next + * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Authors: + * Mika Kuoppala + * + */ + +#include "i915_drv.h" +#include "intel_renderstate.h" + +struct i915_render_state { + struct drm_i915_gem_object *obj; + unsigned long ggtt_offset; + void *batch; + u32 size; + u32 len; +}; + +static struct i915_render_state *render_state_alloc(struct drm_device *dev) +{ + struct i915_render_state *so; + struct page *page; + int ret; + + so = kzalloc(sizeof(*so), GFP_KERNEL); + if (!so) + return ERR_PTR(-ENOMEM); + + so->obj = i915_gem_alloc_object(dev, 4096); + if (so->obj == NULL) { + ret = -ENOMEM; + goto free; + } + so->size = 4096; + + ret = i915_gem_obj_ggtt_pin(so->obj, 4096, 0); + if (ret) + goto free_gem; + + BUG_ON(so->obj->pages->nents != 1); + page = sg_page(so->obj->pages->sgl); + + so->batch = kmap(page); + if (!so->batch) { + ret = -ENOMEM; + goto unpin; + } + + so->ggtt_offset = i915_gem_obj_ggtt_offset(so->obj); + + return so; +unpin: + i915_gem_object_ggtt_unpin(so->obj); +free_gem: + drm_gem_object_unreference(&so->obj->base); +free: + kfree(so); + return ERR_PTR(ret); +} + +static void render_state_free(struct i915_render_state *so) +{ + kunmap(so->batch); + i915_gem_object_ggtt_unpin(so->obj); + drm_gem_object_unreference(&so->obj->base); + kfree(so); +} + +static const struct intel_renderstate_rodata * +render_state_get_rodata(const int gen) +{ + switch (gen) { + case 6: + return &gen6_null_state; + case 7: + return &gen7_null_state; + case 8: + return &gen8_null_state; + } + + return NULL; +} + +static int render_state_setup(const int gen, struct i915_render_state *so) +{ + const struct intel_renderstate_rodata *rodata; + const u64 goffset = i915_gem_obj_ggtt_offset(so->obj); + u32 reloc_index = 0; + u32 * const d = so->batch; + unsigned int i = 0; + + rodata = render_state_get_rodata(gen); + if (rodata == NULL) + return -ENOENT; + + if (rodata->batch_items * 4 > so->size) + return -EINVAL; + + while (i < rodata->batch_items) { + u32 s = rodata->batch[i]; + + if (reloc_index < rodata->reloc_items && + i * 4 == rodata->reloc[reloc_index]) { + + s += goffset & 0xffffffff; + + /* We keep batch offsets max 32bit */ + if (gen >= 8) { + if (i + 1 >= rodata->batch_items || + rodata->batch[i + 1] != 0) + return -EINVAL; + + d[i] = s; + i++; + s = (goffset & 0xffffffff00000000ull) >> 32; + } + + reloc_index++; + } + + d[i] = s; + i++; + } + + if (rodata->reloc_items != reloc_index) { + DRM_ERROR("not all relocs resolved, %d out of %d\n", + reloc_index, rodata->reloc_items); + return -EINVAL; + } + + so->len = rodata->batch_items * 4; + + return 0; +} + +int i915_gem_render_state_init(struct intel_ring_buffer *ring) +{ + const int gen = INTEL_INFO(ring->dev)->gen; + struct i915_render_state *so; + u32 seqno; + int ret; + + if (gen < 6) + return 0; + + so = render_state_alloc(ring->dev); + if (IS_ERR(so)) + return PTR_ERR(so); + + ret = render_state_setup(gen, so); + if (ret) + goto out; + + ret = ring->dispatch_execbuffer(ring, + i915_gem_obj_ggtt_offset(so->obj), + so->len, + I915_DISPATCH_SECURE); + if (ret) + goto out; + + ret = i915_add_request(ring, &seqno); + +out: + render_state_free(so); + return ret; +} diff --git a/drivers/gpu/drm/i915/intel_renderstate.h b/drivers/gpu/drm/i915/intel_renderstate.h new file mode 100644 index 0000000..a5e783a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_renderstate.h @@ -0,0 +1,48 @@ +/* + * Copyright © 2014 Intel Corporation + * + * 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 (including the next + * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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 _INTEL_RENDERSTATE_H +#define _INTEL_RENDERSTATE_H + +#include + +struct intel_renderstate_rodata { + const u32 *reloc; + const u32 reloc_items; + const u32 *batch; + const u32 batch_items; +}; + +extern const struct intel_renderstate_rodata gen6_null_state; +extern const struct intel_renderstate_rodata gen7_null_state; +extern const struct intel_renderstate_rodata gen8_null_state; + +#define RO_RENDERSTATE(_g) \ + const struct intel_renderstate_rodata gen ## _g ## _null_state = { \ + .reloc = gen ## _g ## _null_state_relocs, \ + .reloc_items = sizeof(gen ## _g ## _null_state_relocs)/4, \ + .batch = gen ## _g ## _null_state_batch, \ + .batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \ + } + +#endif /* INTEL_RENDERSTATE_H */ diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen6.c b/drivers/gpu/drm/i915/intel_renderstate_gen6.c new file mode 100644 index 0000000..5ed251a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_renderstate_gen6.c @@ -0,0 +1,10 @@ +#include "intel_renderstate.h" + +static const u32 gen6_null_state_relocs[] = { +}; + +static const u32 gen6_null_state_batch[] = { + 0x0a << 23, /* MI_BATCH_BUFFER_END */ +}; + +RO_RENDERSTATE(6); diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen7.c b/drivers/gpu/drm/i915/intel_renderstate_gen7.c new file mode 100644 index 0000000..5333f44 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_renderstate_gen7.c @@ -0,0 +1,10 @@ +#include "intel_renderstate.h" + +static const u32 gen7_null_state_relocs[] = { +}; + +static const u32 gen7_null_state_batch[] = { + 0x0a << 23, /* MI_BATCH_BUFFER_END */ +}; + +RO_RENDERSTATE(7); diff --git a/drivers/gpu/drm/i915/intel_renderstate_gen8.c b/drivers/gpu/drm/i915/intel_renderstate_gen8.c new file mode 100644 index 0000000..88c3733 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_renderstate_gen8.c @@ -0,0 +1,10 @@ +#include "intel_renderstate.h" + +static const u32 gen8_null_state_relocs[] = { +}; + +static const u32 gen8_null_state_batch[] = { + 0x0a << 23, /* MI_BATCH_BUFFER_END */ +}; + +RO_RENDERSTATE(8);