1 /* 2 * Copyright © 2016 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 */ 24 25 #include "i915_drv.h" 26 #include "intel_ringbuffer.h" 27 #include "intel_lrc.h" 28 29 static const struct engine_info { 30 const char *name; 31 unsigned exec_id; 32 unsigned guc_id; 33 u32 mmio_base; 34 unsigned irq_shift; 35 int (*init_legacy)(struct intel_engine_cs *engine); 36 int (*init_execlists)(struct intel_engine_cs *engine); 37 } intel_engines[] = { 38 [RCS] = { 39 .name = "render ring", 40 .exec_id = I915_EXEC_RENDER, 41 .guc_id = GUC_RENDER_ENGINE, 42 .mmio_base = RENDER_RING_BASE, 43 .irq_shift = GEN8_RCS_IRQ_SHIFT, 44 .init_execlists = logical_render_ring_init, 45 .init_legacy = intel_init_render_ring_buffer, 46 }, 47 [BCS] = { 48 .name = "blitter ring", 49 .exec_id = I915_EXEC_BLT, 50 .guc_id = GUC_BLITTER_ENGINE, 51 .mmio_base = BLT_RING_BASE, 52 .irq_shift = GEN8_BCS_IRQ_SHIFT, 53 .init_execlists = logical_xcs_ring_init, 54 .init_legacy = intel_init_blt_ring_buffer, 55 }, 56 [VCS] = { 57 .name = "bsd ring", 58 .exec_id = I915_EXEC_BSD, 59 .guc_id = GUC_VIDEO_ENGINE, 60 .mmio_base = GEN6_BSD_RING_BASE, 61 .irq_shift = GEN8_VCS1_IRQ_SHIFT, 62 .init_execlists = logical_xcs_ring_init, 63 .init_legacy = intel_init_bsd_ring_buffer, 64 }, 65 [VCS2] = { 66 .name = "bsd2 ring", 67 .exec_id = I915_EXEC_BSD, 68 .guc_id = GUC_VIDEO_ENGINE2, 69 .mmio_base = GEN8_BSD2_RING_BASE, 70 .irq_shift = GEN8_VCS2_IRQ_SHIFT, 71 .init_execlists = logical_xcs_ring_init, 72 .init_legacy = intel_init_bsd2_ring_buffer, 73 }, 74 [VECS] = { 75 .name = "video enhancement ring", 76 .exec_id = I915_EXEC_VEBOX, 77 .guc_id = GUC_VIDEOENHANCE_ENGINE, 78 .mmio_base = VEBOX_RING_BASE, 79 .irq_shift = GEN8_VECS_IRQ_SHIFT, 80 .init_execlists = logical_xcs_ring_init, 81 .init_legacy = intel_init_vebox_ring_buffer, 82 }, 83 }; 84 85 static struct intel_engine_cs * 86 intel_engine_setup(struct drm_i915_private *dev_priv, 87 enum intel_engine_id id) 88 { 89 const struct engine_info *info = &intel_engines[id]; 90 struct intel_engine_cs *engine = &dev_priv->engine[id]; 91 92 engine->id = id; 93 engine->i915 = dev_priv; 94 engine->name = info->name; 95 engine->exec_id = info->exec_id; 96 engine->hw_id = engine->guc_id = info->guc_id; 97 engine->mmio_base = info->mmio_base; 98 engine->irq_shift = info->irq_shift; 99 100 return engine; 101 } 102 103 /** 104 * intel_engines_init() - allocate, populate and init the Engine Command Streamers 105 * @dev: DRM device. 106 * 107 * Return: non-zero if the initialization failed. 108 */ 109 int intel_engines_init(struct drm_device *dev) 110 { 111 struct drm_i915_private *dev_priv = to_i915(dev); 112 unsigned int mask = 0; 113 int (*init)(struct intel_engine_cs *engine); 114 unsigned int i; 115 int ret; 116 117 WARN_ON(INTEL_INFO(dev_priv)->ring_mask & 118 GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES)); 119 120 for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { 121 if (!HAS_ENGINE(dev_priv, i)) 122 continue; 123 124 if (i915.enable_execlists) 125 init = intel_engines[i].init_execlists; 126 else 127 init = intel_engines[i].init_legacy; 128 129 if (!init) 130 continue; 131 132 ret = init(intel_engine_setup(dev_priv, i)); 133 if (ret) 134 goto cleanup; 135 136 mask |= ENGINE_MASK(i); 137 } 138 139 /* 140 * Catch failures to update intel_engines table when the new engines 141 * are added to the driver by a warning and disabling the forgotten 142 * engines. 143 */ 144 if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask)) { 145 struct intel_device_info *info = 146 (struct intel_device_info *)&dev_priv->info; 147 info->ring_mask = mask; 148 } 149 150 return 0; 151 152 cleanup: 153 for (i = 0; i < I915_NUM_ENGINES; i++) { 154 if (i915.enable_execlists) 155 intel_logical_ring_cleanup(&dev_priv->engine[i]); 156 else 157 intel_cleanup_engine(&dev_priv->engine[i]); 158 } 159 160 return ret; 161 } 162 163 void intel_engine_init_hangcheck(struct intel_engine_cs *engine) 164 { 165 memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); 166 } 167 168 /** 169 * intel_engines_setup_common - setup engine state not requiring hw access 170 * @engine: Engine to setup. 171 * 172 * Initializes @engine@ structure members shared between legacy and execlists 173 * submission modes which do not require hardware access. 174 * 175 * Typically done early in the submission mode specific engine setup stage. 176 */ 177 void intel_engine_setup_common(struct intel_engine_cs *engine) 178 { 179 INIT_LIST_HEAD(&engine->active_list); 180 INIT_LIST_HEAD(&engine->request_list); 181 INIT_LIST_HEAD(&engine->buffers); 182 INIT_LIST_HEAD(&engine->execlist_queue); 183 lockinit(&engine->execlist_lock, "i915el", 0, LK_CANRECURSE); 184 185 engine->fence_context = fence_context_alloc(1); 186 187 intel_engine_init_hangcheck(engine); 188 i915_gem_batch_pool_init(&engine->i915->drm, &engine->batch_pool); 189 } 190 191 /** 192 * intel_engines_init_common - initialize cengine state which might require hw access 193 * @engine: Engine to initialize. 194 * 195 * Initializes @engine@ structure members shared between legacy and execlists 196 * submission modes which do require hardware access. 197 * 198 * Typcally done at later stages of submission mode specific engine setup. 199 * 200 * Returns zero on success or an error code on failure. 201 */ 202 int intel_engine_init_common(struct intel_engine_cs *engine) 203 { 204 int ret; 205 206 ret = intel_engine_init_breadcrumbs(engine); 207 if (ret) 208 return ret; 209 210 return i915_cmd_parser_init_ring(engine); 211 } 212