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; 31*a85cb24fSFrançois Tigeot unsigned int exec_id; 32*a85cb24fSFrançois Tigeot unsigned int 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] = { 39*a85cb24fSFrançois Tigeot .name = "rcs", 401e12ee3bSFrançois Tigeot .hw_id = RCS_HW, 41*a85cb24fSFrançois Tigeot .exec_id = I915_EXEC_RENDER, 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] = { 48*a85cb24fSFrançois Tigeot .name = "bcs", 491e12ee3bSFrançois Tigeot .hw_id = BCS_HW, 50*a85cb24fSFrançois Tigeot .exec_id = I915_EXEC_BLT, 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] = { 57*a85cb24fSFrançois Tigeot .name = "vcs", 581e12ee3bSFrançois Tigeot .hw_id = VCS_HW, 59*a85cb24fSFrançois Tigeot .exec_id = I915_EXEC_BSD, 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] = { 66*a85cb24fSFrançois Tigeot .name = "vcs2", 671e12ee3bSFrançois Tigeot .hw_id = VCS2_HW, 68*a85cb24fSFrançois Tigeot .exec_id = I915_EXEC_BSD, 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] = { 75*a85cb24fSFrançois Tigeot .name = "vecs", 761e12ee3bSFrançois Tigeot .hw_id = VECS_HW, 77*a85cb24fSFrançois Tigeot .exec_id = I915_EXEC_VEBOX, 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 1054be47400SFrançois Tigeot /* Nothing to do here, execute in order of dependencies */ 1064be47400SFrançois Tigeot engine->schedule = NULL; 1074be47400SFrançois Tigeot 108*a85cb24fSFrançois Tigeot ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier); 109*a85cb24fSFrançois Tigeot 1101e12ee3bSFrançois Tigeot dev_priv->engine[id] = engine; 1111e12ee3bSFrançois Tigeot return 0; 11287df8fc6SFrançois Tigeot } 11387df8fc6SFrançois Tigeot 11487df8fc6SFrançois Tigeot /** 115*a85cb24fSFrançois Tigeot * intel_engines_init_early() - allocate the Engine Command Streamers 116*a85cb24fSFrançois Tigeot * @dev_priv: i915 device private 11787df8fc6SFrançois Tigeot * 11887df8fc6SFrançois Tigeot * Return: non-zero if the initialization failed. 11987df8fc6SFrançois Tigeot */ 120*a85cb24fSFrançois Tigeot int intel_engines_init_early(struct drm_i915_private *dev_priv) 12187df8fc6SFrançois Tigeot { 1221e12ee3bSFrançois Tigeot struct intel_device_info *device_info = mkwrite_device_info(dev_priv); 1231e12ee3bSFrançois Tigeot unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask; 12487df8fc6SFrançois Tigeot unsigned int mask = 0; 1251e12ee3bSFrançois Tigeot struct intel_engine_cs *engine; 1261e12ee3bSFrançois Tigeot enum intel_engine_id id; 12787df8fc6SFrançois Tigeot unsigned int i; 128*a85cb24fSFrançois Tigeot int err; 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 138*a85cb24fSFrançois Tigeot err = intel_engine_setup(dev_priv, i); 139*a85cb24fSFrançois Tigeot if (err) 14087df8fc6SFrançois Tigeot goto cleanup; 14187df8fc6SFrançois Tigeot 14287df8fc6SFrançois Tigeot mask |= ENGINE_MASK(i); 14387df8fc6SFrançois Tigeot } 14487df8fc6SFrançois Tigeot 14587df8fc6SFrançois Tigeot /* 14687df8fc6SFrançois Tigeot * Catch failures to update intel_engines table when the new engines 14787df8fc6SFrançois Tigeot * are added to the driver by a warning and disabling the forgotten 14887df8fc6SFrançois Tigeot * engines. 14987df8fc6SFrançois Tigeot */ 1501e12ee3bSFrançois Tigeot if (WARN_ON(mask != ring_mask)) 1511e12ee3bSFrançois Tigeot device_info->ring_mask = mask; 1521e12ee3bSFrançois Tigeot 1531e12ee3bSFrançois Tigeot device_info->num_rings = hweight32(mask); 15487df8fc6SFrançois Tigeot 15587df8fc6SFrançois Tigeot return 0; 15687df8fc6SFrançois Tigeot 15787df8fc6SFrançois Tigeot cleanup: 158*a85cb24fSFrançois Tigeot for_each_engine(engine, dev_priv, id) 159*a85cb24fSFrançois Tigeot kfree(engine); 160*a85cb24fSFrançois Tigeot return err; 16187df8fc6SFrançois Tigeot } 16287df8fc6SFrançois Tigeot 163*a85cb24fSFrançois Tigeot /** 164*a85cb24fSFrançois Tigeot * intel_engines_init() - allocate, populate and init the Engine Command Streamers 165*a85cb24fSFrançois Tigeot * @dev_priv: i915 device private 166*a85cb24fSFrançois Tigeot * 167*a85cb24fSFrançois Tigeot * Return: non-zero if the initialization failed. 168*a85cb24fSFrançois Tigeot */ 169*a85cb24fSFrançois Tigeot int intel_engines_init(struct drm_i915_private *dev_priv) 170*a85cb24fSFrançois Tigeot { 171*a85cb24fSFrançois Tigeot struct intel_device_info *device_info = mkwrite_device_info(dev_priv); 172*a85cb24fSFrançois Tigeot struct intel_engine_cs *engine; 173*a85cb24fSFrançois Tigeot enum intel_engine_id id, err_id; 174*a85cb24fSFrançois Tigeot unsigned int mask = 0; 175*a85cb24fSFrançois Tigeot int err = 0; 176*a85cb24fSFrançois Tigeot 177*a85cb24fSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 178*a85cb24fSFrançois Tigeot int (*init)(struct intel_engine_cs *engine); 179*a85cb24fSFrançois Tigeot 180*a85cb24fSFrançois Tigeot if (i915.enable_execlists) 181*a85cb24fSFrançois Tigeot init = intel_engines[id].init_execlists; 182*a85cb24fSFrançois Tigeot else 183*a85cb24fSFrançois Tigeot init = intel_engines[id].init_legacy; 184*a85cb24fSFrançois Tigeot if (!init) { 185*a85cb24fSFrançois Tigeot kfree(engine); 186*a85cb24fSFrançois Tigeot dev_priv->engine[id] = NULL; 187*a85cb24fSFrançois Tigeot continue; 188*a85cb24fSFrançois Tigeot } 189*a85cb24fSFrançois Tigeot 190*a85cb24fSFrançois Tigeot err = init(engine); 191*a85cb24fSFrançois Tigeot if (err) { 192*a85cb24fSFrançois Tigeot err_id = id; 193*a85cb24fSFrançois Tigeot goto cleanup; 194*a85cb24fSFrançois Tigeot } 195*a85cb24fSFrançois Tigeot 196*a85cb24fSFrançois Tigeot GEM_BUG_ON(!engine->submit_request); 197*a85cb24fSFrançois Tigeot mask |= ENGINE_MASK(id); 198*a85cb24fSFrançois Tigeot } 199*a85cb24fSFrançois Tigeot 200*a85cb24fSFrançois Tigeot /* 201*a85cb24fSFrançois Tigeot * Catch failures to update intel_engines table when the new engines 202*a85cb24fSFrançois Tigeot * are added to the driver by a warning and disabling the forgotten 203*a85cb24fSFrançois Tigeot * engines. 204*a85cb24fSFrançois Tigeot */ 205*a85cb24fSFrançois Tigeot if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask)) 206*a85cb24fSFrançois Tigeot device_info->ring_mask = mask; 207*a85cb24fSFrançois Tigeot 208*a85cb24fSFrançois Tigeot device_info->num_rings = hweight32(mask); 209*a85cb24fSFrançois Tigeot 210*a85cb24fSFrançois Tigeot return 0; 211*a85cb24fSFrançois Tigeot 212*a85cb24fSFrançois Tigeot cleanup: 213*a85cb24fSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 214*a85cb24fSFrançois Tigeot if (id >= err_id) 215*a85cb24fSFrançois Tigeot kfree(engine); 216*a85cb24fSFrançois Tigeot else 217*a85cb24fSFrançois Tigeot dev_priv->gt.cleanup_engine(engine); 218*a85cb24fSFrançois Tigeot } 219*a85cb24fSFrançois Tigeot return err; 22087df8fc6SFrançois Tigeot } 22187df8fc6SFrançois Tigeot 2224be47400SFrançois Tigeot void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno) 2231e12ee3bSFrançois Tigeot { 2241e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 2251e12ee3bSFrançois Tigeot 2261e12ee3bSFrançois Tigeot /* Our semaphore implementation is strictly monotonic (i.e. we proceed 2271e12ee3bSFrançois Tigeot * so long as the semaphore value in the register/page is greater 2281e12ee3bSFrançois Tigeot * than the sync value), so whenever we reset the seqno, 2291e12ee3bSFrançois Tigeot * so long as we reset the tracking semaphore value to 0, it will 2301e12ee3bSFrançois Tigeot * always be before the next request's seqno. If we don't reset 2311e12ee3bSFrançois Tigeot * the semaphore value, then when the seqno moves backwards all 2321e12ee3bSFrançois Tigeot * future waits will complete instantly (causing rendering corruption). 2331e12ee3bSFrançois Tigeot */ 2341e12ee3bSFrançois Tigeot if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { 2351e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_0(engine->mmio_base), 0); 2361e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_1(engine->mmio_base), 0); 2371e12ee3bSFrançois Tigeot if (HAS_VEBOX(dev_priv)) 2381e12ee3bSFrançois Tigeot I915_WRITE(RING_SYNC_2(engine->mmio_base), 0); 2391e12ee3bSFrançois Tigeot } 2401e12ee3bSFrançois Tigeot if (dev_priv->semaphore) { 2411e12ee3bSFrançois Tigeot struct page *page = i915_vma_first_page(dev_priv->semaphore); 2421e12ee3bSFrançois Tigeot void *semaphores; 2431e12ee3bSFrançois Tigeot 2441e12ee3bSFrançois Tigeot /* Semaphores are in noncoherent memory, flush to be safe */ 245*a85cb24fSFrançois Tigeot semaphores = kmap_atomic(page); 2461e12ee3bSFrançois Tigeot memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 2471e12ee3bSFrançois Tigeot 0, I915_NUM_ENGINES * gen8_semaphore_seqno_size); 2481e12ee3bSFrançois Tigeot drm_clflush_virt_range(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0), 2491e12ee3bSFrançois Tigeot I915_NUM_ENGINES * gen8_semaphore_seqno_size); 250*a85cb24fSFrançois Tigeot kunmap_atomic(semaphores); 2511e12ee3bSFrançois Tigeot } 2521e12ee3bSFrançois Tigeot 2531e12ee3bSFrançois Tigeot intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno); 254*a85cb24fSFrançois Tigeot clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted); 2554be47400SFrançois Tigeot 2564be47400SFrançois Tigeot GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request)); 2571e12ee3bSFrançois Tigeot engine->hangcheck.seqno = seqno; 2581e12ee3bSFrançois Tigeot 2591e12ee3bSFrançois Tigeot /* After manually advancing the seqno, fake the interrupt in case 2601e12ee3bSFrançois Tigeot * there are any waiters for that seqno. 2611e12ee3bSFrançois Tigeot */ 2621e12ee3bSFrançois Tigeot intel_engine_wakeup(engine); 2631e12ee3bSFrançois Tigeot } 2641e12ee3bSFrançois Tigeot 2654be47400SFrançois Tigeot static void intel_engine_init_timeline(struct intel_engine_cs *engine) 26687df8fc6SFrançois Tigeot { 2674be47400SFrançois Tigeot engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; 26871f41f3eSFrançois Tigeot } 26971f41f3eSFrançois Tigeot 27087df8fc6SFrançois Tigeot /** 27187df8fc6SFrançois Tigeot * intel_engines_setup_common - setup engine state not requiring hw access 27287df8fc6SFrançois Tigeot * @engine: Engine to setup. 27387df8fc6SFrançois Tigeot * 27487df8fc6SFrançois Tigeot * Initializes @engine@ structure members shared between legacy and execlists 27587df8fc6SFrançois Tigeot * submission modes which do not require hardware access. 27687df8fc6SFrançois Tigeot * 27787df8fc6SFrançois Tigeot * Typically done early in the submission mode specific engine setup stage. 27887df8fc6SFrançois Tigeot */ 27987df8fc6SFrançois Tigeot void intel_engine_setup_common(struct intel_engine_cs *engine) 28087df8fc6SFrançois Tigeot { 2814be47400SFrançois Tigeot engine->execlist_queue = LINUX_RB_ROOT; 2824be47400SFrançois Tigeot engine->execlist_first = NULL; 28387df8fc6SFrançois Tigeot 2844be47400SFrançois Tigeot intel_engine_init_timeline(engine); 28587df8fc6SFrançois Tigeot intel_engine_init_hangcheck(engine); 28671f41f3eSFrançois Tigeot i915_gem_batch_pool_init(engine, &engine->batch_pool); 2871e12ee3bSFrançois Tigeot 2881e12ee3bSFrançois Tigeot intel_engine_init_cmd_parser(engine); 2891e12ee3bSFrançois Tigeot } 2901e12ee3bSFrançois Tigeot 2911e12ee3bSFrançois Tigeot int intel_engine_create_scratch(struct intel_engine_cs *engine, int size) 2921e12ee3bSFrançois Tigeot { 2931e12ee3bSFrançois Tigeot struct drm_i915_gem_object *obj; 2941e12ee3bSFrançois Tigeot struct i915_vma *vma; 2951e12ee3bSFrançois Tigeot int ret; 2961e12ee3bSFrançois Tigeot 2971e12ee3bSFrançois Tigeot WARN_ON(engine->scratch); 2981e12ee3bSFrançois Tigeot 299*a85cb24fSFrançois Tigeot obj = i915_gem_object_create_stolen(engine->i915, size); 3001e12ee3bSFrançois Tigeot if (!obj) 3014be47400SFrançois Tigeot obj = i915_gem_object_create_internal(engine->i915, size); 3021e12ee3bSFrançois Tigeot if (IS_ERR(obj)) { 3031e12ee3bSFrançois Tigeot DRM_ERROR("Failed to allocate scratch page\n"); 3041e12ee3bSFrançois Tigeot return PTR_ERR(obj); 3051e12ee3bSFrançois Tigeot } 3061e12ee3bSFrançois Tigeot 307*a85cb24fSFrançois Tigeot vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); 3081e12ee3bSFrançois Tigeot if (IS_ERR(vma)) { 3091e12ee3bSFrançois Tigeot ret = PTR_ERR(vma); 3101e12ee3bSFrançois Tigeot goto err_unref; 3111e12ee3bSFrançois Tigeot } 3121e12ee3bSFrançois Tigeot 3131e12ee3bSFrançois Tigeot ret = i915_vma_pin(vma, 0, 4096, PIN_GLOBAL | PIN_HIGH); 3141e12ee3bSFrançois Tigeot if (ret) 3151e12ee3bSFrançois Tigeot goto err_unref; 3161e12ee3bSFrançois Tigeot 3171e12ee3bSFrançois Tigeot engine->scratch = vma; 3181e12ee3bSFrançois Tigeot DRM_DEBUG_DRIVER("%s pipe control offset: 0x%08x\n", 3191e12ee3bSFrançois Tigeot engine->name, i915_ggtt_offset(vma)); 3201e12ee3bSFrançois Tigeot return 0; 3211e12ee3bSFrançois Tigeot 3221e12ee3bSFrançois Tigeot err_unref: 3231e12ee3bSFrançois Tigeot i915_gem_object_put(obj); 3241e12ee3bSFrançois Tigeot return ret; 3251e12ee3bSFrançois Tigeot } 3261e12ee3bSFrançois Tigeot 3271e12ee3bSFrançois Tigeot static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine) 3281e12ee3bSFrançois Tigeot { 3291e12ee3bSFrançois Tigeot i915_vma_unpin_and_release(&engine->scratch); 33087df8fc6SFrançois Tigeot } 33187df8fc6SFrançois Tigeot 33287df8fc6SFrançois Tigeot /** 33387df8fc6SFrançois Tigeot * intel_engines_init_common - initialize cengine state which might require hw access 33487df8fc6SFrançois Tigeot * @engine: Engine to initialize. 33587df8fc6SFrançois Tigeot * 33687df8fc6SFrançois Tigeot * Initializes @engine@ structure members shared between legacy and execlists 33787df8fc6SFrançois Tigeot * submission modes which do require hardware access. 33887df8fc6SFrançois Tigeot * 33987df8fc6SFrançois Tigeot * Typcally done at later stages of submission mode specific engine setup. 34087df8fc6SFrançois Tigeot * 34187df8fc6SFrançois Tigeot * Returns zero on success or an error code on failure. 34287df8fc6SFrançois Tigeot */ 34387df8fc6SFrançois Tigeot int intel_engine_init_common(struct intel_engine_cs *engine) 34487df8fc6SFrançois Tigeot { 34587df8fc6SFrançois Tigeot int ret; 34687df8fc6SFrançois Tigeot 347*a85cb24fSFrançois Tigeot engine->set_default_submission(engine); 348*a85cb24fSFrançois Tigeot 349*a85cb24fSFrançois Tigeot /* We may need to do things with the shrinker which 350*a85cb24fSFrançois Tigeot * require us to immediately switch back to the default 351*a85cb24fSFrançois Tigeot * context. This can cause a problem as pinning the 352*a85cb24fSFrançois Tigeot * default context also requires GTT space which may not 353*a85cb24fSFrançois Tigeot * be available. To avoid this we always pin the default 354*a85cb24fSFrançois Tigeot * context. 355*a85cb24fSFrançois Tigeot */ 356*a85cb24fSFrançois Tigeot ret = engine->context_pin(engine, engine->i915->kernel_context); 35787df8fc6SFrançois Tigeot if (ret) 35887df8fc6SFrançois Tigeot return ret; 35987df8fc6SFrançois Tigeot 360*a85cb24fSFrançois Tigeot ret = intel_engine_init_breadcrumbs(engine); 361*a85cb24fSFrançois Tigeot if (ret) 362*a85cb24fSFrançois Tigeot goto err_unpin; 363*a85cb24fSFrançois Tigeot 3644be47400SFrançois Tigeot ret = i915_gem_render_state_init(engine); 3654be47400SFrançois Tigeot if (ret) 366*a85cb24fSFrançois Tigeot goto err_unpin; 3674be47400SFrançois Tigeot 3681e12ee3bSFrançois Tigeot return 0; 369*a85cb24fSFrançois Tigeot 370*a85cb24fSFrançois Tigeot err_unpin: 371*a85cb24fSFrançois Tigeot engine->context_unpin(engine, engine->i915->kernel_context); 372*a85cb24fSFrançois Tigeot return ret; 37371f41f3eSFrançois Tigeot } 37471f41f3eSFrançois Tigeot 37571f41f3eSFrançois Tigeot /** 37671f41f3eSFrançois Tigeot * intel_engines_cleanup_common - cleans up the engine state created by 37771f41f3eSFrançois Tigeot * the common initiailizers. 37871f41f3eSFrançois Tigeot * @engine: Engine to cleanup. 37971f41f3eSFrançois Tigeot * 38071f41f3eSFrançois Tigeot * This cleans up everything created by the common helpers. 38171f41f3eSFrançois Tigeot */ 38271f41f3eSFrançois Tigeot void intel_engine_cleanup_common(struct intel_engine_cs *engine) 38371f41f3eSFrançois Tigeot { 3841e12ee3bSFrançois Tigeot intel_engine_cleanup_scratch(engine); 3851e12ee3bSFrançois Tigeot 3864be47400SFrançois Tigeot i915_gem_render_state_fini(engine); 38771f41f3eSFrançois Tigeot intel_engine_fini_breadcrumbs(engine); 3881e12ee3bSFrançois Tigeot intel_engine_cleanup_cmd_parser(engine); 38971f41f3eSFrançois Tigeot i915_gem_batch_pool_fini(&engine->batch_pool); 390*a85cb24fSFrançois Tigeot 391*a85cb24fSFrançois Tigeot engine->context_unpin(engine, engine->i915->kernel_context); 39287df8fc6SFrançois Tigeot } 3931e12ee3bSFrançois Tigeot 3941e12ee3bSFrançois Tigeot u64 intel_engine_get_active_head(struct intel_engine_cs *engine) 3951e12ee3bSFrançois Tigeot { 3961e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 3971e12ee3bSFrançois Tigeot u64 acthd; 3981e12ee3bSFrançois Tigeot 3991e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 4001e12ee3bSFrançois Tigeot acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), 4011e12ee3bSFrançois Tigeot RING_ACTHD_UDW(engine->mmio_base)); 4021e12ee3bSFrançois Tigeot else if (INTEL_GEN(dev_priv) >= 4) 4031e12ee3bSFrançois Tigeot acthd = I915_READ(RING_ACTHD(engine->mmio_base)); 4041e12ee3bSFrançois Tigeot else 4051e12ee3bSFrançois Tigeot acthd = I915_READ(ACTHD); 4061e12ee3bSFrançois Tigeot 4071e12ee3bSFrançois Tigeot return acthd; 4081e12ee3bSFrançois Tigeot } 4091e12ee3bSFrançois Tigeot 4101e12ee3bSFrançois Tigeot u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) 4111e12ee3bSFrançois Tigeot { 4121e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4131e12ee3bSFrançois Tigeot u64 bbaddr; 4141e12ee3bSFrançois Tigeot 4151e12ee3bSFrançois Tigeot if (INTEL_GEN(dev_priv) >= 8) 4161e12ee3bSFrançois Tigeot bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base), 4171e12ee3bSFrançois Tigeot RING_BBADDR_UDW(engine->mmio_base)); 4181e12ee3bSFrançois Tigeot else 4191e12ee3bSFrançois Tigeot bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); 4201e12ee3bSFrançois Tigeot 4211e12ee3bSFrançois Tigeot return bbaddr; 4221e12ee3bSFrançois Tigeot } 4231e12ee3bSFrançois Tigeot 4241e12ee3bSFrançois Tigeot const char *i915_cache_level_str(struct drm_i915_private *i915, int type) 4251e12ee3bSFrançois Tigeot { 4261e12ee3bSFrançois Tigeot switch (type) { 4271e12ee3bSFrançois Tigeot case I915_CACHE_NONE: return " uncached"; 4281e12ee3bSFrançois Tigeot case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; 4291e12ee3bSFrançois Tigeot case I915_CACHE_L3_LLC: return " L3+LLC"; 4301e12ee3bSFrançois Tigeot case I915_CACHE_WT: return " WT"; 4311e12ee3bSFrançois Tigeot default: return ""; 4321e12ee3bSFrançois Tigeot } 4331e12ee3bSFrançois Tigeot } 4341e12ee3bSFrançois Tigeot 4351e12ee3bSFrançois Tigeot static inline uint32_t 4361e12ee3bSFrançois Tigeot read_subslice_reg(struct drm_i915_private *dev_priv, int slice, 4371e12ee3bSFrançois Tigeot int subslice, i915_reg_t reg) 4381e12ee3bSFrançois Tigeot { 4391e12ee3bSFrançois Tigeot uint32_t mcr; 4401e12ee3bSFrançois Tigeot uint32_t ret; 4411e12ee3bSFrançois Tigeot enum forcewake_domains fw_domains; 4421e12ee3bSFrançois Tigeot 4431e12ee3bSFrançois Tigeot fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, 4441e12ee3bSFrançois Tigeot FW_REG_READ); 4451e12ee3bSFrançois Tigeot fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, 4461e12ee3bSFrançois Tigeot GEN8_MCR_SELECTOR, 4471e12ee3bSFrançois Tigeot FW_REG_READ | FW_REG_WRITE); 4481e12ee3bSFrançois Tigeot 4491e12ee3bSFrançois Tigeot spin_lock_irq(&dev_priv->uncore.lock); 4501e12ee3bSFrançois Tigeot intel_uncore_forcewake_get__locked(dev_priv, fw_domains); 4511e12ee3bSFrançois Tigeot 4521e12ee3bSFrançois Tigeot mcr = I915_READ_FW(GEN8_MCR_SELECTOR); 4531e12ee3bSFrançois Tigeot /* 4541e12ee3bSFrançois Tigeot * The HW expects the slice and sublice selectors to be reset to 0 4551e12ee3bSFrançois Tigeot * after reading out the registers. 4561e12ee3bSFrançois Tigeot */ 4571e12ee3bSFrançois Tigeot WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); 4581e12ee3bSFrançois Tigeot mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); 4591e12ee3bSFrançois Tigeot mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); 4601e12ee3bSFrançois Tigeot I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); 4611e12ee3bSFrançois Tigeot 4621e12ee3bSFrançois Tigeot ret = I915_READ_FW(reg); 4631e12ee3bSFrançois Tigeot 4641e12ee3bSFrançois Tigeot mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); 4651e12ee3bSFrançois Tigeot I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); 4661e12ee3bSFrançois Tigeot 4671e12ee3bSFrançois Tigeot intel_uncore_forcewake_put__locked(dev_priv, fw_domains); 4681e12ee3bSFrançois Tigeot spin_unlock_irq(&dev_priv->uncore.lock); 4691e12ee3bSFrançois Tigeot 4701e12ee3bSFrançois Tigeot return ret; 4711e12ee3bSFrançois Tigeot } 4721e12ee3bSFrançois Tigeot 4731e12ee3bSFrançois Tigeot /* NB: please notice the memset */ 4741e12ee3bSFrançois Tigeot void intel_engine_get_instdone(struct intel_engine_cs *engine, 4751e12ee3bSFrançois Tigeot struct intel_instdone *instdone) 4761e12ee3bSFrançois Tigeot { 4771e12ee3bSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 4781e12ee3bSFrançois Tigeot u32 mmio_base = engine->mmio_base; 4791e12ee3bSFrançois Tigeot int slice; 4801e12ee3bSFrançois Tigeot int subslice; 4811e12ee3bSFrançois Tigeot 4821e12ee3bSFrançois Tigeot memset(instdone, 0, sizeof(*instdone)); 4831e12ee3bSFrançois Tigeot 4841e12ee3bSFrançois Tigeot switch (INTEL_GEN(dev_priv)) { 4851e12ee3bSFrançois Tigeot default: 4861e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 4871e12ee3bSFrançois Tigeot 4881e12ee3bSFrançois Tigeot if (engine->id != RCS) 4891e12ee3bSFrançois Tigeot break; 4901e12ee3bSFrançois Tigeot 4911e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); 4921e12ee3bSFrançois Tigeot for_each_instdone_slice_subslice(dev_priv, slice, subslice) { 4931e12ee3bSFrançois Tigeot instdone->sampler[slice][subslice] = 4941e12ee3bSFrançois Tigeot read_subslice_reg(dev_priv, slice, subslice, 4951e12ee3bSFrançois Tigeot GEN7_SAMPLER_INSTDONE); 4961e12ee3bSFrançois Tigeot instdone->row[slice][subslice] = 4971e12ee3bSFrançois Tigeot read_subslice_reg(dev_priv, slice, subslice, 4981e12ee3bSFrançois Tigeot GEN7_ROW_INSTDONE); 4991e12ee3bSFrançois Tigeot } 5001e12ee3bSFrançois Tigeot break; 5011e12ee3bSFrançois Tigeot case 7: 5021e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 5031e12ee3bSFrançois Tigeot 5041e12ee3bSFrançois Tigeot if (engine->id != RCS) 5051e12ee3bSFrançois Tigeot break; 5061e12ee3bSFrançois Tigeot 5071e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); 5081e12ee3bSFrançois Tigeot instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); 5091e12ee3bSFrançois Tigeot instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); 5101e12ee3bSFrançois Tigeot 5111e12ee3bSFrançois Tigeot break; 5121e12ee3bSFrançois Tigeot case 6: 5131e12ee3bSFrançois Tigeot case 5: 5141e12ee3bSFrançois Tigeot case 4: 5151e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); 5161e12ee3bSFrançois Tigeot 5171e12ee3bSFrançois Tigeot if (engine->id == RCS) 5181e12ee3bSFrançois Tigeot /* HACK: Using the wrong struct member */ 5191e12ee3bSFrançois Tigeot instdone->slice_common = I915_READ(GEN4_INSTDONE1); 5201e12ee3bSFrançois Tigeot break; 5211e12ee3bSFrançois Tigeot case 3: 5221e12ee3bSFrançois Tigeot case 2: 5231e12ee3bSFrançois Tigeot instdone->instdone = I915_READ(GEN2_INSTDONE); 5241e12ee3bSFrançois Tigeot break; 5251e12ee3bSFrançois Tigeot } 5261e12ee3bSFrançois Tigeot } 527*a85cb24fSFrançois Tigeot 528*a85cb24fSFrançois Tigeot static int wa_add(struct drm_i915_private *dev_priv, 529*a85cb24fSFrançois Tigeot i915_reg_t addr, 530*a85cb24fSFrançois Tigeot const u32 mask, const u32 val) 531*a85cb24fSFrançois Tigeot { 532*a85cb24fSFrançois Tigeot const u32 idx = dev_priv->workarounds.count; 533*a85cb24fSFrançois Tigeot 534*a85cb24fSFrançois Tigeot if (WARN_ON(idx >= I915_MAX_WA_REGS)) 535*a85cb24fSFrançois Tigeot return -ENOSPC; 536*a85cb24fSFrançois Tigeot 537*a85cb24fSFrançois Tigeot dev_priv->workarounds.reg[idx].addr = addr; 538*a85cb24fSFrançois Tigeot dev_priv->workarounds.reg[idx].value = val; 539*a85cb24fSFrançois Tigeot dev_priv->workarounds.reg[idx].mask = mask; 540*a85cb24fSFrançois Tigeot 541*a85cb24fSFrançois Tigeot dev_priv->workarounds.count++; 542*a85cb24fSFrançois Tigeot 543*a85cb24fSFrançois Tigeot return 0; 544*a85cb24fSFrançois Tigeot } 545*a85cb24fSFrançois Tigeot 546*a85cb24fSFrançois Tigeot #define WA_REG(addr, mask, val) do { \ 547*a85cb24fSFrançois Tigeot const int r = wa_add(dev_priv, (addr), (mask), (val)); \ 548*a85cb24fSFrançois Tigeot if (r) \ 549*a85cb24fSFrançois Tigeot return r; \ 550*a85cb24fSFrançois Tigeot } while (0) 551*a85cb24fSFrançois Tigeot 552*a85cb24fSFrançois Tigeot #define WA_SET_BIT_MASKED(addr, mask) \ 553*a85cb24fSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_ENABLE(mask)) 554*a85cb24fSFrançois Tigeot 555*a85cb24fSFrançois Tigeot #define WA_CLR_BIT_MASKED(addr, mask) \ 556*a85cb24fSFrançois Tigeot WA_REG(addr, (mask), _MASKED_BIT_DISABLE(mask)) 557*a85cb24fSFrançois Tigeot 558*a85cb24fSFrançois Tigeot #define WA_SET_FIELD_MASKED(addr, mask, value) \ 559*a85cb24fSFrançois Tigeot WA_REG(addr, mask, _MASKED_FIELD(mask, value)) 560*a85cb24fSFrançois Tigeot 561*a85cb24fSFrançois Tigeot #define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) 562*a85cb24fSFrançois Tigeot #define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) 563*a85cb24fSFrançois Tigeot 564*a85cb24fSFrançois Tigeot #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) 565*a85cb24fSFrançois Tigeot 566*a85cb24fSFrançois Tigeot static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, 567*a85cb24fSFrançois Tigeot i915_reg_t reg) 568*a85cb24fSFrançois Tigeot { 569*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 570*a85cb24fSFrançois Tigeot struct i915_workarounds *wa = &dev_priv->workarounds; 571*a85cb24fSFrançois Tigeot const uint32_t index = wa->hw_whitelist_count[engine->id]; 572*a85cb24fSFrançois Tigeot 573*a85cb24fSFrançois Tigeot if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) 574*a85cb24fSFrançois Tigeot return -EINVAL; 575*a85cb24fSFrançois Tigeot 576*a85cb24fSFrançois Tigeot WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), 577*a85cb24fSFrançois Tigeot i915_mmio_reg_offset(reg)); 578*a85cb24fSFrançois Tigeot wa->hw_whitelist_count[engine->id]++; 579*a85cb24fSFrançois Tigeot 580*a85cb24fSFrançois Tigeot return 0; 581*a85cb24fSFrançois Tigeot } 582*a85cb24fSFrançois Tigeot 583*a85cb24fSFrançois Tigeot static int gen8_init_workarounds(struct intel_engine_cs *engine) 584*a85cb24fSFrançois Tigeot { 585*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 586*a85cb24fSFrançois Tigeot 587*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(INSTPM, INSTPM_FORCE_ORDERING); 588*a85cb24fSFrançois Tigeot 589*a85cb24fSFrançois Tigeot /* WaDisableAsyncFlipPerfMode:bdw,chv */ 590*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(MI_MODE, ASYNC_FLIP_PERF_DISABLE); 591*a85cb24fSFrançois Tigeot 592*a85cb24fSFrançois Tigeot /* WaDisablePartialInstShootdown:bdw,chv */ 593*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 594*a85cb24fSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 595*a85cb24fSFrançois Tigeot 596*a85cb24fSFrançois Tigeot /* Use Force Non-Coherent whenever executing a 3D context. This is a 597*a85cb24fSFrançois Tigeot * workaround for for a possible hang in the unlikely event a TLB 598*a85cb24fSFrançois Tigeot * invalidation occurs during a PSD flush. 599*a85cb24fSFrançois Tigeot */ 600*a85cb24fSFrançois Tigeot /* WaForceEnableNonCoherent:bdw,chv */ 601*a85cb24fSFrançois Tigeot /* WaHdcDisableFetchWhenMasked:bdw,chv */ 602*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 603*a85cb24fSFrançois Tigeot HDC_DONOT_FETCH_MEM_WHEN_MASKED | 604*a85cb24fSFrançois Tigeot HDC_FORCE_NON_COHERENT); 605*a85cb24fSFrançois Tigeot 606*a85cb24fSFrançois Tigeot /* From the Haswell PRM, Command Reference: Registers, CACHE_MODE_0: 607*a85cb24fSFrançois Tigeot * "The Hierarchical Z RAW Stall Optimization allows non-overlapping 608*a85cb24fSFrançois Tigeot * polygons in the same 8x4 pixel/sample area to be processed without 609*a85cb24fSFrançois Tigeot * stalling waiting for the earlier ones to write to Hierarchical Z 610*a85cb24fSFrançois Tigeot * buffer." 611*a85cb24fSFrançois Tigeot * 612*a85cb24fSFrançois Tigeot * This optimization is off by default for BDW and CHV; turn it on. 613*a85cb24fSFrançois Tigeot */ 614*a85cb24fSFrançois Tigeot WA_CLR_BIT_MASKED(CACHE_MODE_0_GEN7, HIZ_RAW_STALL_OPT_DISABLE); 615*a85cb24fSFrançois Tigeot 616*a85cb24fSFrançois Tigeot /* Wa4x4STCOptimizationDisable:bdw,chv */ 617*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, GEN8_4x4_STC_OPTIMIZATION_DISABLE); 618*a85cb24fSFrançois Tigeot 619*a85cb24fSFrançois Tigeot /* 620*a85cb24fSFrançois Tigeot * BSpec recommends 8x4 when MSAA is used, 621*a85cb24fSFrançois Tigeot * however in practice 16x4 seems fastest. 622*a85cb24fSFrançois Tigeot * 623*a85cb24fSFrançois Tigeot * Note that PS/WM thread counts depend on the WIZ hashing 624*a85cb24fSFrançois Tigeot * disable bit, which we don't touch here, but it's good 625*a85cb24fSFrançois Tigeot * to keep in mind (see 3DSTATE_PS and 3DSTATE_WM). 626*a85cb24fSFrançois Tigeot */ 627*a85cb24fSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 628*a85cb24fSFrançois Tigeot GEN6_WIZ_HASHING_MASK, 629*a85cb24fSFrançois Tigeot GEN6_WIZ_HASHING_16x4); 630*a85cb24fSFrançois Tigeot 631*a85cb24fSFrançois Tigeot return 0; 632*a85cb24fSFrançois Tigeot } 633*a85cb24fSFrançois Tigeot 634*a85cb24fSFrançois Tigeot static int bdw_init_workarounds(struct intel_engine_cs *engine) 635*a85cb24fSFrançois Tigeot { 636*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 637*a85cb24fSFrançois Tigeot int ret; 638*a85cb24fSFrançois Tigeot 639*a85cb24fSFrançois Tigeot ret = gen8_init_workarounds(engine); 640*a85cb24fSFrançois Tigeot if (ret) 641*a85cb24fSFrançois Tigeot return ret; 642*a85cb24fSFrançois Tigeot 643*a85cb24fSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bdw (pre-production) */ 644*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 645*a85cb24fSFrançois Tigeot 646*a85cb24fSFrançois Tigeot /* WaDisableDopClockGating:bdw 647*a85cb24fSFrançois Tigeot * 648*a85cb24fSFrançois Tigeot * Also see the related UCGTCL1 write in broadwell_init_clock_gating() 649*a85cb24fSFrançois Tigeot * to disable EUTC clock gating. 650*a85cb24fSFrançois Tigeot */ 651*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, 652*a85cb24fSFrançois Tigeot DOP_CLOCK_GATING_DISABLE); 653*a85cb24fSFrançois Tigeot 654*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 655*a85cb24fSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 656*a85cb24fSFrançois Tigeot 657*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 658*a85cb24fSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:bdw */ 659*a85cb24fSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 660*a85cb24fSFrançois Tigeot /* WaDisableFenceDestinationToSLM:bdw (pre-prod) */ 661*a85cb24fSFrançois Tigeot (IS_BDW_GT3(dev_priv) ? HDC_FENCE_DEST_SLM_DISABLE : 0)); 662*a85cb24fSFrançois Tigeot 663*a85cb24fSFrançois Tigeot return 0; 664*a85cb24fSFrançois Tigeot } 665*a85cb24fSFrançois Tigeot 666*a85cb24fSFrançois Tigeot static int chv_init_workarounds(struct intel_engine_cs *engine) 667*a85cb24fSFrançois Tigeot { 668*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 669*a85cb24fSFrançois Tigeot int ret; 670*a85cb24fSFrançois Tigeot 671*a85cb24fSFrançois Tigeot ret = gen8_init_workarounds(engine); 672*a85cb24fSFrançois Tigeot if (ret) 673*a85cb24fSFrançois Tigeot return ret; 674*a85cb24fSFrançois Tigeot 675*a85cb24fSFrançois Tigeot /* WaDisableThreadStallDopClockGating:chv */ 676*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE); 677*a85cb24fSFrançois Tigeot 678*a85cb24fSFrançois Tigeot /* Improve HiZ throughput on CHV. */ 679*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X); 680*a85cb24fSFrançois Tigeot 681*a85cb24fSFrançois Tigeot return 0; 682*a85cb24fSFrançois Tigeot } 683*a85cb24fSFrançois Tigeot 684*a85cb24fSFrançois Tigeot static int gen9_init_workarounds(struct intel_engine_cs *engine) 685*a85cb24fSFrançois Tigeot { 686*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 687*a85cb24fSFrançois Tigeot int ret; 688*a85cb24fSFrançois Tigeot 689*a85cb24fSFrançois Tigeot /* WaConextSwitchWithConcurrentTLBInvalidate:skl,bxt,kbl,glk */ 690*a85cb24fSFrançois Tigeot I915_WRITE(GEN9_CSFE_CHICKEN1_RCS, _MASKED_BIT_ENABLE(GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE)); 691*a85cb24fSFrançois Tigeot 692*a85cb24fSFrançois Tigeot /* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk */ 693*a85cb24fSFrançois Tigeot I915_WRITE(BDW_SCRATCH1, I915_READ(BDW_SCRATCH1) | 694*a85cb24fSFrançois Tigeot GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE); 695*a85cb24fSFrançois Tigeot 696*a85cb24fSFrançois Tigeot /* WaDisableKillLogic:bxt,skl,kbl */ 697*a85cb24fSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 698*a85cb24fSFrançois Tigeot ECOCHK_DIS_TLB); 699*a85cb24fSFrançois Tigeot 700*a85cb24fSFrançois Tigeot /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk */ 701*a85cb24fSFrançois Tigeot /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk */ 702*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 703*a85cb24fSFrançois Tigeot FLOW_CONTROL_ENABLE | 704*a85cb24fSFrançois Tigeot PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE); 705*a85cb24fSFrançois Tigeot 706*a85cb24fSFrançois Tigeot /* Syncing dependencies between camera and graphics:skl,bxt,kbl */ 707*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 708*a85cb24fSFrançois Tigeot GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); 709*a85cb24fSFrançois Tigeot 710*a85cb24fSFrançois Tigeot /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */ 711*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 712*a85cb24fSFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 713*a85cb24fSFrançois Tigeot GEN9_DG_MIRROR_FIX_ENABLE); 714*a85cb24fSFrançois Tigeot 715*a85cb24fSFrançois Tigeot /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ 716*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 717*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, 718*a85cb24fSFrançois Tigeot GEN9_RHWO_OPTIMIZATION_DISABLE); 719*a85cb24fSFrançois Tigeot /* 720*a85cb24fSFrançois Tigeot * WA also requires GEN9_SLICE_COMMON_ECO_CHICKEN0[14:14] to be set 721*a85cb24fSFrançois Tigeot * but we do that in per ctx batchbuffer as there is an issue 722*a85cb24fSFrançois Tigeot * with this register not getting restored on ctx restore 723*a85cb24fSFrançois Tigeot */ 724*a85cb24fSFrançois Tigeot } 725*a85cb24fSFrançois Tigeot 726*a85cb24fSFrançois Tigeot /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ 727*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, 728*a85cb24fSFrançois Tigeot GEN9_ENABLE_GPGPU_PREEMPTION); 729*a85cb24fSFrançois Tigeot 730*a85cb24fSFrançois Tigeot /* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk */ 731*a85cb24fSFrançois Tigeot /* WaDisablePartialResolveInVc:skl,bxt,kbl */ 732*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(CACHE_MODE_1, (GEN8_4x4_STC_OPTIMIZATION_DISABLE | 733*a85cb24fSFrançois Tigeot GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE)); 734*a85cb24fSFrançois Tigeot 735*a85cb24fSFrançois Tigeot /* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk */ 736*a85cb24fSFrançois Tigeot WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, 737*a85cb24fSFrançois Tigeot GEN9_CCS_TLB_PREFETCH_ENABLE); 738*a85cb24fSFrançois Tigeot 739*a85cb24fSFrançois Tigeot /* WaDisableMaskBasedCammingInRCC:bxt */ 740*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 741*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, 742*a85cb24fSFrançois Tigeot PIXEL_MASK_CAMMING_DISABLE); 743*a85cb24fSFrançois Tigeot 744*a85cb24fSFrançois Tigeot /* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl */ 745*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 746*a85cb24fSFrançois Tigeot HDC_FORCE_CONTEXT_SAVE_RESTORE_NON_COHERENT | 747*a85cb24fSFrançois Tigeot HDC_FORCE_CSR_NON_COHERENT_OVR_DISABLE); 748*a85cb24fSFrançois Tigeot 749*a85cb24fSFrançois Tigeot /* WaForceEnableNonCoherent and WaDisableHDCInvalidation are 750*a85cb24fSFrançois Tigeot * both tied to WaForceContextSaveRestoreNonCoherent 751*a85cb24fSFrançois Tigeot * in some hsds for skl. We keep the tie for all gen9. The 752*a85cb24fSFrançois Tigeot * documentation is a bit hazy and so we want to get common behaviour, 753*a85cb24fSFrançois Tigeot * even though there is no clear evidence we would need both on kbl/bxt. 754*a85cb24fSFrançois Tigeot * This area has been source of system hangs so we play it safe 755*a85cb24fSFrançois Tigeot * and mimic the skl regardless of what bspec says. 756*a85cb24fSFrançois Tigeot * 757*a85cb24fSFrançois Tigeot * Use Force Non-Coherent whenever executing a 3D context. This 758*a85cb24fSFrançois Tigeot * is a workaround for a possible hang in the unlikely event 759*a85cb24fSFrançois Tigeot * a TLB invalidation occurs during a PSD flush. 760*a85cb24fSFrançois Tigeot */ 761*a85cb24fSFrançois Tigeot 762*a85cb24fSFrançois Tigeot /* WaForceEnableNonCoherent:skl,bxt,kbl */ 763*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 764*a85cb24fSFrançois Tigeot HDC_FORCE_NON_COHERENT); 765*a85cb24fSFrançois Tigeot 766*a85cb24fSFrançois Tigeot /* WaDisableHDCInvalidation:skl,bxt,kbl */ 767*a85cb24fSFrançois Tigeot I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | 768*a85cb24fSFrançois Tigeot BDW_DISABLE_HDC_INVALIDATION); 769*a85cb24fSFrançois Tigeot 770*a85cb24fSFrançois Tigeot /* WaDisableSamplerPowerBypassForSOPingPong:skl,bxt,kbl */ 771*a85cb24fSFrançois Tigeot if (IS_SKYLAKE(dev_priv) || 772*a85cb24fSFrançois Tigeot IS_KABYLAKE(dev_priv) || 773*a85cb24fSFrançois Tigeot IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) 774*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, 775*a85cb24fSFrançois Tigeot GEN8_SAMPLER_POWER_BYPASS_DIS); 776*a85cb24fSFrançois Tigeot 777*a85cb24fSFrançois Tigeot /* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk */ 778*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE); 779*a85cb24fSFrançois Tigeot 780*a85cb24fSFrançois Tigeot /* WaOCLCoherentLineFlush:skl,bxt,kbl */ 781*a85cb24fSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | 782*a85cb24fSFrançois Tigeot GEN8_LQSC_FLUSH_COHERENT_LINES)); 783*a85cb24fSFrançois Tigeot 784*a85cb24fSFrançois Tigeot /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk */ 785*a85cb24fSFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); 786*a85cb24fSFrançois Tigeot if (ret) 787*a85cb24fSFrançois Tigeot return ret; 788*a85cb24fSFrançois Tigeot 789*a85cb24fSFrançois Tigeot /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl */ 790*a85cb24fSFrançois Tigeot ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); 791*a85cb24fSFrançois Tigeot if (ret) 792*a85cb24fSFrançois Tigeot return ret; 793*a85cb24fSFrançois Tigeot 794*a85cb24fSFrançois Tigeot /* WaAllowUMDToModifyHDCChicken1:skl,bxt,kbl,glk */ 795*a85cb24fSFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_HDC_CHICKEN1); 796*a85cb24fSFrançois Tigeot if (ret) 797*a85cb24fSFrançois Tigeot return ret; 798*a85cb24fSFrançois Tigeot 799*a85cb24fSFrançois Tigeot return 0; 800*a85cb24fSFrançois Tigeot } 801*a85cb24fSFrançois Tigeot 802*a85cb24fSFrançois Tigeot static int skl_tune_iz_hashing(struct intel_engine_cs *engine) 803*a85cb24fSFrançois Tigeot { 804*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 805*a85cb24fSFrançois Tigeot u8 vals[3] = { 0, 0, 0 }; 806*a85cb24fSFrançois Tigeot unsigned int i; 807*a85cb24fSFrançois Tigeot 808*a85cb24fSFrançois Tigeot for (i = 0; i < 3; i++) { 809*a85cb24fSFrançois Tigeot u8 ss; 810*a85cb24fSFrançois Tigeot 811*a85cb24fSFrançois Tigeot /* 812*a85cb24fSFrançois Tigeot * Only consider slices where one, and only one, subslice has 7 813*a85cb24fSFrançois Tigeot * EUs 814*a85cb24fSFrançois Tigeot */ 815*a85cb24fSFrançois Tigeot if (!is_power_of_2(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i])) 816*a85cb24fSFrançois Tigeot continue; 817*a85cb24fSFrançois Tigeot 818*a85cb24fSFrançois Tigeot /* 819*a85cb24fSFrançois Tigeot * subslice_7eu[i] != 0 (because of the check above) and 820*a85cb24fSFrançois Tigeot * ss_max == 4 (maximum number of subslices possible per slice) 821*a85cb24fSFrançois Tigeot * 822*a85cb24fSFrançois Tigeot * -> 0 <= ss <= 3; 823*a85cb24fSFrançois Tigeot */ 824*a85cb24fSFrançois Tigeot ss = ffs(INTEL_INFO(dev_priv)->sseu.subslice_7eu[i]) - 1; 825*a85cb24fSFrançois Tigeot vals[i] = 3 - ss; 826*a85cb24fSFrançois Tigeot } 827*a85cb24fSFrançois Tigeot 828*a85cb24fSFrançois Tigeot if (vals[0] == 0 && vals[1] == 0 && vals[2] == 0) 829*a85cb24fSFrançois Tigeot return 0; 830*a85cb24fSFrançois Tigeot 831*a85cb24fSFrançois Tigeot /* Tune IZ hashing. See intel_device_info_runtime_init() */ 832*a85cb24fSFrançois Tigeot WA_SET_FIELD_MASKED(GEN7_GT_MODE, 833*a85cb24fSFrançois Tigeot GEN9_IZ_HASHING_MASK(2) | 834*a85cb24fSFrançois Tigeot GEN9_IZ_HASHING_MASK(1) | 835*a85cb24fSFrançois Tigeot GEN9_IZ_HASHING_MASK(0), 836*a85cb24fSFrançois Tigeot GEN9_IZ_HASHING(2, vals[2]) | 837*a85cb24fSFrançois Tigeot GEN9_IZ_HASHING(1, vals[1]) | 838*a85cb24fSFrançois Tigeot GEN9_IZ_HASHING(0, vals[0])); 839*a85cb24fSFrançois Tigeot 840*a85cb24fSFrançois Tigeot return 0; 841*a85cb24fSFrançois Tigeot } 842*a85cb24fSFrançois Tigeot 843*a85cb24fSFrançois Tigeot static int skl_init_workarounds(struct intel_engine_cs *engine) 844*a85cb24fSFrançois Tigeot { 845*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 846*a85cb24fSFrançois Tigeot int ret; 847*a85cb24fSFrançois Tigeot 848*a85cb24fSFrançois Tigeot ret = gen9_init_workarounds(engine); 849*a85cb24fSFrançois Tigeot if (ret) 850*a85cb24fSFrançois Tigeot return ret; 851*a85cb24fSFrançois Tigeot 852*a85cb24fSFrançois Tigeot /* 853*a85cb24fSFrançois Tigeot * Actual WA is to disable percontext preemption granularity control 854*a85cb24fSFrançois Tigeot * until D0 which is the default case so this is equivalent to 855*a85cb24fSFrançois Tigeot * !WaDisablePerCtxtPreemptionGranularityControl:skl 856*a85cb24fSFrançois Tigeot */ 857*a85cb24fSFrançois Tigeot I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, 858*a85cb24fSFrançois Tigeot _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); 859*a85cb24fSFrançois Tigeot 860*a85cb24fSFrançois Tigeot /* WaEnableGapsTsvCreditFix:skl */ 861*a85cb24fSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 862*a85cb24fSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 863*a85cb24fSFrançois Tigeot 864*a85cb24fSFrançois Tigeot /* WaDisableGafsUnitClkGating:skl */ 865*a85cb24fSFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 866*a85cb24fSFrançois Tigeot 867*a85cb24fSFrançois Tigeot /* WaInPlaceDecompressionHang:skl */ 868*a85cb24fSFrançois Tigeot if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) 869*a85cb24fSFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 870*a85cb24fSFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 871*a85cb24fSFrançois Tigeot 872*a85cb24fSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:skl */ 873*a85cb24fSFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 874*a85cb24fSFrançois Tigeot if (ret) 875*a85cb24fSFrançois Tigeot return ret; 876*a85cb24fSFrançois Tigeot 877*a85cb24fSFrançois Tigeot return skl_tune_iz_hashing(engine); 878*a85cb24fSFrançois Tigeot } 879*a85cb24fSFrançois Tigeot 880*a85cb24fSFrançois Tigeot static int bxt_init_workarounds(struct intel_engine_cs *engine) 881*a85cb24fSFrançois Tigeot { 882*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 883*a85cb24fSFrançois Tigeot int ret; 884*a85cb24fSFrançois Tigeot 885*a85cb24fSFrançois Tigeot ret = gen9_init_workarounds(engine); 886*a85cb24fSFrançois Tigeot if (ret) 887*a85cb24fSFrançois Tigeot return ret; 888*a85cb24fSFrançois Tigeot 889*a85cb24fSFrançois Tigeot /* WaStoreMultiplePTEenable:bxt */ 890*a85cb24fSFrançois Tigeot /* This is a requirement according to Hardware specification */ 891*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) 892*a85cb24fSFrançois Tigeot I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_TLBPF); 893*a85cb24fSFrançois Tigeot 894*a85cb24fSFrançois Tigeot /* WaSetClckGatingDisableMedia:bxt */ 895*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 896*a85cb24fSFrançois Tigeot I915_WRITE(GEN7_MISCCPCTL, (I915_READ(GEN7_MISCCPCTL) & 897*a85cb24fSFrançois Tigeot ~GEN8_DOP_CLOCK_GATE_MEDIA_ENABLE)); 898*a85cb24fSFrançois Tigeot } 899*a85cb24fSFrançois Tigeot 900*a85cb24fSFrançois Tigeot /* WaDisableThreadStallDopClockGating:bxt */ 901*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, 902*a85cb24fSFrançois Tigeot STALL_DOP_GATING_DISABLE); 903*a85cb24fSFrançois Tigeot 904*a85cb24fSFrançois Tigeot /* WaDisablePooledEuLoadBalancingFix:bxt */ 905*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { 906*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, 907*a85cb24fSFrançois Tigeot GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); 908*a85cb24fSFrançois Tigeot } 909*a85cb24fSFrançois Tigeot 910*a85cb24fSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:bxt */ 911*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) { 912*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED( 913*a85cb24fSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 914*a85cb24fSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 915*a85cb24fSFrançois Tigeot } 916*a85cb24fSFrançois Tigeot 917*a85cb24fSFrançois Tigeot /* WaDisableObjectLevelPreemptionForTrifanOrPolygon:bxt */ 918*a85cb24fSFrançois Tigeot /* WaDisableObjectLevelPreemptionForInstancedDraw:bxt */ 919*a85cb24fSFrançois Tigeot /* WaDisableObjectLevelPreemtionForInstanceId:bxt */ 920*a85cb24fSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:bxt */ 921*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { 922*a85cb24fSFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN9_CS_DEBUG_MODE1); 923*a85cb24fSFrançois Tigeot if (ret) 924*a85cb24fSFrançois Tigeot return ret; 925*a85cb24fSFrançois Tigeot 926*a85cb24fSFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 927*a85cb24fSFrançois Tigeot if (ret) 928*a85cb24fSFrançois Tigeot return ret; 929*a85cb24fSFrançois Tigeot } 930*a85cb24fSFrançois Tigeot 931*a85cb24fSFrançois Tigeot /* WaProgramL3SqcReg1DefaultForPerf:bxt */ 932*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) 933*a85cb24fSFrançois Tigeot I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | 934*a85cb24fSFrançois Tigeot L3_HIGH_PRIO_CREDITS(2)); 935*a85cb24fSFrançois Tigeot 936*a85cb24fSFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:bxt */ 937*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 938*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 939*a85cb24fSFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 940*a85cb24fSFrançois Tigeot 941*a85cb24fSFrançois Tigeot /* WaInPlaceDecompressionHang:bxt */ 942*a85cb24fSFrançois Tigeot if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) 943*a85cb24fSFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 944*a85cb24fSFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 945*a85cb24fSFrançois Tigeot 946*a85cb24fSFrançois Tigeot return 0; 947*a85cb24fSFrançois Tigeot } 948*a85cb24fSFrançois Tigeot 949*a85cb24fSFrançois Tigeot static int kbl_init_workarounds(struct intel_engine_cs *engine) 950*a85cb24fSFrançois Tigeot { 951*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 952*a85cb24fSFrançois Tigeot int ret; 953*a85cb24fSFrançois Tigeot 954*a85cb24fSFrançois Tigeot ret = gen9_init_workarounds(engine); 955*a85cb24fSFrançois Tigeot if (ret) 956*a85cb24fSFrançois Tigeot return ret; 957*a85cb24fSFrançois Tigeot 958*a85cb24fSFrançois Tigeot /* WaEnableGapsTsvCreditFix:kbl */ 959*a85cb24fSFrançois Tigeot I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | 960*a85cb24fSFrançois Tigeot GEN9_GAPS_TSV_CREDIT_DISABLE)); 961*a85cb24fSFrançois Tigeot 962*a85cb24fSFrançois Tigeot /* WaDisableDynamicCreditSharing:kbl */ 963*a85cb24fSFrançois Tigeot if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) 964*a85cb24fSFrançois Tigeot WA_SET_BIT(GAMT_CHKN_BIT_REG, 965*a85cb24fSFrançois Tigeot GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); 966*a85cb24fSFrançois Tigeot 967*a85cb24fSFrançois Tigeot /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ 968*a85cb24fSFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) 969*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(HDC_CHICKEN0, 970*a85cb24fSFrançois Tigeot HDC_FENCE_DEST_SLM_DISABLE); 971*a85cb24fSFrançois Tigeot 972*a85cb24fSFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:kbl */ 973*a85cb24fSFrançois Tigeot if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER)) 974*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 975*a85cb24fSFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 976*a85cb24fSFrançois Tigeot 977*a85cb24fSFrançois Tigeot /* WaDisableGafsUnitClkGating:kbl */ 978*a85cb24fSFrançois Tigeot WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); 979*a85cb24fSFrançois Tigeot 980*a85cb24fSFrançois Tigeot /* WaDisableSbeCacheDispatchPortSharing:kbl */ 981*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED( 982*a85cb24fSFrançois Tigeot GEN7_HALF_SLICE_CHICKEN1, 983*a85cb24fSFrançois Tigeot GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); 984*a85cb24fSFrançois Tigeot 985*a85cb24fSFrançois Tigeot /* WaInPlaceDecompressionHang:kbl */ 986*a85cb24fSFrançois Tigeot WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, 987*a85cb24fSFrançois Tigeot GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); 988*a85cb24fSFrançois Tigeot 989*a85cb24fSFrançois Tigeot /* WaDisableLSQCROPERFforOCL:kbl */ 990*a85cb24fSFrançois Tigeot ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); 991*a85cb24fSFrançois Tigeot if (ret) 992*a85cb24fSFrançois Tigeot return ret; 993*a85cb24fSFrançois Tigeot 994*a85cb24fSFrançois Tigeot return 0; 995*a85cb24fSFrançois Tigeot } 996*a85cb24fSFrançois Tigeot 997*a85cb24fSFrançois Tigeot static int glk_init_workarounds(struct intel_engine_cs *engine) 998*a85cb24fSFrançois Tigeot { 999*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1000*a85cb24fSFrançois Tigeot int ret; 1001*a85cb24fSFrançois Tigeot 1002*a85cb24fSFrançois Tigeot ret = gen9_init_workarounds(engine); 1003*a85cb24fSFrançois Tigeot if (ret) 1004*a85cb24fSFrançois Tigeot return ret; 1005*a85cb24fSFrançois Tigeot 1006*a85cb24fSFrançois Tigeot /* WaToEnableHwFixForPushConstHWBug:glk */ 1007*a85cb24fSFrançois Tigeot WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, 1008*a85cb24fSFrançois Tigeot GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); 1009*a85cb24fSFrançois Tigeot 1010*a85cb24fSFrançois Tigeot return 0; 1011*a85cb24fSFrançois Tigeot } 1012*a85cb24fSFrançois Tigeot 1013*a85cb24fSFrançois Tigeot int init_workarounds_ring(struct intel_engine_cs *engine) 1014*a85cb24fSFrançois Tigeot { 1015*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1016*a85cb24fSFrançois Tigeot int err; 1017*a85cb24fSFrançois Tigeot 1018*a85cb24fSFrançois Tigeot WARN_ON(engine->id != RCS); 1019*a85cb24fSFrançois Tigeot 1020*a85cb24fSFrançois Tigeot dev_priv->workarounds.count = 0; 1021*a85cb24fSFrançois Tigeot dev_priv->workarounds.hw_whitelist_count[engine->id] = 0; 1022*a85cb24fSFrançois Tigeot 1023*a85cb24fSFrançois Tigeot if (IS_BROADWELL(dev_priv)) 1024*a85cb24fSFrançois Tigeot err = bdw_init_workarounds(engine); 1025*a85cb24fSFrançois Tigeot else if (IS_CHERRYVIEW(dev_priv)) 1026*a85cb24fSFrançois Tigeot err = chv_init_workarounds(engine); 1027*a85cb24fSFrançois Tigeot else if (IS_SKYLAKE(dev_priv)) 1028*a85cb24fSFrançois Tigeot err = skl_init_workarounds(engine); 1029*a85cb24fSFrançois Tigeot else if (IS_BROXTON(dev_priv)) 1030*a85cb24fSFrançois Tigeot err = bxt_init_workarounds(engine); 1031*a85cb24fSFrançois Tigeot else if (IS_KABYLAKE(dev_priv)) 1032*a85cb24fSFrançois Tigeot err = kbl_init_workarounds(engine); 1033*a85cb24fSFrançois Tigeot else if (IS_GEMINILAKE(dev_priv)) 1034*a85cb24fSFrançois Tigeot err = glk_init_workarounds(engine); 1035*a85cb24fSFrançois Tigeot else 1036*a85cb24fSFrançois Tigeot err = 0; 1037*a85cb24fSFrançois Tigeot if (err) 1038*a85cb24fSFrançois Tigeot return err; 1039*a85cb24fSFrançois Tigeot 1040*a85cb24fSFrançois Tigeot DRM_DEBUG_DRIVER("%s: Number of context specific w/a: %d\n", 1041*a85cb24fSFrançois Tigeot engine->name, dev_priv->workarounds.count); 1042*a85cb24fSFrançois Tigeot return 0; 1043*a85cb24fSFrançois Tigeot } 1044*a85cb24fSFrançois Tigeot 1045*a85cb24fSFrançois Tigeot int intel_ring_workarounds_emit(struct drm_i915_gem_request *req) 1046*a85cb24fSFrançois Tigeot { 1047*a85cb24fSFrançois Tigeot struct i915_workarounds *w = &req->i915->workarounds; 1048*a85cb24fSFrançois Tigeot u32 *cs; 1049*a85cb24fSFrançois Tigeot int ret, i; 1050*a85cb24fSFrançois Tigeot 1051*a85cb24fSFrançois Tigeot if (w->count == 0) 1052*a85cb24fSFrançois Tigeot return 0; 1053*a85cb24fSFrançois Tigeot 1054*a85cb24fSFrançois Tigeot ret = req->engine->emit_flush(req, EMIT_BARRIER); 1055*a85cb24fSFrançois Tigeot if (ret) 1056*a85cb24fSFrançois Tigeot return ret; 1057*a85cb24fSFrançois Tigeot 1058*a85cb24fSFrançois Tigeot cs = intel_ring_begin(req, (w->count * 2 + 2)); 1059*a85cb24fSFrançois Tigeot if (IS_ERR(cs)) 1060*a85cb24fSFrançois Tigeot return PTR_ERR(cs); 1061*a85cb24fSFrançois Tigeot 1062*a85cb24fSFrançois Tigeot *cs++ = MI_LOAD_REGISTER_IMM(w->count); 1063*a85cb24fSFrançois Tigeot for (i = 0; i < w->count; i++) { 1064*a85cb24fSFrançois Tigeot *cs++ = i915_mmio_reg_offset(w->reg[i].addr); 1065*a85cb24fSFrançois Tigeot *cs++ = w->reg[i].value; 1066*a85cb24fSFrançois Tigeot } 1067*a85cb24fSFrançois Tigeot *cs++ = MI_NOOP; 1068*a85cb24fSFrançois Tigeot 1069*a85cb24fSFrançois Tigeot intel_ring_advance(req, cs); 1070*a85cb24fSFrançois Tigeot 1071*a85cb24fSFrançois Tigeot ret = req->engine->emit_flush(req, EMIT_BARRIER); 1072*a85cb24fSFrançois Tigeot if (ret) 1073*a85cb24fSFrançois Tigeot return ret; 1074*a85cb24fSFrançois Tigeot 1075*a85cb24fSFrançois Tigeot return 0; 1076*a85cb24fSFrançois Tigeot } 1077*a85cb24fSFrançois Tigeot 1078*a85cb24fSFrançois Tigeot static bool ring_is_idle(struct intel_engine_cs *engine) 1079*a85cb24fSFrançois Tigeot { 1080*a85cb24fSFrançois Tigeot struct drm_i915_private *dev_priv = engine->i915; 1081*a85cb24fSFrançois Tigeot bool idle = true; 1082*a85cb24fSFrançois Tigeot 1083*a85cb24fSFrançois Tigeot intel_runtime_pm_get(dev_priv); 1084*a85cb24fSFrançois Tigeot 1085*a85cb24fSFrançois Tigeot /* No bit for gen2, so assume the CS parser is idle */ 1086*a85cb24fSFrançois Tigeot if (INTEL_GEN(dev_priv) > 2 && !(I915_READ_MODE(engine) & MODE_IDLE)) 1087*a85cb24fSFrançois Tigeot idle = false; 1088*a85cb24fSFrançois Tigeot 1089*a85cb24fSFrançois Tigeot intel_runtime_pm_put(dev_priv); 1090*a85cb24fSFrançois Tigeot 1091*a85cb24fSFrançois Tigeot return idle; 1092*a85cb24fSFrançois Tigeot } 1093*a85cb24fSFrançois Tigeot 1094*a85cb24fSFrançois Tigeot /** 1095*a85cb24fSFrançois Tigeot * intel_engine_is_idle() - Report if the engine has finished process all work 1096*a85cb24fSFrançois Tigeot * @engine: the intel_engine_cs 1097*a85cb24fSFrançois Tigeot * 1098*a85cb24fSFrançois Tigeot * Return true if there are no requests pending, nothing left to be submitted 1099*a85cb24fSFrançois Tigeot * to hardware, and that the engine is idle. 1100*a85cb24fSFrançois Tigeot */ 1101*a85cb24fSFrançois Tigeot bool intel_engine_is_idle(struct intel_engine_cs *engine) 1102*a85cb24fSFrançois Tigeot { 1103*a85cb24fSFrançois Tigeot /* Any inflight/incomplete requests? */ 1104*a85cb24fSFrançois Tigeot if (!i915_seqno_passed(intel_engine_get_seqno(engine), 1105*a85cb24fSFrançois Tigeot intel_engine_last_submit(engine))) 1106*a85cb24fSFrançois Tigeot return false; 1107*a85cb24fSFrançois Tigeot 1108*a85cb24fSFrançois Tigeot /* Interrupt/tasklet pending? */ 1109*a85cb24fSFrançois Tigeot if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) 1110*a85cb24fSFrançois Tigeot return false; 1111*a85cb24fSFrançois Tigeot 1112*a85cb24fSFrançois Tigeot /* Both ports drained, no more ELSP submission? */ 1113*a85cb24fSFrançois Tigeot if (engine->execlist_port[0].request) 1114*a85cb24fSFrançois Tigeot return false; 1115*a85cb24fSFrançois Tigeot 1116*a85cb24fSFrançois Tigeot /* Ring stopped? */ 1117*a85cb24fSFrançois Tigeot if (!ring_is_idle(engine)) 1118*a85cb24fSFrançois Tigeot return false; 1119*a85cb24fSFrançois Tigeot 1120*a85cb24fSFrançois Tigeot return true; 1121*a85cb24fSFrançois Tigeot } 1122*a85cb24fSFrançois Tigeot 1123*a85cb24fSFrançois Tigeot bool intel_engines_are_idle(struct drm_i915_private *dev_priv) 1124*a85cb24fSFrançois Tigeot { 1125*a85cb24fSFrançois Tigeot struct intel_engine_cs *engine; 1126*a85cb24fSFrançois Tigeot enum intel_engine_id id; 1127*a85cb24fSFrançois Tigeot 1128*a85cb24fSFrançois Tigeot if (READ_ONCE(dev_priv->gt.active_requests)) 1129*a85cb24fSFrançois Tigeot return false; 1130*a85cb24fSFrançois Tigeot 1131*a85cb24fSFrançois Tigeot /* If the driver is wedged, HW state may be very inconsistent and 1132*a85cb24fSFrançois Tigeot * report that it is still busy, even though we have stopped using it. 1133*a85cb24fSFrançois Tigeot */ 1134*a85cb24fSFrançois Tigeot if (i915_terminally_wedged(&dev_priv->gpu_error)) 1135*a85cb24fSFrançois Tigeot return true; 1136*a85cb24fSFrançois Tigeot 1137*a85cb24fSFrançois Tigeot for_each_engine(engine, dev_priv, id) { 1138*a85cb24fSFrançois Tigeot if (!intel_engine_is_idle(engine)) 1139*a85cb24fSFrançois Tigeot return false; 1140*a85cb24fSFrançois Tigeot } 1141*a85cb24fSFrançois Tigeot 1142*a85cb24fSFrançois Tigeot return true; 1143*a85cb24fSFrançois Tigeot } 1144*a85cb24fSFrançois Tigeot 1145*a85cb24fSFrançois Tigeot void intel_engines_reset_default_submission(struct drm_i915_private *i915) 1146*a85cb24fSFrançois Tigeot { 1147*a85cb24fSFrançois Tigeot struct intel_engine_cs *engine; 1148*a85cb24fSFrançois Tigeot enum intel_engine_id id; 1149*a85cb24fSFrançois Tigeot 1150*a85cb24fSFrançois Tigeot for_each_engine(engine, i915, id) 1151*a85cb24fSFrançois Tigeot engine->set_default_submission(engine); 1152*a85cb24fSFrançois Tigeot } 1153*a85cb24fSFrançois Tigeot 1154*a85cb24fSFrançois Tigeot #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 1155*a85cb24fSFrançois Tigeot #include "selftests/mock_engine.c" 1156*a85cb24fSFrançois Tigeot #endif 1157