struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc) { struct dma_fence *fence; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return NULL; dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock, crtc->fence_context, ++crtc->fence_seqno); return fence; }
struct dma_fence * drm_writeback_get_out_fence(struct drm_writeback_connector *wb_connector) { struct dma_fence *fence; if (WARN_ON(wb_connector->base.connector_type != DRM_MODE_CONNECTOR_WRITEBACK)) return NULL; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return NULL; dma_fence_init(fence, &drm_writeback_fence_ops, &wb_connector->fence_lock, wb_connector->fence_context, ++wb_connector->fence_seqno); return fence; }
static struct dma_fence *vgem_fence_create(struct vgem_file *vfile, unsigned int flags) { struct vgem_fence *fence; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return NULL; spin_lock_init(&fence->lock); dma_fence_init(&fence->base, &vgem_fence_ops, &fence->lock, dma_fence_context_alloc(1), 1); setup_timer(&fence->timer, vgem_fence_timeout, (unsigned long)fence); /* We force the fence to expire within 10s to prevent driver hangs */ mod_timer(&fence->timer, jiffies + VGEM_FENCE_TIMEOUT); return &fence->base; }
/** * amdgpu_fence_emit - emit a fence on the requested ring * * @ring: ring the fence is associated with * @f: resulting fence object * * Emits a fence command on the requested ring (all asics). * Returns 0 on success, -ENOMEM on failure. */ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f) { struct amdgpu_device *adev = ring->adev; struct amdgpu_fence *fence; struct dma_fence *old, **ptr; uint32_t seq; fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL); if (fence == NULL) return -ENOMEM; seq = ++ring->fence_drv.sync_seq; fence->ring = ring; dma_fence_init(&fence->base, &amdgpu_fence_ops, &ring->fence_drv.lock, adev->fence_context + ring->idx, seq); amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, AMDGPU_FENCE_FLAG_INT); ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; /* This function can't be called concurrently anyway, otherwise * emitting the fence would mess up the hardware ring buffer. */ old = rcu_dereference_protected(*ptr, 1); if (old && !dma_fence_is_signaled(old)) { DRM_INFO("rcu slot is busy\n"); dma_fence_wait(old, false); } rcu_assign_pointer(*ptr, dma_fence_get(&fence->base)); *f = &fence->base; return 0; }
bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, unsigned int flags) { struct clflush *clflush; /* * Stolen memory is always coherent with the GPU as it is explicitly * marked as wc by the system, or the system is cache-coherent. * Similarly, we only access struct pages through the CPU cache, so * anything not backed by physical memory we consider to be always * coherent and not need clflushing. */ if (!i915_gem_object_has_struct_page(obj)) { obj->cache_dirty = false; return false; } /* If the GPU is snooping the contents of the CPU cache, * we do not need to manually clear the CPU cache lines. However, * the caches are only snooped when the render cache is * flushed/invalidated. As we always have to emit invalidations * and flushes when moving into and out of the RENDER domain, correct * snooping behaviour occurs naturally as the result of our domain * tracking. */ if (!(flags & I915_CLFLUSH_FORCE) && obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ) return false; trace_i915_gem_object_clflush(obj); clflush = NULL; if (!(flags & I915_CLFLUSH_SYNC)) clflush = kmalloc(sizeof(*clflush), GFP_KERNEL); if (clflush) { GEM_BUG_ON(!obj->cache_dirty); dma_fence_init(&clflush->dma, &i915_clflush_ops, &clflush_lock, to_i915(obj->base.dev)->mm.unordered_timeline, 0); i915_sw_fence_init(&clflush->wait, i915_clflush_notify); clflush->obj = i915_gem_object_get(obj); INIT_WORK(&clflush->work, i915_clflush_work); dma_fence_get(&clflush->dma); i915_sw_fence_await_reservation(&clflush->wait, obj->resv, NULL, true, I915_FENCE_TIMEOUT, I915_FENCE_GFP); reservation_object_lock(obj->resv, NULL); reservation_object_add_excl_fence(obj->resv, &clflush->dma); reservation_object_unlock(obj->resv); i915_sw_fence_commit(&clflush->wait); } else if (obj->mm.pages) { __i915_do_clflush(obj); } else { GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU); } obj->cache_dirty = false; return true; }