| 1 | // SPDX-License-Identifier: MIT | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright © 2019 Intel Corporation | 
|---|
| 4 | */ | 
|---|
| 5 |  | 
|---|
| 6 | #include <uapi/drm/i915_drm.h> | 
|---|
| 7 |  | 
|---|
| 8 | #include "intel_memory_region.h" | 
|---|
| 9 | #include "gem/i915_gem_region.h" | 
|---|
| 10 | #include "gem/i915_gem_lmem.h" | 
|---|
| 11 | #include "i915_drv.h" | 
|---|
| 12 |  | 
|---|
| 13 | void __iomem * | 
|---|
| 14 | i915_gem_object_lmem_io_map(struct drm_i915_gem_object *obj, | 
|---|
| 15 | unsigned long n, | 
|---|
| 16 | unsigned long size) | 
|---|
| 17 | { | 
|---|
| 18 | resource_size_t offset; | 
|---|
| 19 |  | 
|---|
| 20 | GEM_BUG_ON(!i915_gem_object_is_contiguous(obj)); | 
|---|
| 21 |  | 
|---|
| 22 | offset = i915_gem_object_get_dma_address(obj, n); | 
|---|
| 23 | offset -= obj->mm.region->region.start; | 
|---|
| 24 |  | 
|---|
| 25 | return io_mapping_map_wc(mapping: &obj->mm.region->iomap, offset, size); | 
|---|
| 26 | } | 
|---|
| 27 |  | 
|---|
| 28 | /** | 
|---|
| 29 | * i915_gem_object_is_lmem - Whether the object is resident in | 
|---|
| 30 | * lmem | 
|---|
| 31 | * @obj: The object to check. | 
|---|
| 32 | * | 
|---|
| 33 | * Even if an object is allowed to migrate and change memory region, | 
|---|
| 34 | * this function checks whether it will always be present in lmem when | 
|---|
| 35 | * valid *or* if that's not the case, whether it's currently resident in lmem. | 
|---|
| 36 | * For migratable and evictable objects, the latter only makes sense when | 
|---|
| 37 | * the object is locked. | 
|---|
| 38 | * | 
|---|
| 39 | * Return: Whether the object migratable but resident in lmem, or not | 
|---|
| 40 | * migratable and will be present in lmem when valid. | 
|---|
| 41 | */ | 
|---|
| 42 | bool i915_gem_object_is_lmem(struct drm_i915_gem_object *obj) | 
|---|
| 43 | { | 
|---|
| 44 | struct intel_memory_region *mr = READ_ONCE(obj->mm.region); | 
|---|
| 45 |  | 
|---|
| 46 | #ifdef CONFIG_LOCKDEP | 
|---|
| 47 | if (i915_gem_object_migratable(obj) && | 
|---|
| 48 | i915_gem_object_evictable(obj)) | 
|---|
| 49 | assert_object_held(obj); | 
|---|
| 50 | #endif | 
|---|
| 51 | return mr && intel_memory_type_is_local(mem_type: mr->type); | 
|---|
| 52 | } | 
|---|
| 53 |  | 
|---|
| 54 | /** | 
|---|
| 55 | * __i915_gem_object_create_lmem_with_ps - Create lmem object and force the | 
|---|
| 56 | * minimum page size for the backing pages. | 
|---|
| 57 | * @i915: The i915 instance. | 
|---|
| 58 | * @size: The size in bytes for the object. Note that we need to round the size | 
|---|
| 59 | * up depending on the @page_size. The final object size can be fished out from | 
|---|
| 60 | * the drm GEM object. | 
|---|
| 61 | * @page_size: The requested minimum page size in bytes for this object. This is | 
|---|
| 62 | * useful if we need something bigger than the regions min_page_size due to some | 
|---|
| 63 | * hw restriction, or in some very specialised cases where it needs to be | 
|---|
| 64 | * smaller, where the internal fragmentation cost is too great when rounding up | 
|---|
| 65 | * the object size. | 
|---|
| 66 | * @flags: The optional BO allocation flags. | 
|---|
| 67 | * | 
|---|
| 68 | * Note that this interface assumes you know what you are doing when forcing the | 
|---|
| 69 | * @page_size. If this is smaller than the regions min_page_size then it can | 
|---|
| 70 | * never be inserted into any GTT, otherwise it might lead to undefined | 
|---|
| 71 | * behaviour. | 
|---|
| 72 | * | 
|---|
| 73 | * Return: The object pointer, which might be an ERR_PTR in the case of failure. | 
|---|
| 74 | */ | 
|---|
| 75 | struct drm_i915_gem_object * | 
|---|
| 76 | __i915_gem_object_create_lmem_with_ps(struct drm_i915_private *i915, | 
|---|
| 77 | resource_size_t size, | 
|---|
| 78 | resource_size_t page_size, | 
|---|
| 79 | unsigned int flags) | 
|---|
| 80 | { | 
|---|
| 81 | return i915_gem_object_create_region(mem: i915->mm.regions[INTEL_REGION_LMEM_0], | 
|---|
| 82 | size, page_size, flags); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | struct drm_i915_gem_object * | 
|---|
| 86 | i915_gem_object_create_lmem_from_data(struct drm_i915_private *i915, | 
|---|
| 87 | const void *data, size_t size) | 
|---|
| 88 | { | 
|---|
| 89 | struct drm_i915_gem_object *obj; | 
|---|
| 90 | void *map; | 
|---|
| 91 |  | 
|---|
| 92 | obj = i915_gem_object_create_lmem(i915, | 
|---|
| 93 | round_up(size, PAGE_SIZE), | 
|---|
| 94 | I915_BO_ALLOC_CONTIGUOUS); | 
|---|
| 95 | if (IS_ERR(ptr: obj)) | 
|---|
| 96 | return obj; | 
|---|
| 97 |  | 
|---|
| 98 | map = i915_gem_object_pin_map_unlocked(obj, type: I915_MAP_WC); | 
|---|
| 99 | if (IS_ERR(ptr: map)) { | 
|---|
| 100 | i915_gem_object_put(obj); | 
|---|
| 101 | return map; | 
|---|
| 102 | } | 
|---|
| 103 |  | 
|---|
| 104 | memcpy(to: map, from: data, len: size); | 
|---|
| 105 |  | 
|---|
| 106 | i915_gem_object_flush_map(obj); | 
|---|
| 107 | __i915_gem_object_release_map(obj); | 
|---|
| 108 |  | 
|---|
| 109 | return obj; | 
|---|
| 110 | } | 
|---|
| 111 |  | 
|---|
| 112 | struct drm_i915_gem_object * | 
|---|
| 113 | i915_gem_object_create_lmem(struct drm_i915_private *i915, | 
|---|
| 114 | resource_size_t size, | 
|---|
| 115 | unsigned int flags) | 
|---|
| 116 | { | 
|---|
| 117 | return i915_gem_object_create_region(mem: i915->mm.regions[INTEL_REGION_LMEM_0], | 
|---|
| 118 | size, page_size: 0, flags); | 
|---|
| 119 | } | 
|---|
| 120 |  | 
|---|