187df8fc6SFrançois Tigeot /* 287df8fc6SFrançois Tigeot * Copyright © 2016 Intel Corporation 387df8fc6SFrançois Tigeot * 487df8fc6SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 587df8fc6SFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 687df8fc6SFrançois Tigeot * to deal in the Software without restriction, including without limitation 787df8fc6SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 887df8fc6SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 987df8fc6SFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 1087df8fc6SFrançois Tigeot * 1187df8fc6SFrançois Tigeot * The above copyright notice and this permission notice (including the next 1287df8fc6SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 1387df8fc6SFrançois Tigeot * Software. 1487df8fc6SFrançois Tigeot * 1587df8fc6SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1687df8fc6SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1787df8fc6SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1887df8fc6SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1987df8fc6SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2087df8fc6SFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2187df8fc6SFrançois Tigeot * IN THE SOFTWARE. 2287df8fc6SFrançois Tigeot * 2387df8fc6SFrançois Tigeot */ 2487df8fc6SFrançois Tigeot 2587df8fc6SFrançois Tigeot #include "i915_drv.h" 2687df8fc6SFrançois Tigeot #include "intel_ringbuffer.h" 2787df8fc6SFrançois Tigeot #include "intel_lrc.h" 2887df8fc6SFrançois Tigeot 2987df8fc6SFrançois Tigeot static const struct engine_info { 3087df8fc6SFrançois Tigeot const char *name; 3187df8fc6SFrançois Tigeot unsigned exec_id; 32*1e12ee3bSFrançois Tigeot enum intel_engine_hw_id hw_id; 3387df8fc6SFrançois Tigeot u32 mmio_base; 3487df8fc6SFrançois Tigeot unsigned irq_shift; 3587df8fc6SFrançois Tigeot int (*init_legacy)(struct intel_engine_cs *engine); 3687df8fc6SFrançois Tigeot int (*init_execlists)(struct intel_engine_cs *engine); 3787df8fc6SFrançois Tigeot } intel_engines[] = { 3887df8fc6SFrançois Tigeot [RCS] = { 3987df8fc6SFrançois Tigeot .name = "render ring", 4087df8fc6SFrançois Tigeot .exec_id = I915_EXEC_RENDER, 41*1e12ee3bSFrançois Tigeot .hw_id = RCS_HW, 4287df8fc6SFrançois Tigeot .mmio_base = RENDER_RING_BASE, 4387df8fc6SFrançois Tigeot .irq_shift = GEN8_RCS_IRQ_SHIFT, 4487df8fc6SFrançois Tigeot .init_execlists = logical_render_ring_init, 4587df8fc6SFrançois Tigeot .init_legacy = intel_init_render_ring_buffer, 4687df8fc6SFrançois Tigeot }, 4787df8fc6SFrançois Tigeot [BCS] = { 4887df8fc6SFrançois Tigeot .name = "blitter ring", 4987df8fc6SFrançois Tigeot .exec_id = I915_EXEC_BLT, 50*1e12ee3bSFrançois Tigeot .hw_id = BCS_HW, 5187df8fc6SFrançois Tigeot .mmio_base = BLT_RING_BASE, 5287df8fc6SFrançois Tigeot .irq_shift = GEN8_BCS_IRQ_SHIFT, 5387df8fc6SFrançois Tigeot .init_execlists = logical_xcs_ring_init, 5487df8fc6SFrançois Tigeot .init_legacy = intel_init_blt_ring_buffer, 5587df8fc6SFrançois Tigeot }, 5687df8fc6SFrançois Tigeot [VCS] = { 5787df8fc6SFrançois Tigeot .name = "bsd ring", 5887df8fc6SFrançois Tigeot .exec_id = I915_EXEC_BSD, 59*1e12ee3bSFrançois Tigeot .hw_id = VCS_HW, 6087df8fc6SFrançois Tigeot .mmio_base = GEN6_BSD_RING_BASE, 6187df8fc6SFrançois Tigeot .irq_shift = GEN8_VCS1_IRQ_SHIFT, 6287df8fc6SFrançois Tigeot .init_execlists = logical_xcs_ring_init, 6387df8fc6SFrançois Tigeot .init_legacy = intel_init_bsd_ring_buffer, 6487df8fc6SFrançois Tigeot }, 6587df8fc6SFrançois Tigeot [VCS2] = { 6687df8fc6SFrançois Tigeot .name = "bsd2 ring", 6787df8fc6SFrançois Tigeot .exec_id = I915_EXEC_BSD, 68*1e12ee3bSFrançois Tigeot .hw_id = VCS2_HW, 6987df8fc6SFrançois Tigeot .mmio_base = GEN8_BSD2_RING_BASE, 7087df8fc6SFrançois Tigeot .irq_shift = GEN8_VCS2_IRQ_SHIFT, 7187df8fc6SFrançois Tigeot .init_execlists = logical_xcs_ring_init, 7287df8fc6SFrançois Tigeot .init_legacy = intel_init_bsd2_ring_buffer, 7387df8fc6SFrançois Tigeot }, 7487df8fc6SFrançois Tigeot [VECS] = { 7587df8fc6SFrançois Tigeot .name = "video enhancement ring", 7687df8fc6SFrançois Tigeot .exec_id = I915_EXEC_VEBOX, 77*1e12ee3bSFrançois Tigeot .hw_id = VECS_HW, 7887df8fc6SFrançois Tigeot .mmio_base = VEBOX_RING_BASE, 7987df8fc6SFrançois Tigeot .irq_shift = GEN8_VECS_IRQ_SHIFT, 8087df8fc6SFrançois Tigeot .init_execlists = logical_xcs_ring_init, 8187df8fc6SFrançois Tigeot .init_legacy = intel_init_vebox_ring_buffer, 8287df8fc6SFrançois Tigeot }, 8387df8fc6SFrançois Tigeot }; 8487df8fc6SFrançois Tigeot 85*1e12ee3bSFrançois Tigeot static int 8687df8fc6SFrançois Tigeot intel_engine_setup(struct drm_i915_private *dev_priv, 8787df8fc6SFrançois Tigeot enum intel_engine_id id) 8887df8fc6SFrançois Tigeot { 8987df8fc6SFrançois Tigeot const struct engine_info *info = &intel_engines[id]; 90*1e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 91*1e12ee3bSFrançois Tigeot 92*1e12ee3bSFrançois Tigeot GEM_BUG_ON(dev_priv->engine[id]); 93*1e12ee3bSFrançois Tigeot engine = kzalloc(sizeof(*engine), GFP_KERNEL); 94*1e12ee3bSFrançois Tigeot if (!engine) 95*1e12ee3bSFrançois Tigeot return -ENOMEM; 9687df8fc6SFrançois Tigeot 9787df8fc6SFrançois Tigeot engine->id = id; 9887df8fc6SFrançois Tigeot engine->i915 = dev_priv; 9987df8fc6SFrançois Tigeot engine->name = info->name; 10087df8fc6SFrançois Tigeot engine->exec_id = info->exec_id; 101*1e12ee3bSFrançois Tigeot engine->hw_id = engine->guc_id = info->hw_id; 10287df8fc6SFrançois Tigeot engine->mmio_base = info->mmio_base; 10387df8fc6SFrançois Tigeot engine->irq_shift = info->irq_shift; 10487df8fc6SFrançois Tigeot 105*1e12ee3bSFrançois Tigeot dev_priv->engine[id] = engine; 106*1e12ee3bSFrançois Tigeot return 0; 10787df8fc6SFrançois Tigeot } 10887df8fc6SFrançois Tigeot 10987df8fc6SFrançois Tigeot /** 11087df8fc6SFrançois Tigeot * intel_engines_init() - allocate, populate and init the Engine Command Streamers 11187df8fc6SFrançois Tigeot * @dev: DRM device. 11287df8fc6SFrançois Tigeot * 11387df8fc6SFrançois Tigeot * Return: non-zero if the initialization failed. 11487df8fc6SFrançois Tigeot */ 11587df8fc6SFrançois Tigeot int intel_engines_init(struct drm_device *dev) 11687df8fc6SFrançois Tigeot { 11787df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 118*1e12ee3bSFrançois Tigeot struct intel_device_info *device_info = mkwrite_device_info(dev_priv); 119*1e12ee3bSFrançois Tigeot unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask; 12087df8fc6SFrançois Tigeot unsigned int mask = 0; 12187df8fc6SFrançois Tigeot int (*init)(struct intel_engine_cs *engine); 122*1e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 123*1e12ee3bSFrançois Tigeot enum intel_engine_id id; 12487df8fc6SFrançois Tigeot unsigned int i; 12587df8fc6SFrançois Tigeot int ret; 12687df8fc6SFrançois Tigeot 127*1e12ee3bSFrançois Tigeot WARN_ON(ring_mask == 0); 128*1e12ee3bSFrançois Tigeot WARN_ON(ring_mask & 12987df8fc6SFrançois Tigeot GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES)); 13087df8fc6SFrançois Tigeot 13187df8fc6SFrançois Tigeot for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { 13287df8fc6SFrançois Tigeot if (!HAS_ENGINE(dev_priv, i)) 13387df8fc6SFrançois Tigeot continue; 13487df8fc6SFrançois Tigeot 13587df8fc6SFrançois Tigeot if (i915.enable_execlists) 13687df8fc6SFrançois Tigeot init = intel_engines[i].init_execlists; 13787df8fc6SFrançois Tigeot else 13887df8fc6SFrançois Tigeot init = intel_engines[i].init_legacy; 13987df8fc6SFrançois Tigeot 14087df8fc6SFrançois Tigeot if (!init) 14187df8fc6SFrançois Tigeot continue; 14287df8fc6SFrançois Tigeot 143*1e12ee3bSFrançois Tigeot ret = intel_engine_setup(dev_priv, i); 144*1e12ee3bSFrançois Tigeot if (ret) 145*1e12ee3bSFrançois Tigeot goto cleanup; 146*1e12ee3bSFrançois Tigeot 147*1e12ee3bSFrançois Tigeot ret = init(dev_priv->engine[i]); 14887df8fc6SFrançois Tigeot if (ret) 14987df8fc6SFrançois Tigeot goto cleanup; 15087df8fc6SFrançois Tigeot 15187df8fc6SFrançois Tigeot mask |= ENGINE_MASK(i); 15287df8fc6SFrançois Tigeot } 15387df8fc6SFrançois Tigeot 15487df8fc6SFrançois Tigeot /* 15587df8fc6SFrançois Tigeot * Catch failures to update intel_engines table when the new engines 15687df8fc6SFrançois Tigeot * are added to the driver by a warning and disabling the forgotten 15787df8fc6SFrançois Tigeot * engines. 15887df8fc6SFrançois Tigeot */ 159*1e12ee3bSFrançois Tigeot if (WARN_ON(mask != ring_mask)) 160*1e12ee3bSFrançois Tigeot device_info->ring_mask = mask; 161*1e12ee3bSFrançois Tigeot 162*1e12ee3bSFrançois Tigeot device_info->num_rings = hweight32(mask); 16387df8fc6SFrançois Tigeot 16487df8fc6SFrançois Tigeot return 0; 16587df8fc6SFrançois Tigeot 16687df8fc6SFrançois Tigeot cleanup: 167*1e12ee3bSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 16887df8fc6SFrançois Tigeot if (i915.enable_execlists) 169*1e12ee3bSFrançois Tigeot intel_logical_ring_cleanup(engine); 17087df8fc6SFrançois Tigeot else 171*1e12ee3bSFrançois Tigeot intel_engine_cleanup(engine); 17287df8fc6SFrançois Tigeot } 17387df8fc6SFrançois Tigeot 17487df8fc6SFrançois Tigeot return ret; 17587df8fc6SFrançois Tigeot } 17687df8fc6SFrançois Tigeot 177*1e12ee3bSFrançois Tigeot void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) 178*1e12ee3bSFrançois Tigeot { 179*1e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 180*1e12ee3bSFrançois Tigeot 181*1e12ee3bSFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 182*1e12ee3bSFrançois Tigeot * so long as the semaphore value in the register/page is greater 183*1e12ee3bSFrançois Tigeot * than the sync value), so whenever we reset the seqno, 184*1e12ee3bSFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 185*1e12ee3bSFrançois Tigeot * always be before the next request's seqno. If we don't reset 186*1e12ee3bSFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 187*1e12ee3bSFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 188*1e12ee3bSFrançois Tigeot */ 189*1e12ee3bSFrançois Tigeot if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { 190*1e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 191*1e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 192*1e12ee3bSFrançois Tigeot if (HAS_VEBOX(dev_priv)) 193*1e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 194*1e12ee3bSFrançois Tigeot } 195*1e12ee3bSFrançois Tigeot if (dev_priv->semaphore) { 196*1e12ee3bSFrançois Tigeot struct page *page = i915_vma_first_page(dev_priv->semaphore); 197*1e12ee3bSFrançois Tigeot void *semaphores; 198*1e12ee3bSFrançois Tigeot 199*1e12ee3bSFrançois Tigeot /* Semaphores are in noncoherent memory, flush to be safe */ 200*1e12ee3bSFrançois Tigeot semaphores = kmap(page); 201*1e12ee3bSFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 202*1e12ee3bSFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 203*1e12ee3bSFrançois Tigeot drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 204*1e12ee3bSFrançois Tigeot I915_NUM_ENGINES * gen8_semaphore_seqno_size); 205*1e12ee3bSFrançois Tigeot kunmap(page); 206*1e12ee3bSFrançois Tigeot } 207*1e12ee3bSFrançois Tigeot memset(engine->semaphore.sync_seqno, 0, 208*1e12ee3bSFrançois Tigeot sizeof(engine->semaphore.sync_seqno)); 209*1e12ee3bSFrançois Tigeot 210*1e12ee3bSFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 211*1e12ee3bSFrançois Tigeot if (engine->irq_seqno_barrier) 212*1e12ee3bSFrançois Tigeot engine->irq_seqno_barrier(engine); 213*1e12ee3bSFrançois Tigeot engine->last_submitted_seqno = seqno; 214*1e12ee3bSFrançois Tigeot 215*1e12ee3bSFrançois Tigeot engine->hangcheck.seqno = seqno; 216*1e12ee3bSFrançois Tigeot 217*1e12ee3bSFrançois Tigeot /* After manually advancing the seqno, fake the interrupt in case 218*1e12ee3bSFrançois Tigeot * there are any waiters for that seqno. 219*1e12ee3bSFrançois Tigeot */ 220*1e12ee3bSFrançois Tigeot intel_engine_wakeup(engine); 221*1e12ee3bSFrançois Tigeot } 222*1e12ee3bSFrançois Tigeot 22387df8fc6SFrançois Tigeot void intel_engine_init_hangcheck(struct intel_engine_cs *engine) 22487df8fc6SFrançois Tigeot { 22587df8fc6SFrançois Tigeot memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); 22687df8fc6SFrançois Tigeot } 22787df8fc6SFrançois Tigeot 22871f41f3eSFrançois Tigeot static void intel_engine_init_requests(struct intel_engine_cs *engine) 22971f41f3eSFrançois Tigeot { 23071f41f3eSFrançois Tigeot init_request_active(&engine->last_request, NULL); 23171f41f3eSFrançois Tigeot INIT_LIST_HEAD(&engine->request_list); 23271f41f3eSFrançois Tigeot } 23371f41f3eSFrançois Tigeot 23487df8fc6SFrançois Tigeot /** 23587df8fc6SFrançois Tigeot * intel_engines_setup_common - setup engine state not requiring hw access 23687df8fc6SFrançois Tigeot * @engine: Engine to setup. 23787df8fc6SFrançois Tigeot * 23887df8fc6SFrançois Tigeot * Initializes @engine@ structure members shared between legacy and execlists 23987df8fc6SFrançois Tigeot * submission modes which do not require hardware access. 24087df8fc6SFrançois Tigeot * 24187df8fc6SFrançois Tigeot * Typically done early in the submission mode specific engine setup stage. 24287df8fc6SFrançois Tigeot */ 24387df8fc6SFrançois Tigeot void intel_engine_setup_common(struct intel_engine_cs *engine) 24487df8fc6SFrançois Tigeot { 24587df8fc6SFrançois Tigeot INIT_LIST_HEAD(&engine->execlist_queue); 246*1e12ee3bSFrançois Tigeot lockinit(&engine->execlist_lock, "i915el", 0, 0); 24787df8fc6SFrançois Tigeot 24887df8fc6SFrançois Tigeot engine->fence_context = fence_context_alloc(1); 24987df8fc6SFrançois Tigeot 25071f41f3eSFrançois Tigeot intel_engine_init_requests(engine); 25187df8fc6SFrançois Tigeot intel_engine_init_hangcheck(engine); 25271f41f3eSFrançois Tigeot i915_gem_batch_pool_init(engine, &engine->batch_pool); 253*1e12ee3bSFrançois Tigeot 254*1e12ee3bSFrançois Tigeot intel_engine_init_cmd_parser(engine); 255*1e12ee3bSFrançois Tigeot } 256*1e12ee3bSFrançois Tigeot 257*1e12ee3bSFrançois Tigeot int intel_engine_create_scratch(struct intel_engine_cs *engine, int size) 258*1e12ee3bSFrançois Tigeot { 259*1e12ee3bSFrançois Tigeot struct drm_i915_gem_object *obj; 260*1e12ee3bSFrançois Tigeot struct i915_vma *vma; 261*1e12ee3bSFrançois Tigeot int ret; 262*1e12ee3bSFrançois Tigeot 263*1e12ee3bSFrançois Tigeot WARN_ON(engine->scratch); 264*1e12ee3bSFrançois Tigeot 265*1e12ee3bSFrançois Tigeot obj = i915_gem_object_create_stolen(&engine->i915->drm, size); 266*1e12ee3bSFrançois Tigeot if (!obj) 267*1e12ee3bSFrançois Tigeot obj = i915_gem_object_create(&engine->i915->drm, size); 268*1e12ee3bSFrançois Tigeot if (IS_ERR(obj)) { 269*1e12ee3bSFrançois Tigeot DRM_ERROR("Failed to allocate scratch page\n"); 270*1e12ee3bSFrançois Tigeot return PTR_ERR(obj); 271*1e12ee3bSFrançois Tigeot } 272*1e12ee3bSFrançois Tigeot 273*1e12ee3bSFrançois Tigeot vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL); 274*1e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 275*1e12ee3bSFrançois Tigeot ret = PTR_ERR(vma); 276*1e12ee3bSFrançois Tigeot goto err_unref; 277*1e12ee3bSFrançois Tigeot } 278*1e12ee3bSFrançois Tigeot 279*1e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 4096, PIN_GLOBAL | PIN_HIGH); 280*1e12ee3bSFrançois Tigeot if (ret) 281*1e12ee3bSFrançois Tigeot goto err_unref; 282*1e12ee3bSFrançois Tigeot 283*1e12ee3bSFrançois Tigeot engine->scratch = vma; 284*1e12ee3bSFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 285*1e12ee3bSFrançois Tigeot engine->name, i915_ggtt_offset(vma)); 286*1e12ee3bSFrançois Tigeot return 0; 287*1e12ee3bSFrançois Tigeot 288*1e12ee3bSFrançois Tigeot err_unref: 289*1e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 290*1e12ee3bSFrançois Tigeot return ret; 291*1e12ee3bSFrançois Tigeot } 292*1e12ee3bSFrançois Tigeot 293*1e12ee3bSFrançois Tigeot static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine) 294*1e12ee3bSFrançois Tigeot { 295*1e12ee3bSFrançois Tigeot i915_vma_unpin_and_release(&engine->scratch); 29687df8fc6SFrançois Tigeot } 29787df8fc6SFrançois Tigeot 29887df8fc6SFrançois Tigeot /** 29987df8fc6SFrançois Tigeot * intel_engines_init_common - initialize cengine state which might require hw access 30087df8fc6SFrançois Tigeot * @engine: Engine to initialize. 30187df8fc6SFrançois Tigeot * 30287df8fc6SFrançois Tigeot * Initializes @engine@ structure members shared between legacy and execlists 30387df8fc6SFrançois Tigeot * submission modes which do require hardware access. 30487df8fc6SFrançois Tigeot * 30587df8fc6SFrançois Tigeot * Typcally done at later stages of submission mode specific engine setup. 30687df8fc6SFrançois Tigeot * 30787df8fc6SFrançois Tigeot * Returns zero on success or an error code on failure. 30887df8fc6SFrançois Tigeot */ 30987df8fc6SFrançois Tigeot int intel_engine_init_common(struct intel_engine_cs *engine) 31087df8fc6SFrançois Tigeot { 31187df8fc6SFrançois Tigeot int ret; 31287df8fc6SFrançois Tigeot 31387df8fc6SFrançois Tigeot ret = intel_engine_init_breadcrumbs(engine); 31487df8fc6SFrançois Tigeot if (ret) 31587df8fc6SFrançois Tigeot return ret; 31687df8fc6SFrançois Tigeot 317*1e12ee3bSFrançois Tigeot return 0; 31871f41f3eSFrançois Tigeot } 31971f41f3eSFrançois Tigeot 32071f41f3eSFrançois Tigeot /** 32171f41f3eSFrançois Tigeot * intel_engines_cleanup_common - cleans up the engine state created by 32271f41f3eSFrançois Tigeot * the common initiailizers. 32371f41f3eSFrançois Tigeot * @engine: Engine to cleanup. 32471f41f3eSFrançois Tigeot * 32571f41f3eSFrançois Tigeot * This cleans up everything created by the common helpers. 32671f41f3eSFrançois Tigeot */ 32771f41f3eSFrançois Tigeot void intel_engine_cleanup_common(struct intel_engine_cs *engine) 32871f41f3eSFrançois Tigeot { 329*1e12ee3bSFrançois Tigeot intel_engine_cleanup_scratch(engine); 330*1e12ee3bSFrançois Tigeot 33171f41f3eSFrançois Tigeot intel_engine_fini_breadcrumbs(engine); 332*1e12ee3bSFrançois Tigeot intel_engine_cleanup_cmd_parser(engine); 33371f41f3eSFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 33487df8fc6SFrançois Tigeot } 335*1e12ee3bSFrançois Tigeot 336*1e12ee3bSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine) 337*1e12ee3bSFrançois Tigeot { 338*1e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 339*1e12ee3bSFrançois Tigeot u64 acthd; 340*1e12ee3bSFrançois Tigeot 341*1e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 342*1e12ee3bSFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 343*1e12ee3bSFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 344*1e12ee3bSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 345*1e12ee3bSFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 346*1e12ee3bSFrançois Tigeot else 347*1e12ee3bSFrançois Tigeot acthd = I915_READ(ACTHD); 348*1e12ee3bSFrançois Tigeot 349*1e12ee3bSFrançois Tigeot return acthd; 350*1e12ee3bSFrançois Tigeot } 351*1e12ee3bSFrançois Tigeot 352*1e12ee3bSFrançois Tigeot u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) 353*1e12ee3bSFrançois Tigeot { 354*1e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 355*1e12ee3bSFrançois Tigeot u64 bbaddr; 356*1e12ee3bSFrançois Tigeot 357*1e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 358*1e12ee3bSFrançois Tigeot bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base), 359*1e12ee3bSFrançois Tigeot RING_BBADDR_UDW(engine->mmio_base)); 360*1e12ee3bSFrançois Tigeot else 361*1e12ee3bSFrançois Tigeot bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); 362*1e12ee3bSFrançois Tigeot 363*1e12ee3bSFrançois Tigeot return bbaddr; 364*1e12ee3bSFrançois Tigeot } 365*1e12ee3bSFrançois Tigeot 366*1e12ee3bSFrançois Tigeot const char *i915_cache_level_str(struct drm_i915_private *i915, int type) 367*1e12ee3bSFrançois Tigeot { 368*1e12ee3bSFrançois Tigeot switch (type) { 369*1e12ee3bSFrançois Tigeot case I915_CACHE_NONE: return " uncached"; 370*1e12ee3bSFrançois Tigeot case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; 371*1e12ee3bSFrançois Tigeot case I915_CACHE_L3_LLC: return " L3+LLC"; 372*1e12ee3bSFrançois Tigeot case I915_CACHE_WT: return " WT"; 373*1e12ee3bSFrançois Tigeot default: return ""; 374*1e12ee3bSFrançois Tigeot } 375*1e12ee3bSFrançois Tigeot } 376*1e12ee3bSFrançois Tigeot 377*1e12ee3bSFrançois Tigeot static inline uint32_t 378*1e12ee3bSFrançois Tigeot read_subslice_reg(struct drm_i915_private *dev_priv, int slice, 379*1e12ee3bSFrançois Tigeot int subslice, i915_reg_t reg) 380*1e12ee3bSFrançois Tigeot { 381*1e12ee3bSFrançois Tigeot uint32_t mcr; 382*1e12ee3bSFrançois Tigeot uint32_t ret; 383*1e12ee3bSFrançois Tigeot enum forcewake_domains fw_domains; 384*1e12ee3bSFrançois Tigeot 385*1e12ee3bSFrançois Tigeot fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, 386*1e12ee3bSFrançois Tigeot FW_REG_READ); 387*1e12ee3bSFrançois Tigeot fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, 388*1e12ee3bSFrançois Tigeot GEN8_MCR_SELECTOR, 389*1e12ee3bSFrançois Tigeot FW_REG_READ | FW_REG_WRITE); 390*1e12ee3bSFrançois Tigeot 391*1e12ee3bSFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 392*1e12ee3bSFrançois Tigeot intel_uncore_forcewake_get__locked(dev_priv, fw_domains); 393*1e12ee3bSFrançois Tigeot 394*1e12ee3bSFrançois Tigeot mcr = I915_READ_FW(GEN8_MCR_SELECTOR); 395*1e12ee3bSFrançois Tigeot /* 396*1e12ee3bSFrançois Tigeot * The HW expects the slice and sublice selectors to be reset to 0 397*1e12ee3bSFrançois Tigeot * after reading out the registers. 398*1e12ee3bSFrançois Tigeot */ 399*1e12ee3bSFrançois Tigeot WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); 400*1e12ee3bSFrançois Tigeot mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); 401*1e12ee3bSFrançois Tigeot mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); 402*1e12ee3bSFrançois Tigeot I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); 403*1e12ee3bSFrançois Tigeot 404*1e12ee3bSFrançois Tigeot ret = I915_READ_FW(reg); 405*1e12ee3bSFrançois Tigeot 406*1e12ee3bSFrançois Tigeot mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); 407*1e12ee3bSFrançois Tigeot I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); 408*1e12ee3bSFrançois Tigeot 409*1e12ee3bSFrançois Tigeot intel_uncore_forcewake_put__locked(dev_priv, fw_domains); 410*1e12ee3bSFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 411*1e12ee3bSFrançois Tigeot 412*1e12ee3bSFrançois Tigeot return ret; 413*1e12ee3bSFrançois Tigeot } 414*1e12ee3bSFrançois Tigeot 415*1e12ee3bSFrançois Tigeot /* NB: please notice the memset */ 416*1e12ee3bSFrançois Tigeot void intel_engine_get_instdone(struct intel_engine_cs *engine, 417*1e12ee3bSFrançois Tigeot struct intel_instdone *instdone) 418*1e12ee3bSFrançois Tigeot { 419*1e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 420*1e12ee3bSFrançois Tigeot u32 mmio_base = engine->mmio_base; 421*1e12ee3bSFrançois Tigeot int slice; 422*1e12ee3bSFrançois Tigeot int subslice; 423*1e12ee3bSFrançois Tigeot 424*1e12ee3bSFrançois Tigeot memset(instdone, 0, sizeof(*instdone)); 425*1e12ee3bSFrançois Tigeot 426*1e12ee3bSFrançois Tigeot switch (INTEL_GEN(dev_priv)) { 427*1e12ee3bSFrançois Tigeot default: 428*1e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 429*1e12ee3bSFrançois Tigeot 430*1e12ee3bSFrançois Tigeot if (engine->id != RCS) 431*1e12ee3bSFrançois Tigeot break; 432*1e12ee3bSFrançois Tigeot 433*1e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); 434*1e12ee3bSFrançois Tigeot for_each_instdone_slice_subslice(dev_priv, slice, subslice) { 435*1e12ee3bSFrançois Tigeot instdone->sampler[slice][subslice] = 436*1e12ee3bSFrançois Tigeot read_subslice_reg(dev_priv, slice, subslice, 437*1e12ee3bSFrançois Tigeot GEN7_SAMPLER_INSTDONE); 438*1e12ee3bSFrançois Tigeot instdone->row[slice][subslice] = 439*1e12ee3bSFrançois Tigeot read_subslice_reg(dev_priv, slice, subslice, 440*1e12ee3bSFrançois Tigeot GEN7_ROW_INSTDONE); 441*1e12ee3bSFrançois Tigeot } 442*1e12ee3bSFrançois Tigeot break; 443*1e12ee3bSFrançois Tigeot case 7: 444*1e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 445*1e12ee3bSFrançois Tigeot 446*1e12ee3bSFrançois Tigeot if (engine->id != RCS) 447*1e12ee3bSFrançois Tigeot break; 448*1e12ee3bSFrançois Tigeot 449*1e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); 450*1e12ee3bSFrançois Tigeot instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); 451*1e12ee3bSFrançois Tigeot instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); 452*1e12ee3bSFrançois Tigeot 453*1e12ee3bSFrançois Tigeot break; 454*1e12ee3bSFrançois Tigeot case 6: 455*1e12ee3bSFrançois Tigeot case 5: 456*1e12ee3bSFrançois Tigeot case 4: 457*1e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 458*1e12ee3bSFrançois Tigeot 459*1e12ee3bSFrançois Tigeot if (engine->id == RCS) 460*1e12ee3bSFrançois Tigeot /* HACK: Using the wrong struct member */ 461*1e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN4_INSTDONE1); 462*1e12ee3bSFrançois Tigeot break; 463*1e12ee3bSFrançois Tigeot case 3: 464*1e12ee3bSFrançois Tigeot case 2: 465*1e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(GEN2_INSTDONE); 466*1e12ee3bSFrançois Tigeot break; 467*1e12ee3bSFrançois Tigeot } 468*1e12ee3bSFrançois Tigeot } 469