Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Matthew Auld | 556 | 69.41% | 13 | 86.67% |
Thomas Hellstrom | 242 | 30.21% | 1 | 6.67% |
Jani Nikula | 3 | 0.37% | 1 | 6.67% |
Total | 801 | 15 |
// SPDX-License-Identifier: MIT /* * Copyright © 2019 Intel Corporation */ #include <uapi/drm/i915_drm.h> #include "intel_memory_region.h" #include "i915_gem_region.h" #include "i915_drv.h" #include "i915_trace.h" void i915_gem_object_init_memory_region(struct drm_i915_gem_object *obj, struct intel_memory_region *mem) { obj->mm.region = mem; mutex_lock(&mem->objects.lock); list_add(&obj->mm.region_link, &mem->objects.list); mutex_unlock(&mem->objects.lock); } void i915_gem_object_release_memory_region(struct drm_i915_gem_object *obj) { struct intel_memory_region *mem = obj->mm.region; mutex_lock(&mem->objects.lock); list_del(&obj->mm.region_link); mutex_unlock(&mem->objects.lock); } static struct drm_i915_gem_object * __i915_gem_object_create_region(struct intel_memory_region *mem, resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags) { struct drm_i915_gem_object *obj; resource_size_t default_page_size; int err; /* * NB: Our use of resource_size_t for the size stems from using struct * resource for the mem->region. We might need to revisit this in the * future. */ GEM_BUG_ON(flags & ~I915_BO_ALLOC_FLAGS); if (WARN_ON_ONCE(flags & I915_BO_ALLOC_GPU_ONLY && (flags & I915_BO_ALLOC_CPU_CLEAR || flags & I915_BO_ALLOC_PM_EARLY))) return ERR_PTR(-EINVAL); if (!mem) return ERR_PTR(-ENODEV); default_page_size = mem->min_page_size; if (page_size) default_page_size = page_size; /* We should be able to fit a page within an sg entry */ GEM_BUG_ON(overflows_type(default_page_size, u32)); GEM_BUG_ON(!is_power_of_2_u64(default_page_size)); GEM_BUG_ON(default_page_size < PAGE_SIZE); size = round_up(size, default_page_size); if (default_page_size == size) flags |= I915_BO_ALLOC_CONTIGUOUS; GEM_BUG_ON(!size); GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT)); if (i915_gem_object_size_2big(size)) return ERR_PTR(-E2BIG); obj = i915_gem_object_alloc(); if (!obj) return ERR_PTR(-ENOMEM); /* * Anything smaller than the min_page_size can't be freely inserted into * the GTT, due to alignemnt restrictions. For such special objects, * make sure we force memcpy based suspend-resume. In the future we can * revisit this, either by allowing special mis-aligned objects in the * migration path, or by mapping all of LMEM upfront using cheap 1G * GTT entries. */ if (default_page_size < mem->min_page_size) flags |= I915_BO_ALLOC_PM_EARLY; err = mem->ops->init_object(mem, obj, offset, size, page_size, flags); if (err) goto err_object_free; trace_i915_gem_object_create(obj); return obj; err_object_free: i915_gem_object_free(obj); return ERR_PTR(err); } struct drm_i915_gem_object * i915_gem_object_create_region(struct intel_memory_region *mem, resource_size_t size, resource_size_t page_size, unsigned int flags) { return __i915_gem_object_create_region(mem, I915_BO_INVALID_OFFSET, size, page_size, flags); } struct drm_i915_gem_object * i915_gem_object_create_region_at(struct intel_memory_region *mem, resource_size_t offset, resource_size_t size, unsigned int flags) { GEM_BUG_ON(offset == I915_BO_INVALID_OFFSET); if (GEM_WARN_ON(!IS_ALIGNED(size, mem->min_page_size)) || GEM_WARN_ON(!IS_ALIGNED(offset, mem->min_page_size))) return ERR_PTR(-EINVAL); if (range_overflows(offset, size, resource_size(&mem->region))) return ERR_PTR(-EINVAL); if (!(flags & I915_BO_ALLOC_GPU_ONLY) && offset + size > mem->io_size && !i915_ggtt_has_aperture(to_gt(mem->i915)->ggtt)) return ERR_PTR(-ENOSPC); return __i915_gem_object_create_region(mem, offset, size, 0, flags | I915_BO_ALLOC_CONTIGUOUS); } /** * i915_gem_process_region - Iterate over all objects of a region using ops * to process and optionally skip objects * @mr: The memory region * @apply: ops and private data * * This function can be used to iterate over the regions object list, * checking whether to skip objects, and, if not, lock the objects and * process them using the supplied ops. Note that this function temporarily * removes objects from the region list while iterating, so that if run * concurrently with itself may not iterate over all objects. * * Return: 0 if successful, negative error code on failure. */ int i915_gem_process_region(struct intel_memory_region *mr, struct i915_gem_apply_to_region *apply) { const struct i915_gem_apply_to_region_ops *ops = apply->ops; struct drm_i915_gem_object *obj; struct list_head still_in_list; int ret = 0; /* * In the future, a non-NULL apply->ww could mean the caller is * already in a locking transaction and provides its own context. */ GEM_WARN_ON(apply->ww); INIT_LIST_HEAD(&still_in_list); mutex_lock(&mr->objects.lock); for (;;) { struct i915_gem_ww_ctx ww; obj = list_first_entry_or_null(&mr->objects.list, typeof(*obj), mm.region_link); if (!obj) break; list_move_tail(&obj->mm.region_link, &still_in_list); if (!kref_get_unless_zero(&obj->base.refcount)) continue; /* * Note: Someone else might be migrating the object at this * point. The object's region is not stable until we lock * the object. */ mutex_unlock(&mr->objects.lock); apply->ww = &ww; for_i915_gem_ww(&ww, ret, apply->interruptible) { ret = i915_gem_object_lock(obj, apply->ww); if (ret) continue; if (obj->mm.region == mr) ret = ops->process_obj(apply, obj); /* Implicit object unlock */ } i915_gem_object_put(obj); mutex_lock(&mr->objects.lock); if (ret) break; } list_splice_tail(&still_in_list, &mr->objects.list); mutex_unlock(&mr->objects.lock); return ret; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1