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
13void __iomem *
14i915_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 */
42bool 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 */
75struct 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
85struct drm_i915_gem_object *
86i915_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
112struct drm_i915_gem_object *
113i915_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