]> Git Repo - J-linux.git/blob - drivers/gpu/drm/i915/intel_memory_region.c
drm/ast: potential dereference of null pointer
[J-linux.git] / drivers / gpu / drm / i915 / intel_memory_region.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2019 Intel Corporation
4  */
5
6 #include "intel_memory_region.h"
7 #include "i915_drv.h"
8 #include "i915_ttm_buddy_manager.h"
9
10 static const struct {
11         u16 class;
12         u16 instance;
13 } intel_region_map[] = {
14         [INTEL_REGION_SMEM] = {
15                 .class = INTEL_MEMORY_SYSTEM,
16                 .instance = 0,
17         },
18         [INTEL_REGION_LMEM] = {
19                 .class = INTEL_MEMORY_LOCAL,
20                 .instance = 0,
21         },
22         [INTEL_REGION_STOLEN_SMEM] = {
23                 .class = INTEL_MEMORY_STOLEN_SYSTEM,
24                 .instance = 0,
25         },
26         [INTEL_REGION_STOLEN_LMEM] = {
27                 .class = INTEL_MEMORY_STOLEN_LOCAL,
28                 .instance = 0,
29         },
30 };
31
32 struct intel_memory_region *
33 intel_memory_region_lookup(struct drm_i915_private *i915,
34                            u16 class, u16 instance)
35 {
36         struct intel_memory_region *mr;
37         int id;
38
39         /* XXX: consider maybe converting to an rb tree at some point */
40         for_each_memory_region(mr, i915, id) {
41                 if (mr->type == class && mr->instance == instance)
42                         return mr;
43         }
44
45         return NULL;
46 }
47
48 struct intel_memory_region *
49 intel_memory_region_by_type(struct drm_i915_private *i915,
50                             enum intel_memory_type mem_type)
51 {
52         struct intel_memory_region *mr;
53         int id;
54
55         for_each_memory_region(mr, i915, id)
56                 if (mr->type == mem_type)
57                         return mr;
58
59         return NULL;
60 }
61
62 /**
63  * intel_memory_region_reserve - Reserve a memory range
64  * @mem: The region for which we want to reserve a range.
65  * @offset: Start of the range to reserve.
66  * @size: The size of the range to reserve.
67  *
68  * Return: 0 on success, negative error code on failure.
69  */
70 int intel_memory_region_reserve(struct intel_memory_region *mem,
71                                 resource_size_t offset,
72                                 resource_size_t size)
73 {
74         struct ttm_resource_manager *man = mem->region_private;
75
76         GEM_BUG_ON(mem->is_range_manager);
77
78         return i915_ttm_buddy_man_reserve(man, offset, size);
79 }
80
81 void intel_memory_region_debug(struct intel_memory_region *mr,
82                                struct drm_printer *printer)
83 {
84         drm_printf(printer, "%s: ", mr->name);
85
86         if (mr->region_private)
87                 ttm_resource_manager_debug(mr->region_private, printer);
88         else
89                 drm_printf(printer, "total:%pa, available:%pa bytes\n",
90                            &mr->total, &mr->avail);
91 }
92
93 struct intel_memory_region *
94 intel_memory_region_create(struct drm_i915_private *i915,
95                            resource_size_t start,
96                            resource_size_t size,
97                            resource_size_t min_page_size,
98                            resource_size_t io_start,
99                            u16 type,
100                            u16 instance,
101                            const struct intel_memory_region_ops *ops)
102 {
103         struct intel_memory_region *mem;
104         int err;
105
106         mem = kzalloc(sizeof(*mem), GFP_KERNEL);
107         if (!mem)
108                 return ERR_PTR(-ENOMEM);
109
110         mem->i915 = i915;
111         mem->region = (struct resource)DEFINE_RES_MEM(start, size);
112         mem->io_start = io_start;
113         mem->min_page_size = min_page_size;
114         mem->ops = ops;
115         mem->total = size;
116         mem->avail = mem->total;
117         mem->type = type;
118         mem->instance = instance;
119
120         mutex_init(&mem->objects.lock);
121         INIT_LIST_HEAD(&mem->objects.list);
122
123         if (ops->init) {
124                 err = ops->init(mem);
125                 if (err)
126                         goto err_free;
127         }
128
129         kref_init(&mem->kref);
130         return mem;
131
132 err_free:
133         kfree(mem);
134         return ERR_PTR(err);
135 }
136
137 void intel_memory_region_set_name(struct intel_memory_region *mem,
138                                   const char *fmt, ...)
139 {
140         va_list ap;
141
142         va_start(ap, fmt);
143         vsnprintf(mem->name, sizeof(mem->name), fmt, ap);
144         va_end(ap);
145 }
146
147 static void __intel_memory_region_destroy(struct kref *kref)
148 {
149         struct intel_memory_region *mem =
150                 container_of(kref, typeof(*mem), kref);
151
152         if (mem->ops->release)
153                 mem->ops->release(mem);
154
155         mutex_destroy(&mem->objects.lock);
156         kfree(mem);
157 }
158
159 struct intel_memory_region *
160 intel_memory_region_get(struct intel_memory_region *mem)
161 {
162         kref_get(&mem->kref);
163         return mem;
164 }
165
166 void intel_memory_region_put(struct intel_memory_region *mem)
167 {
168         kref_put(&mem->kref, __intel_memory_region_destroy);
169 }
170
171 /* Global memory region registration -- only slight layer inversions! */
172
173 int intel_memory_regions_hw_probe(struct drm_i915_private *i915)
174 {
175         int err, i;
176
177         for (i = 0; i < ARRAY_SIZE(i915->mm.regions); i++) {
178                 struct intel_memory_region *mem = ERR_PTR(-ENODEV);
179                 u16 type, instance;
180
181                 if (!HAS_REGION(i915, BIT(i)))
182                         continue;
183
184                 type = intel_region_map[i].class;
185                 instance = intel_region_map[i].instance;
186                 switch (type) {
187                 case INTEL_MEMORY_SYSTEM:
188                         if (IS_DGFX(i915))
189                                 mem = i915_gem_ttm_system_setup(i915, type,
190                                                                 instance);
191                         else
192                                 mem = i915_gem_shmem_setup(i915, type,
193                                                            instance);
194                         break;
195                 case INTEL_MEMORY_STOLEN_LOCAL:
196                         mem = i915_gem_stolen_lmem_setup(i915, type, instance);
197                         if (!IS_ERR(mem))
198                                 i915->mm.stolen_region = mem;
199                         break;
200                 case INTEL_MEMORY_STOLEN_SYSTEM:
201                         mem = i915_gem_stolen_smem_setup(i915, type, instance);
202                         if (!IS_ERR(mem))
203                                 i915->mm.stolen_region = mem;
204                         break;
205                 default:
206                         continue;
207                 }
208
209                 if (IS_ERR(mem)) {
210                         err = PTR_ERR(mem);
211                         drm_err(&i915->drm,
212                                 "Failed to setup region(%d) type=%d\n",
213                                 err, type);
214                         goto out_cleanup;
215                 }
216
217                 mem->id = i;
218                 i915->mm.regions[i] = mem;
219         }
220
221         return 0;
222
223 out_cleanup:
224         intel_memory_regions_driver_release(i915);
225         return err;
226 }
227
228 void intel_memory_regions_driver_release(struct drm_i915_private *i915)
229 {
230         int i;
231
232         for (i = 0; i < ARRAY_SIZE(i915->mm.regions); i++) {
233                 struct intel_memory_region *region =
234                         fetch_and_zero(&i915->mm.regions[i]);
235
236                 if (region)
237                         intel_memory_region_put(region);
238         }
239 }
240
241 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
242 #include "selftests/intel_memory_region.c"
243 #include "selftests/mock_region.c"
244 #endif
This page took 0.043326 seconds and 4 git commands to generate.