18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * SPDX-License-Identifier: MIT 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2019 Intel Corporation 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include "gem/i915_gem_object.h" 88c2ecf20Sopenharmony_ci#include "i915_drv.h" 98c2ecf20Sopenharmony_ci#include "i915_vma.h" 108c2ecf20Sopenharmony_ci#include "intel_engine.h" 118c2ecf20Sopenharmony_ci#include "intel_ring.h" 128c2ecf20Sopenharmony_ci#include "intel_timeline.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciunsigned int intel_ring_update_space(struct intel_ring *ring) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci unsigned int space; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci space = __intel_ring_space(ring->head, ring->emit, ring->size); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci ring->space = space; 218c2ecf20Sopenharmony_ci return space; 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_civoid __intel_ring_pin(struct intel_ring *ring) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci GEM_BUG_ON(!atomic_read(&ring->pin_count)); 278c2ecf20Sopenharmony_ci atomic_inc(&ring->pin_count); 288c2ecf20Sopenharmony_ci} 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciint intel_ring_pin(struct intel_ring *ring, struct i915_gem_ww_ctx *ww) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct i915_vma *vma = ring->vma; 338c2ecf20Sopenharmony_ci unsigned int flags; 348c2ecf20Sopenharmony_ci void *addr; 358c2ecf20Sopenharmony_ci int ret; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (atomic_fetch_inc(&ring->pin_count)) 388c2ecf20Sopenharmony_ci return 0; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ 418c2ecf20Sopenharmony_ci flags = PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if (vma->obj->stolen) 448c2ecf20Sopenharmony_ci flags |= PIN_MAPPABLE; 458c2ecf20Sopenharmony_ci else 468c2ecf20Sopenharmony_ci flags |= PIN_HIGH; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci ret = i915_ggtt_pin(vma, ww, 0, flags); 498c2ecf20Sopenharmony_ci if (unlikely(ret)) 508c2ecf20Sopenharmony_ci goto err_unpin; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (i915_vma_is_map_and_fenceable(vma) && !HAS_LLC(vma->vm->i915)) 538c2ecf20Sopenharmony_ci addr = (void __force *)i915_vma_pin_iomap(vma); 548c2ecf20Sopenharmony_ci else 558c2ecf20Sopenharmony_ci addr = i915_gem_object_pin_map(vma->obj, 568c2ecf20Sopenharmony_ci i915_coherent_map_type(vma->vm->i915)); 578c2ecf20Sopenharmony_ci if (IS_ERR(addr)) { 588c2ecf20Sopenharmony_ci ret = PTR_ERR(addr); 598c2ecf20Sopenharmony_ci goto err_ring; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci i915_vma_make_unshrinkable(vma); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci /* Discard any unused bytes beyond that submitted to hw. */ 658c2ecf20Sopenharmony_ci intel_ring_reset(ring, ring->emit); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci ring->vaddr = addr; 688c2ecf20Sopenharmony_ci return 0; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cierr_ring: 718c2ecf20Sopenharmony_ci i915_vma_unpin(vma); 728c2ecf20Sopenharmony_cierr_unpin: 738c2ecf20Sopenharmony_ci atomic_dec(&ring->pin_count); 748c2ecf20Sopenharmony_ci return ret; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_civoid intel_ring_reset(struct intel_ring *ring, u32 tail) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci tail = intel_ring_wrap(ring, tail); 808c2ecf20Sopenharmony_ci ring->tail = tail; 818c2ecf20Sopenharmony_ci ring->head = tail; 828c2ecf20Sopenharmony_ci ring->emit = tail; 838c2ecf20Sopenharmony_ci intel_ring_update_space(ring); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_civoid intel_ring_unpin(struct intel_ring *ring) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci struct i915_vma *vma = ring->vma; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (!atomic_dec_and_test(&ring->pin_count)) 918c2ecf20Sopenharmony_ci return; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci i915_vma_unset_ggtt_write(vma); 948c2ecf20Sopenharmony_ci if (i915_vma_is_map_and_fenceable(vma) && !HAS_LLC(vma->vm->i915)) 958c2ecf20Sopenharmony_ci i915_vma_unpin_iomap(vma); 968c2ecf20Sopenharmony_ci else 978c2ecf20Sopenharmony_ci i915_gem_object_unpin_map(vma->obj); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci i915_vma_make_purgeable(vma); 1008c2ecf20Sopenharmony_ci i915_vma_unpin(vma); 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic struct i915_vma *create_ring_vma(struct i915_ggtt *ggtt, int size) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct i915_address_space *vm = &ggtt->vm; 1068c2ecf20Sopenharmony_ci struct drm_i915_private *i915 = vm->i915; 1078c2ecf20Sopenharmony_ci struct drm_i915_gem_object *obj; 1088c2ecf20Sopenharmony_ci struct i915_vma *vma; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci obj = ERR_PTR(-ENODEV); 1118c2ecf20Sopenharmony_ci if (i915_ggtt_has_aperture(ggtt) && !HAS_LLC(i915)) 1128c2ecf20Sopenharmony_ci obj = i915_gem_object_create_stolen(i915, size); 1138c2ecf20Sopenharmony_ci if (IS_ERR(obj)) 1148c2ecf20Sopenharmony_ci obj = i915_gem_object_create_internal(i915, size); 1158c2ecf20Sopenharmony_ci if (IS_ERR(obj)) 1168c2ecf20Sopenharmony_ci return ERR_CAST(obj); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* 1198c2ecf20Sopenharmony_ci * Mark ring buffers as read-only from GPU side (so no stray overwrites) 1208c2ecf20Sopenharmony_ci * if supported by the platform's GGTT. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci if (vm->has_read_only) 1238c2ecf20Sopenharmony_ci i915_gem_object_set_readonly(obj); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci vma = i915_vma_instance(obj, vm, NULL); 1268c2ecf20Sopenharmony_ci if (IS_ERR(vma)) 1278c2ecf20Sopenharmony_ci goto err; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return vma; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cierr: 1328c2ecf20Sopenharmony_ci i915_gem_object_put(obj); 1338c2ecf20Sopenharmony_ci return vma; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistruct intel_ring * 1378c2ecf20Sopenharmony_ciintel_engine_create_ring(struct intel_engine_cs *engine, int size) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct drm_i915_private *i915 = engine->i915; 1408c2ecf20Sopenharmony_ci struct intel_ring *ring; 1418c2ecf20Sopenharmony_ci struct i915_vma *vma; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci GEM_BUG_ON(!is_power_of_2(size)); 1448c2ecf20Sopenharmony_ci GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci ring = kzalloc(sizeof(*ring), GFP_KERNEL); 1478c2ecf20Sopenharmony_ci if (!ring) 1488c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci kref_init(&ring->ref); 1518c2ecf20Sopenharmony_ci ring->size = size; 1528c2ecf20Sopenharmony_ci ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* 1558c2ecf20Sopenharmony_ci * Workaround an erratum on the i830 which causes a hang if 1568c2ecf20Sopenharmony_ci * the TAIL pointer points to within the last 2 cachelines 1578c2ecf20Sopenharmony_ci * of the buffer. 1588c2ecf20Sopenharmony_ci */ 1598c2ecf20Sopenharmony_ci ring->effective_size = size; 1608c2ecf20Sopenharmony_ci if (IS_I830(i915) || IS_I845G(i915)) 1618c2ecf20Sopenharmony_ci ring->effective_size -= 2 * CACHELINE_BYTES; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci intel_ring_update_space(ring); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci vma = create_ring_vma(engine->gt->ggtt, size); 1668c2ecf20Sopenharmony_ci if (IS_ERR(vma)) { 1678c2ecf20Sopenharmony_ci kfree(ring); 1688c2ecf20Sopenharmony_ci return ERR_CAST(vma); 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci ring->vma = vma; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci return ring; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_civoid intel_ring_free(struct kref *ref) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci struct intel_ring *ring = container_of(ref, typeof(*ring), ref); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci i915_vma_put(ring->vma); 1808c2ecf20Sopenharmony_ci kfree(ring); 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic noinline int 1848c2ecf20Sopenharmony_ciwait_for_space(struct intel_ring *ring, 1858c2ecf20Sopenharmony_ci struct intel_timeline *tl, 1868c2ecf20Sopenharmony_ci unsigned int bytes) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci struct i915_request *target; 1898c2ecf20Sopenharmony_ci long timeout; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (intel_ring_update_space(ring) >= bytes) 1928c2ecf20Sopenharmony_ci return 0; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci GEM_BUG_ON(list_empty(&tl->requests)); 1958c2ecf20Sopenharmony_ci list_for_each_entry(target, &tl->requests, link) { 1968c2ecf20Sopenharmony_ci if (target->ring != ring) 1978c2ecf20Sopenharmony_ci continue; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* Would completion of this request free enough space? */ 2008c2ecf20Sopenharmony_ci if (bytes <= __intel_ring_space(target->postfix, 2018c2ecf20Sopenharmony_ci ring->emit, ring->size)) 2028c2ecf20Sopenharmony_ci break; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if (GEM_WARN_ON(&target->link == &tl->requests)) 2068c2ecf20Sopenharmony_ci return -ENOSPC; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci timeout = i915_request_wait(target, 2098c2ecf20Sopenharmony_ci I915_WAIT_INTERRUPTIBLE, 2108c2ecf20Sopenharmony_ci MAX_SCHEDULE_TIMEOUT); 2118c2ecf20Sopenharmony_ci if (timeout < 0) 2128c2ecf20Sopenharmony_ci return timeout; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci i915_request_retire_upto(target); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci intel_ring_update_space(ring); 2178c2ecf20Sopenharmony_ci GEM_BUG_ON(ring->space < bytes); 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ciu32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci struct intel_ring *ring = rq->ring; 2248c2ecf20Sopenharmony_ci const unsigned int remain_usable = ring->effective_size - ring->emit; 2258c2ecf20Sopenharmony_ci const unsigned int bytes = num_dwords * sizeof(u32); 2268c2ecf20Sopenharmony_ci unsigned int need_wrap = 0; 2278c2ecf20Sopenharmony_ci unsigned int total_bytes; 2288c2ecf20Sopenharmony_ci u32 *cs; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* Packets must be qword aligned. */ 2318c2ecf20Sopenharmony_ci GEM_BUG_ON(num_dwords & 1); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci total_bytes = bytes + rq->reserved_space; 2348c2ecf20Sopenharmony_ci GEM_BUG_ON(total_bytes > ring->effective_size); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci if (unlikely(total_bytes > remain_usable)) { 2378c2ecf20Sopenharmony_ci const int remain_actual = ring->size - ring->emit; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (bytes > remain_usable) { 2408c2ecf20Sopenharmony_ci /* 2418c2ecf20Sopenharmony_ci * Not enough space for the basic request. So need to 2428c2ecf20Sopenharmony_ci * flush out the remainder and then wait for 2438c2ecf20Sopenharmony_ci * base + reserved. 2448c2ecf20Sopenharmony_ci */ 2458c2ecf20Sopenharmony_ci total_bytes += remain_actual; 2468c2ecf20Sopenharmony_ci need_wrap = remain_actual | 1; 2478c2ecf20Sopenharmony_ci } else { 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * The base request will fit but the reserved space 2508c2ecf20Sopenharmony_ci * falls off the end. So we don't need an immediate 2518c2ecf20Sopenharmony_ci * wrap and only need to effectively wait for the 2528c2ecf20Sopenharmony_ci * reserved size from the start of ringbuffer. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci total_bytes = rq->reserved_space + remain_actual; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci if (unlikely(total_bytes > ring->space)) { 2598c2ecf20Sopenharmony_ci int ret; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* 2628c2ecf20Sopenharmony_ci * Space is reserved in the ringbuffer for finalising the 2638c2ecf20Sopenharmony_ci * request, as that cannot be allowed to fail. During request 2648c2ecf20Sopenharmony_ci * finalisation, reserved_space is set to 0 to stop the 2658c2ecf20Sopenharmony_ci * overallocation and the assumption is that then we never need 2668c2ecf20Sopenharmony_ci * to wait (which has the risk of failing with EINTR). 2678c2ecf20Sopenharmony_ci * 2688c2ecf20Sopenharmony_ci * See also i915_request_alloc() and i915_request_add(). 2698c2ecf20Sopenharmony_ci */ 2708c2ecf20Sopenharmony_ci GEM_BUG_ON(!rq->reserved_space); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci ret = wait_for_space(ring, 2738c2ecf20Sopenharmony_ci i915_request_timeline(rq), 2748c2ecf20Sopenharmony_ci total_bytes); 2758c2ecf20Sopenharmony_ci if (unlikely(ret)) 2768c2ecf20Sopenharmony_ci return ERR_PTR(ret); 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (unlikely(need_wrap)) { 2808c2ecf20Sopenharmony_ci need_wrap &= ~1; 2818c2ecf20Sopenharmony_ci GEM_BUG_ON(need_wrap > ring->space); 2828c2ecf20Sopenharmony_ci GEM_BUG_ON(ring->emit + need_wrap > ring->size); 2838c2ecf20Sopenharmony_ci GEM_BUG_ON(!IS_ALIGNED(need_wrap, sizeof(u64))); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* Fill the tail with MI_NOOP */ 2868c2ecf20Sopenharmony_ci memset64(ring->vaddr + ring->emit, 0, need_wrap / sizeof(u64)); 2878c2ecf20Sopenharmony_ci ring->space -= need_wrap; 2888c2ecf20Sopenharmony_ci ring->emit = 0; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci GEM_BUG_ON(ring->emit > ring->size - bytes); 2928c2ecf20Sopenharmony_ci GEM_BUG_ON(ring->space < bytes); 2938c2ecf20Sopenharmony_ci cs = ring->vaddr + ring->emit; 2948c2ecf20Sopenharmony_ci GEM_DEBUG_EXEC(memset32(cs, POISON_INUSE, bytes / sizeof(*cs))); 2958c2ecf20Sopenharmony_ci ring->emit += bytes; 2968c2ecf20Sopenharmony_ci ring->space -= bytes; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci return cs; 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci/* Align the ring tail to a cacheline boundary */ 3028c2ecf20Sopenharmony_ciint intel_ring_cacheline_align(struct i915_request *rq) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci int num_dwords; 3058c2ecf20Sopenharmony_ci void *cs; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci num_dwords = (rq->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(u32); 3088c2ecf20Sopenharmony_ci if (num_dwords == 0) 3098c2ecf20Sopenharmony_ci return 0; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci num_dwords = CACHELINE_DWORDS - num_dwords; 3128c2ecf20Sopenharmony_ci GEM_BUG_ON(num_dwords & 1); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci cs = intel_ring_begin(rq, num_dwords); 3158c2ecf20Sopenharmony_ci if (IS_ERR(cs)) 3168c2ecf20Sopenharmony_ci return PTR_ERR(cs); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci memset64(cs, (u64)MI_NOOP << 32 | MI_NOOP, num_dwords / 2); 3198c2ecf20Sopenharmony_ci intel_ring_advance(rq, cs + num_dwords); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci GEM_BUG_ON(rq->ring->emit & (CACHELINE_BYTES - 1)); 3228c2ecf20Sopenharmony_ci return 0; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) 3268c2ecf20Sopenharmony_ci#include "selftest_ring.c" 3278c2ecf20Sopenharmony_ci#endif 328