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; 321e12ee3bSFranç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, 411e12ee3bSFranç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, 501e12ee3bSFranç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, 591e12ee3bSFranç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, 681e12ee3bSFranç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, 771e12ee3bSFranç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 851e12ee3bSFranç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]; 901e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 911e12ee3bSFrançois Tigeot 921e12ee3bSFrançois Tigeot GEM_BUG_ON(dev_priv->engine[id]); 931e12ee3bSFrançois Tigeot engine = kzalloc(sizeof(*engine), GFP_KERNEL); 941e12ee3bSFrançois Tigeot if (!engine) 951e12ee3bSFranç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; 1011e12ee3bSFranç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*4be47400SFrançois Tigeot /* Nothing to do here, execute in order of dependencies */ 106*4be47400SFrançois Tigeot engine->schedule = NULL; 107*4be47400SFrançois Tigeot 1081e12ee3bSFrançois Tigeot dev_priv->engine[id] = engine; 1091e12ee3bSFrançois Tigeot return 0; 11087df8fc6SFrançois Tigeot } 11187df8fc6SFrançois Tigeot 11287df8fc6SFrançois Tigeot /** 11387df8fc6SFrançois Tigeot * intel_engines_init() - allocate, populate and init the Engine Command Streamers 11487df8fc6SFrançois Tigeot * @dev: DRM device. 11587df8fc6SFrançois Tigeot * 11687df8fc6SFrançois Tigeot * Return: non-zero if the initialization failed. 11787df8fc6SFrançois Tigeot */ 11887df8fc6SFrançois Tigeot int intel_engines_init(struct drm_device *dev) 11987df8fc6SFrançois Tigeot { 12087df8fc6SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 1211e12ee3bSFrançois Tigeot struct intel_device_info *device_info = mkwrite_device_info(dev_priv); 1221e12ee3bSFrançois Tigeot unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask; 12387df8fc6SFrançois Tigeot unsigned int mask = 0; 12487df8fc6SFrançois Tigeot int (*init)(struct intel_engine_cs *engine); 1251e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 1261e12ee3bSFrançois Tigeot enum intel_engine_id id; 12787df8fc6SFrançois Tigeot unsigned int i; 12887df8fc6SFrançois Tigeot int ret; 12987df8fc6SFrançois Tigeot 1301e12ee3bSFrançois Tigeot WARN_ON(ring_mask == 0); 1311e12ee3bSFrançois Tigeot WARN_ON(ring_mask & 13287df8fc6SFrançois Tigeot GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES)); 13387df8fc6SFrançois Tigeot 13487df8fc6SFrançois Tigeot for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { 13587df8fc6SFrançois Tigeot if (!HAS_ENGINE(dev_priv, i)) 13687df8fc6SFrançois Tigeot continue; 13787df8fc6SFrançois Tigeot 13887df8fc6SFrançois Tigeot if (i915.enable_execlists) 13987df8fc6SFrançois Tigeot init = intel_engines[i].init_execlists; 14087df8fc6SFrançois Tigeot else 14187df8fc6SFrançois Tigeot init = intel_engines[i].init_legacy; 14287df8fc6SFrançois Tigeot 14387df8fc6SFrançois Tigeot if (!init) 14487df8fc6SFrançois Tigeot continue; 14587df8fc6SFrançois Tigeot 1461e12ee3bSFrançois Tigeot ret = intel_engine_setup(dev_priv, i); 1471e12ee3bSFrançois Tigeot if (ret) 1481e12ee3bSFrançois Tigeot goto cleanup; 1491e12ee3bSFrançois Tigeot 1501e12ee3bSFrançois Tigeot ret = init(dev_priv->engine[i]); 15187df8fc6SFrançois Tigeot if (ret) 15287df8fc6SFrançois Tigeot goto cleanup; 15387df8fc6SFrançois Tigeot 15487df8fc6SFrançois Tigeot mask |= ENGINE_MASK(i); 15587df8fc6SFrançois Tigeot } 15687df8fc6SFrançois Tigeot 15787df8fc6SFrançois Tigeot /* 15887df8fc6SFrançois Tigeot * Catch failures to update intel_engines table when the new engines 15987df8fc6SFrançois Tigeot * are added to the driver by a warning and disabling the forgotten 16087df8fc6SFrançois Tigeot * engines. 16187df8fc6SFrançois Tigeot */ 1621e12ee3bSFrançois Tigeot if (WARN_ON(mask != ring_mask)) 1631e12ee3bSFrançois Tigeot device_info->ring_mask = mask; 1641e12ee3bSFrançois Tigeot 1651e12ee3bSFrançois Tigeot device_info->num_rings = hweight32(mask); 16687df8fc6SFrançois Tigeot 16787df8fc6SFrançois Tigeot return 0; 16887df8fc6SFrançois Tigeot 16987df8fc6SFrançois Tigeot cleanup: 1701e12ee3bSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 17187df8fc6SFrançois Tigeot if (i915.enable_execlists) 1721e12ee3bSFrançois Tigeot intel_logical_ring_cleanup(engine); 17387df8fc6SFrançois Tigeot else 1741e12ee3bSFrançois Tigeot intel_engine_cleanup(engine); 17587df8fc6SFrançois Tigeot } 17687df8fc6SFrançois Tigeot 17787df8fc6SFrançois Tigeot return ret; 17887df8fc6SFrançois Tigeot } 17987df8fc6SFrançois Tigeot 180*4be47400SFrançois Tigeot void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) 1811e12ee3bSFrançois Tigeot { 1821e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1831e12ee3bSFrançois Tigeot 1841e12ee3bSFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 1851e12ee3bSFrançois Tigeot * so long as the semaphore value in the register/page is greater 1861e12ee3bSFrançois Tigeot * than the sync value), so whenever we reset the seqno, 1871e12ee3bSFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 1881e12ee3bSFrançois Tigeot * always be before the next request's seqno. If we don't reset 1891e12ee3bSFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 1901e12ee3bSFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 1911e12ee3bSFrançois Tigeot */ 1921e12ee3bSFrançois Tigeot if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { 1931e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 1941e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 1951e12ee3bSFrançois Tigeot if (HAS_VEBOX(dev_priv)) 1961e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 1971e12ee3bSFrançois Tigeot } 1981e12ee3bSFrançois Tigeot if (dev_priv->semaphore) { 1991e12ee3bSFrançois Tigeot struct page *page = i915_vma_first_page(dev_priv->semaphore); 2001e12ee3bSFrançois Tigeot void *semaphores; 2011e12ee3bSFrançois Tigeot 2021e12ee3bSFrançois Tigeot /* Semaphores are in noncoherent memory, flush to be safe */ 2031e12ee3bSFrançois Tigeot semaphores = kmap(page); 2041e12ee3bSFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 2051e12ee3bSFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 2061e12ee3bSFrançois Tigeot drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 2071e12ee3bSFrançois Tigeot I915_NUM_ENGINES * gen8_semaphore_seqno_size); 2081e12ee3bSFrançois Tigeot kunmap(page); 2091e12ee3bSFrançois Tigeot } 2101e12ee3bSFrançois Tigeot 2111e12ee3bSFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 2121e12ee3bSFrançois Tigeot if (engine->irq_seqno_barrier) 2131e12ee3bSFrançois Tigeot engine->irq_seqno_barrier(engine); 214*4be47400SFrançois Tigeot 215*4be47400SFrançois Tigeot GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request)); 216*4be47400SFrançois Tigeot engine->timeline->last_submitted_seqno = seqno; 2171e12ee3bSFrançois Tigeot 2181e12ee3bSFrançois Tigeot engine->hangcheck.seqno = seqno; 2191e12ee3bSFrançois Tigeot 2201e12ee3bSFrançois Tigeot /* After manually advancing the seqno, fake the interrupt in case 2211e12ee3bSFrançois Tigeot * there are any waiters for that seqno. 2221e12ee3bSFrançois Tigeot */ 2231e12ee3bSFrançois Tigeot intel_engine_wakeup(engine); 2241e12ee3bSFrançois Tigeot } 2251e12ee3bSFrançois Tigeot 226*4be47400SFrançois Tigeot static void intel_engine_init_timeline(struct intel_engine_cs *engine) 22787df8fc6SFrançois Tigeot { 228*4be47400SFrançois Tigeot engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; 22971f41f3eSFrançois Tigeot } 23071f41f3eSFrançois Tigeot 23187df8fc6SFrançois Tigeot /** 23287df8fc6SFrançois Tigeot * intel_engines_setup_common - setup engine state not requiring hw access 23387df8fc6SFrançois Tigeot * @engine: Engine to setup. 23487df8fc6SFrançois Tigeot * 23587df8fc6SFrançois Tigeot * Initializes @engine@ structure members shared between legacy and execlists 23687df8fc6SFrançois Tigeot * submission modes which do not require hardware access. 23787df8fc6SFrançois Tigeot * 23887df8fc6SFrançois Tigeot * Typically done early in the submission mode specific engine setup stage. 23987df8fc6SFrançois Tigeot */ 24087df8fc6SFrançois Tigeot void intel_engine_setup_common(struct intel_engine_cs *engine) 24187df8fc6SFrançois Tigeot { 242*4be47400SFrançois Tigeot engine->execlist_queue = LINUX_RB_ROOT; 243*4be47400SFrançois Tigeot engine->execlist_first = NULL; 24487df8fc6SFrançois Tigeot 245*4be47400SFrançois Tigeot intel_engine_init_timeline(engine); 24687df8fc6SFrançois Tigeot intel_engine_init_hangcheck(engine); 24771f41f3eSFrançois Tigeot i915_gem_batch_pool_init(engine, &engine->batch_pool); 2481e12ee3bSFrançois Tigeot 2491e12ee3bSFrançois Tigeot intel_engine_init_cmd_parser(engine); 2501e12ee3bSFrançois Tigeot } 2511e12ee3bSFrançois Tigeot 2521e12ee3bSFrançois Tigeot int intel_engine_create_scratch(struct intel_engine_cs *engine, int size) 2531e12ee3bSFrançois Tigeot { 2541e12ee3bSFrançois Tigeot struct drm_i915_gem_object *obj; 2551e12ee3bSFrançois Tigeot struct i915_vma *vma; 2561e12ee3bSFrançois Tigeot int ret; 2571e12ee3bSFrançois Tigeot 2581e12ee3bSFrançois Tigeot WARN_ON(engine->scratch); 2591e12ee3bSFrançois Tigeot 2601e12ee3bSFrançois Tigeot obj = i915_gem_object_create_stolen(&engine->i915->drm, size); 2611e12ee3bSFrançois Tigeot if (!obj) 262*4be47400SFrançois Tigeot obj = i915_gem_object_create_internal(engine->i915, size); 2631e12ee3bSFrançois Tigeot if (IS_ERR(obj)) { 2641e12ee3bSFrançois Tigeot DRM_ERROR("Failed to allocate scratch page\n"); 2651e12ee3bSFrançois Tigeot return PTR_ERR(obj); 2661e12ee3bSFrançois Tigeot } 2671e12ee3bSFrançois Tigeot 2681e12ee3bSFrançois Tigeot vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL); 2691e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 2701e12ee3bSFrançois Tigeot ret = PTR_ERR(vma); 2711e12ee3bSFrançois Tigeot goto err_unref; 2721e12ee3bSFrançois Tigeot } 2731e12ee3bSFrançois Tigeot 2741e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 4096, PIN_GLOBAL | PIN_HIGH); 2751e12ee3bSFrançois Tigeot if (ret) 2761e12ee3bSFrançois Tigeot goto err_unref; 2771e12ee3bSFrançois Tigeot 2781e12ee3bSFrançois Tigeot engine->scratch = vma; 2791e12ee3bSFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 2801e12ee3bSFrançois Tigeot engine->name, i915_ggtt_offset(vma)); 2811e12ee3bSFrançois Tigeot return 0; 2821e12ee3bSFrançois Tigeot 2831e12ee3bSFrançois Tigeot err_unref: 2841e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 2851e12ee3bSFrançois Tigeot return ret; 2861e12ee3bSFrançois Tigeot } 2871e12ee3bSFrançois Tigeot 2881e12ee3bSFrançois Tigeot static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine) 2891e12ee3bSFrançois Tigeot { 2901e12ee3bSFrançois Tigeot i915_vma_unpin_and_release(&engine->scratch); 29187df8fc6SFrançois Tigeot } 29287df8fc6SFrançois Tigeot 29387df8fc6SFrançois Tigeot /** 29487df8fc6SFrançois Tigeot * intel_engines_init_common - initialize cengine state which might require hw access 29587df8fc6SFrançois Tigeot * @engine: Engine to initialize. 29687df8fc6SFrançois Tigeot * 29787df8fc6SFrançois Tigeot * Initializes @engine@ structure members shared between legacy and execlists 29887df8fc6SFrançois Tigeot * submission modes which do require hardware access. 29987df8fc6SFrançois Tigeot * 30087df8fc6SFrançois Tigeot * Typcally done at later stages of submission mode specific engine setup. 30187df8fc6SFrançois Tigeot * 30287df8fc6SFrançois Tigeot * Returns zero on success or an error code on failure. 30387df8fc6SFrançois Tigeot */ 30487df8fc6SFrançois Tigeot int intel_engine_init_common(struct intel_engine_cs *engine) 30587df8fc6SFrançois Tigeot { 30687df8fc6SFrançois Tigeot int ret; 30787df8fc6SFrançois Tigeot 30887df8fc6SFrançois Tigeot ret = intel_engine_init_breadcrumbs(engine); 30987df8fc6SFrançois Tigeot if (ret) 31087df8fc6SFrançois Tigeot return ret; 31187df8fc6SFrançois Tigeot 312*4be47400SFrançois Tigeot ret = i915_gem_render_state_init(engine); 313*4be47400SFrançois Tigeot if (ret) 314*4be47400SFrançois Tigeot return ret; 315*4be47400SFrançois Tigeot 3161e12ee3bSFrançois Tigeot return 0; 31771f41f3eSFrançois Tigeot } 31871f41f3eSFrançois Tigeot 31971f41f3eSFrançois Tigeot /** 32071f41f3eSFrançois Tigeot * intel_engines_cleanup_common - cleans up the engine state created by 32171f41f3eSFrançois Tigeot * the common initiailizers. 32271f41f3eSFrançois Tigeot * @engine: Engine to cleanup. 32371f41f3eSFrançois Tigeot * 32471f41f3eSFrançois Tigeot * This cleans up everything created by the common helpers. 32571f41f3eSFrançois Tigeot */ 32671f41f3eSFrançois Tigeot void intel_engine_cleanup_common(struct intel_engine_cs *engine) 32771f41f3eSFrançois Tigeot { 3281e12ee3bSFrançois Tigeot intel_engine_cleanup_scratch(engine); 3291e12ee3bSFrançois Tigeot 330*4be47400SFrançois Tigeot i915_gem_render_state_fini(engine); 33171f41f3eSFrançois Tigeot intel_engine_fini_breadcrumbs(engine); 3321e12ee3bSFrançois Tigeot intel_engine_cleanup_cmd_parser(engine); 33371f41f3eSFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 33487df8fc6SFrançois Tigeot } 3351e12ee3bSFrançois Tigeot 3361e12ee3bSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine) 3371e12ee3bSFrançois Tigeot { 3381e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 3391e12ee3bSFrançois Tigeot u64 acthd; 3401e12ee3bSFrançois Tigeot 3411e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 3421e12ee3bSFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 3431e12ee3bSFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 3441e12ee3bSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 3451e12ee3bSFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 3461e12ee3bSFrançois Tigeot else 3471e12ee3bSFrançois Tigeot acthd = I915_READ(ACTHD); 3481e12ee3bSFrançois Tigeot 3491e12ee3bSFrançois Tigeot return acthd; 3501e12ee3bSFrançois Tigeot } 3511e12ee3bSFrançois Tigeot 3521e12ee3bSFrançois Tigeot u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) 3531e12ee3bSFrançois Tigeot { 3541e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 3551e12ee3bSFrançois Tigeot u64 bbaddr; 3561e12ee3bSFrançois Tigeot 3571e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 3581e12ee3bSFrançois Tigeot bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base), 3591e12ee3bSFrançois Tigeot RING_BBADDR_UDW(engine->mmio_base)); 3601e12ee3bSFrançois Tigeot else 3611e12ee3bSFrançois Tigeot bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); 3621e12ee3bSFrançois Tigeot 3631e12ee3bSFrançois Tigeot return bbaddr; 3641e12ee3bSFrançois Tigeot } 3651e12ee3bSFrançois Tigeot 3661e12ee3bSFrançois Tigeot const char *i915_cache_level_str(struct drm_i915_private *i915, int type) 3671e12ee3bSFrançois Tigeot { 3681e12ee3bSFrançois Tigeot switch (type) { 3691e12ee3bSFrançois Tigeot case I915_CACHE_NONE: return " uncached"; 3701e12ee3bSFrançois Tigeot case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; 3711e12ee3bSFrançois Tigeot case I915_CACHE_L3_LLC: return " L3+LLC"; 3721e12ee3bSFrançois Tigeot case I915_CACHE_WT: return " WT"; 3731e12ee3bSFrançois Tigeot default: return ""; 3741e12ee3bSFrançois Tigeot } 3751e12ee3bSFrançois Tigeot } 3761e12ee3bSFrançois Tigeot 3771e12ee3bSFrançois Tigeot static inline uint32_t 3781e12ee3bSFrançois Tigeot read_subslice_reg(struct drm_i915_private *dev_priv, int slice, 3791e12ee3bSFrançois Tigeot int subslice, i915_reg_t reg) 3801e12ee3bSFrançois Tigeot { 3811e12ee3bSFrançois Tigeot uint32_t mcr; 3821e12ee3bSFrançois Tigeot uint32_t ret; 3831e12ee3bSFrançois Tigeot enum forcewake_domains fw_domains; 3841e12ee3bSFrançois Tigeot 3851e12ee3bSFrançois Tigeot fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, 3861e12ee3bSFrançois Tigeot FW_REG_READ); 3871e12ee3bSFrançois Tigeot fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, 3881e12ee3bSFrançois Tigeot GEN8_MCR_SELECTOR, 3891e12ee3bSFrançois Tigeot FW_REG_READ | FW_REG_WRITE); 3901e12ee3bSFrançois Tigeot 3911e12ee3bSFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 3921e12ee3bSFrançois Tigeot intel_uncore_forcewake_get__locked(dev_priv, fw_domains); 3931e12ee3bSFrançois Tigeot 3941e12ee3bSFrançois Tigeot mcr = I915_READ_FW(GEN8_MCR_SELECTOR); 3951e12ee3bSFrançois Tigeot /* 3961e12ee3bSFrançois Tigeot * The HW expects the slice and sublice selectors to be reset to 0 3971e12ee3bSFrançois Tigeot * after reading out the registers. 3981e12ee3bSFrançois Tigeot */ 3991e12ee3bSFrançois Tigeot WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); 4001e12ee3bSFrançois Tigeot mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); 4011e12ee3bSFrançois Tigeot mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); 4021e12ee3bSFrançois Tigeot I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); 4031e12ee3bSFrançois Tigeot 4041e12ee3bSFrançois Tigeot ret = I915_READ_FW(reg); 4051e12ee3bSFrançois Tigeot 4061e12ee3bSFrançois Tigeot mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); 4071e12ee3bSFrançois Tigeot I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); 4081e12ee3bSFrançois Tigeot 4091e12ee3bSFrançois Tigeot intel_uncore_forcewake_put__locked(dev_priv, fw_domains); 4101e12ee3bSFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 4111e12ee3bSFrançois Tigeot 4121e12ee3bSFrançois Tigeot return ret; 4131e12ee3bSFrançois Tigeot } 4141e12ee3bSFrançois Tigeot 4151e12ee3bSFrançois Tigeot /* NB: please notice the memset */ 4161e12ee3bSFrançois Tigeot void intel_engine_get_instdone(struct intel_engine_cs *engine, 4171e12ee3bSFrançois Tigeot struct intel_instdone *instdone) 4181e12ee3bSFrançois Tigeot { 4191e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4201e12ee3bSFrançois Tigeot u32 mmio_base = engine->mmio_base; 4211e12ee3bSFrançois Tigeot int slice; 4221e12ee3bSFrançois Tigeot int subslice; 4231e12ee3bSFrançois Tigeot 4241e12ee3bSFrançois Tigeot memset(instdone, 0, sizeof(*instdone)); 4251e12ee3bSFrançois Tigeot 4261e12ee3bSFrançois Tigeot switch (INTEL_GEN(dev_priv)) { 4271e12ee3bSFrançois Tigeot default: 4281e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 4291e12ee3bSFrançois Tigeot 4301e12ee3bSFrançois Tigeot if (engine->id != RCS) 4311e12ee3bSFrançois Tigeot break; 4321e12ee3bSFrançois Tigeot 4331e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); 4341e12ee3bSFrançois Tigeot for_each_instdone_slice_subslice(dev_priv, slice, subslice) { 4351e12ee3bSFrançois Tigeot instdone->sampler[slice][subslice] = 4361e12ee3bSFrançois Tigeot read_subslice_reg(dev_priv, slice, subslice, 4371e12ee3bSFrançois Tigeot GEN7_SAMPLER_INSTDONE); 4381e12ee3bSFrançois Tigeot instdone->row[slice][subslice] = 4391e12ee3bSFrançois Tigeot read_subslice_reg(dev_priv, slice, subslice, 4401e12ee3bSFrançois Tigeot GEN7_ROW_INSTDONE); 4411e12ee3bSFrançois Tigeot } 4421e12ee3bSFrançois Tigeot break; 4431e12ee3bSFrançois Tigeot case 7: 4441e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 4451e12ee3bSFrançois Tigeot 4461e12ee3bSFrançois Tigeot if (engine->id != RCS) 4471e12ee3bSFrançois Tigeot break; 4481e12ee3bSFrançois Tigeot 4491e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); 4501e12ee3bSFrançois Tigeot instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); 4511e12ee3bSFrançois Tigeot instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); 4521e12ee3bSFrançois Tigeot 4531e12ee3bSFrançois Tigeot break; 4541e12ee3bSFrançois Tigeot case 6: 4551e12ee3bSFrançois Tigeot case 5: 4561e12ee3bSFrançois Tigeot case 4: 4571e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 4581e12ee3bSFrançois Tigeot 4591e12ee3bSFrançois Tigeot if (engine->id == RCS) 4601e12ee3bSFrançois Tigeot /* HACK: Using the wrong struct member */ 4611e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN4_INSTDONE1); 4621e12ee3bSFrançois Tigeot break; 4631e12ee3bSFrançois Tigeot case 3: 4641e12ee3bSFrançois Tigeot case 2: 4651e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(GEN2_INSTDONE); 4661e12ee3bSFrançois Tigeot break; 4671e12ee3bSFrançois Tigeot } 4681e12ee3bSFrançois Tigeot } 469