Add new extension to support setting an immutable-priority-list of potential placements, at creation time. If we use the normal gem_create or gem_create_ext without the extensions/placements then we still get the old behaviour with only placing the object in system memory. v2(Daniel & Jason): - Add a bunch of kernel-doc - Simplify design for placements extension
Unified · Split
| @@ -4,12 +4,51 @@ · 3 unmodified lines | |||
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include "gem/i915_gem_ioctls.h" | 6 | #include "gem/i915_gem_ioctls.h" |
| 7 | #include "gem/i915_gem_lmem.h" | ||
| 7 | #include "gem/i915_gem_region.h" | 8 | #include "gem/i915_gem_region.h" |
| 8 | 9 | ||
| 9 | #include "i915_drv.h" | 10 | #include "i915_drv.h" |
| 10 | #include "i915_trace.h" | 11 | #include "i915_trace.h" |
| 11 | #include "i915_user_extensions.h" | 12 | #include "i915_user_extensions.h" |
| 12 | 13 | ||
| 14 | static u32 object_max_page_size(struct drm_i915_gem_object *obj) | ||
| 15 | { | ||
| 16 | u32 max_page_size = 0; | ||
| 17 | int i; | ||
| 18 | |||
| 19 | for (i = 0; i < obj->mm.n_placements; i++) { | ||
| 20 | struct intel_memory_region *mr = obj->mm.placements[i]; | ||
| 21 | |||
| 22 | GEM_BUG_ON(!is_power_of_2(mr->min_page_size)); | ||
| 23 | max_page_size = max_t(u32, max_page_size, mr->min_page_size); | ||
| 24 | } | ||
| 25 | |||
| 26 | GEM_BUG_ON(!max_page_size); | ||
| 27 | return max_page_size; | ||
| 28 | } | ||
| 29 | |||
| 30 | static void object_set_placements(struct drm_i915_gem_object *obj, | ||
| 31 | struct intel_memory_region **placements, | ||
| 32 | unsigned int n_placements) | ||
| 33 | { | ||
| 34 | GEM_BUG_ON(!n_placements); | ||
| 35 | |||
| 36 | /* | ||
| 37 | * For the common case of one memory region, skip storing an | ||
| 38 | * allocated array and just point at the region directly. | ||
| 39 | */ | ||
| 40 | if (n_placements == 1) { | ||
| 41 | struct intel_memory_region *mr = placements[0]; | ||
| 42 | struct drm_i915_private *i915 = mr->i915; | ||
| 43 | |||
| 44 | obj->mm.placements = &i915->mm.regions[mr->id]; | ||
| 45 | obj->mm.n_placements = 1; | ||
| 46 | } else { | ||
| 47 | obj->mm.placements = placements; | ||
| 48 | obj->mm.n_placements = n_placements; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 13 | static int i915_gem_publish(struct drm_i915_gem_object *obj, | 52 | static int i915_gem_publish(struct drm_i915_gem_object *obj, |
| 14 | struct drm_file *file, | 53 | struct drm_file *file, |
| 15 | u64 *size_p, | 54 | u64 *size_p, |
| @@ -29,14 +68,12 @@ static int i915_gem_publish(struct drm_i915_gem_object *obj, · 13 unmodified lines | |||
| 29 | } | 68 | } |
| 30 | 69 | ||
| 31 | static int | 70 | static int |
| 32 | i915_gem_setup(struct drm_i915_gem_object *obj, | 71 | i915_gem_setup(struct drm_i915_gem_object *obj, u64 size) |
| 33 | struct intel_memory_region *mr, | ||
| 34 | u64 size) | ||
| 35 | { | 72 | { |
| 73 | struct intel_memory_region *mr = obj->mm.placements[0]; | ||
| 36 | int ret; | 74 | int ret; |
| 37 | 75 | ||
| 38 | GEM_BUG_ON(!is_power_of_2(mr->min_page_size)); | 76 | size = round_up(size, object_max_page_size(obj)); |
| 39 | size = round_up(size, mr->min_page_size); | ||
| 40 | if (size == 0) | 77 | if (size == 0) |
| 41 | return -EINVAL; | 78 | return -EINVAL; |
| 42 | 79 | ||
| @@ -62,6 +99,7 @@ i915_gem_dumb_create(struct drm_file *file, · 19 unmodified lines | |||
| 62 | struct drm_mode_create_dumb *args) | 99 | struct drm_mode_create_dumb *args) |
| 63 | { | 100 | { |
| 64 | struct drm_i915_gem_object *obj; | 101 | struct drm_i915_gem_object *obj; |
| 102 | struct intel_memory_region *mr; | ||
| 65 | enum intel_memory_type mem_type; | 103 | enum intel_memory_type mem_type; |
| 66 | int cpp = DIV_ROUND_UP(args->bpp, 8); | 104 | int cpp = DIV_ROUND_UP(args->bpp, 8); |
| 67 | u32 format; | 105 | u32 format; |
| @@ -102,10 +140,10 @@ i915_gem_dumb_create(struct drm_file *file, · 34 unmodified lines | |||
| 102 | if (!obj) | 140 | if (!obj) |
| 103 | return -ENOMEM; | 141 | return -ENOMEM; |
| 104 | 142 | ||
| 105 | ret = i915_gem_setup(obj, | 143 | mr = intel_memory_region_by_type(to_i915(dev), mem_type); |
| 106 | intel_memory_region_by_type(to_i915(dev), | 144 | object_set_placements(obj, &mr, 1); |
| 107 | mem_type), | 145 | |
| 108 | args->size); | 146 | ret = i915_gem_setup(obj, args->size); |
| 109 | if (ret) | 147 | if (ret) |
| 110 | goto object_free; | 148 | goto object_free; |
| 111 | 149 | ||
| @@ -129,6 +167,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, · 17 unmodified lines | |||
| 129 | struct drm_i915_private *i915 = to_i915(dev); | 167 | struct drm_i915_private *i915 = to_i915(dev); |
| 130 | struct drm_i915_gem_create *args = data; | 168 | struct drm_i915_gem_create *args = data; |
| 131 | struct drm_i915_gem_object *obj; | 169 | struct drm_i915_gem_object *obj; |
| 170 | struct intel_memory_region *mr; | ||
| 132 | int ret; | 171 | int ret; |
| 133 | 172 | ||
| 134 | i915_gem_flush_free_objects(i915); | 173 | i915_gem_flush_free_objects(i915); |
| @@ -137,10 +176,10 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, · 2 unmodified lines | |||
| 137 | if (!obj) | 176 | if (!obj) |
| 138 | return -ENOMEM; | 177 | return -ENOMEM; |
| 139 | 178 | ||
| 140 | ret = i915_gem_setup(obj, | 179 | mr = intel_memory_region_by_type(i915, INTEL_MEMORY_SYSTEM); |
| 141 | intel_memory_region_by_type(i915, | 180 | object_set_placements(obj, &mr, 1); |
| 142 | INTEL_MEMORY_SYSTEM), | 181 | |
| 143 | args->size); | 182 | ret = i915_gem_setup(obj, args->size); |
| 144 | if (ret) | 183 | if (ret) |
| 145 | goto object_free; | 184 | goto object_free; |
| 146 | 185 | ||
| @@ -156,7 +195,144 @@ struct create_ext { · 9 unmodified lines | |||
| 156 | struct drm_i915_gem_object *vanilla_object; | 195 | struct drm_i915_gem_object *vanilla_object; |
| 157 | }; | 196 | }; |
| 158 | 197 | ||
| 198 | static void repr_placements(char *buf, size_t size, | ||
| 199 | struct intel_memory_region **placements, | ||
| 200 | int n_placements) | ||
| 201 | { | ||
| 202 | int i; | ||
| 203 | |||
| 204 | buf[0] = '\0'; | ||
| 205 | |||
| 206 | for (i = 0; i < n_placements; i++) { | ||
| 207 | struct intel_memory_region *mr = placements[i]; | ||
| 208 | int r; | ||
| 209 | |||
| 210 | r = snprintf(buf, size, "\n %s -> { class: %d, inst: %d }", | ||
| 211 | mr->name, mr->type, mr->instance); | ||
| 212 | if (r >= size) | ||
| 213 | return; | ||
| 214 | |||
| 215 | buf += r; | ||
| 216 | size -= r; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args, | ||
| 221 | struct create_ext *ext_data) | ||
| 222 | { | ||
| 223 | struct drm_i915_private *i915 = ext_data->i915; | ||
| 224 | struct drm_i915_gem_memory_class_instance __user *uregions = | ||
| 225 | u64_to_user_ptr(args->regions); | ||
| 226 | struct drm_i915_gem_object *obj = ext_data->vanilla_object; | ||
| 227 | struct intel_memory_region **placements; | ||
| 228 | u32 mask; | ||
| 229 | int i, ret = 0; | ||
| 230 | |||
| 231 | if (args->pad) { | ||
| 232 | drm_dbg(&i915->drm, "pad should be zero\n"); | ||
| 233 | ret = -EINVAL; | ||
| 234 | } | ||
| 235 | |||
| 236 | if (!args->num_regions) { | ||
| 237 | drm_dbg(&i915->drm, "num_regions is zero\n"); | ||
| 238 | ret = -EINVAL; | ||
| 239 | } | ||
| 240 | |||
| 241 | if (args->num_regions > ARRAY_SIZE(i915->mm.regions)) { | ||
| 242 | drm_dbg(&i915->drm, "num_regions is too large\n"); | ||
| 243 | ret = -EINVAL; | ||
| 244 | } | ||
| 245 | |||
| 246 | if (ret) | ||
| 247 | return ret; | ||
| 248 | |||
| 249 | placements = kmalloc_array(args->num_regions, | ||
| 250 | sizeof(struct intel_memory_region *), | ||
| 251 | GFP_KERNEL); | ||
| 252 | if (!placements) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | mask = 0; | ||
| 256 | for (i = 0; i < args->num_regions; i++) { | ||
| 257 | struct drm_i915_gem_memory_class_instance region; | ||
| 258 | struct intel_memory_region *mr; | ||
| 259 | |||
| 260 | if (copy_from_user(®ion, uregions, sizeof(region))) { | ||
| 261 | ret = -EFAULT; | ||
| 262 | goto out_free; | ||
| 263 | } | ||
| 264 | |||
| 265 | mr = intel_memory_region_lookup(i915, | ||
| 266 | region.memory_class, | ||
| 267 | region.memory_instance); | ||
| 268 | if (!mr || mr->private) { | ||
| 269 | drm_dbg(&i915->drm, "Device is missing region { class: %d, inst: %d } at index = %d\n", | ||
| 270 | region.memory_class, region.memory_instance, i); | ||
| 271 | ret = -EINVAL; | ||
| 272 | goto out_dump; | ||
| 273 | } | ||
| 274 | |||
| 275 | if (mask & BIT(mr->id)) { | ||
| 276 | drm_dbg(&i915->drm, "Found duplicate placement %s -> { class: %d, inst: %d } at index = %d\n", | ||
| 277 | mr->name, region.memory_class, | ||
| 278 | region.memory_instance, i); | ||
| 279 | ret = -EINVAL; | ||
| 280 | goto out_dump; | ||
| 281 | } | ||
| 282 | |||
| 283 | placements[i] = mr; | ||
| 284 | mask |= BIT(mr->id); | ||
| 285 | |||
| 286 | ++uregions; | ||
| 287 | } | ||
| 288 | |||
| 289 | if (obj->mm.placements) { | ||
| 290 | ret = -EINVAL; | ||
| 291 | goto out_dump; | ||
| 292 | } | ||
| 293 | |||
| 294 | object_set_placements(obj, placements, args->num_regions); | ||
| 295 | if (args->num_regions == 1) | ||
| 296 | kfree(placements); | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | |||
| 300 | out_dump: | ||
| 301 | if (1) { | ||
| 302 | char buf[256]; | ||
| 303 | |||
| 304 | if (obj->mm.placements) { | ||
| 305 | repr_placements(buf, | ||
| 306 | sizeof(buf), | ||
| 307 | obj->mm.placements, | ||
| 308 | obj->mm.n_placements); | ||
| 309 | drm_dbg(&i915->drm, | ||
| 310 | "Placements were already set in previous EXT. Existing placements: %s\n", | ||
| 311 | buf); | ||
| 312 | } | ||
| 313 | |||
| 314 | repr_placements(buf, sizeof(buf), placements, i); | ||
| 315 | drm_dbg(&i915->drm, "New placements(so far validated): %s\n", buf); | ||
| 316 | } | ||
| 317 | |||
| 318 | out_free: | ||
| 319 | kfree(placements); | ||
| 320 | return ret; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int ext_set_placements(struct i915_user_extension __user *base, | ||
| 324 | void *data) | ||
| 325 | { | ||
| 326 | struct drm_i915_gem_create_ext_memory_regions ext; | ||
| 327 | |||
| 328 | if (copy_from_user(&ext, base, sizeof(ext))) | ||
| 329 | return -EFAULT; | ||
| 330 | |||
| 331 | return set_placements(&ext, data); | ||
| 332 | } | ||
| 333 | |||
| 159 | static const i915_user_extension_fn create_extensions[] = { | 334 | static const i915_user_extension_fn create_extensions[] = { |
| 335 | [I915_GEM_CREATE_EXT_MEMORY_REGIONS] = ext_set_placements, | ||
| 160 | }; | 336 | }; |
| 161 | 337 | ||
| 162 | /** | 338 | /** |
| @@ -172,6 +348,7 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data, · 9 unmodified lines | |||
| 172 | struct drm_i915_private *i915 = to_i915(dev); | 348 | struct drm_i915_private *i915 = to_i915(dev); |
| 173 | struct drm_i915_gem_create_ext *args = data; | 349 | struct drm_i915_gem_create_ext *args = data; |
| 174 | struct create_ext ext_data = { .i915 = i915 }; | 350 | struct create_ext ext_data = { .i915 = i915 }; |
| 351 | struct intel_memory_region **placements_ext; | ||
| 175 | struct drm_i915_gem_object *obj; | 352 | struct drm_i915_gem_object *obj; |
| 176 | int ret; | 353 | int ret; |
| 177 | 354 | ||
| @@ -189,19 +366,26 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data, · 11 unmodified lines | |||
| 189 | create_extensions, | 366 | create_extensions, |
| 190 | ARRAY_SIZE(create_extensions), | 367 | ARRAY_SIZE(create_extensions), |
| 191 | &ext_data); | 368 | &ext_data); |
| 369 | placements_ext = obj->mm.placements; | ||
| 192 | if (ret) | 370 | if (ret) |
| 193 | goto object_free; | 371 | goto object_free; |
| 194 | 372 | ||
| 195 | ret = i915_gem_setup(obj, | 373 | if (!placements_ext) { |
| 196 | intel_memory_region_by_type(i915, | 374 | struct intel_memory_region *mr = |
| 197 | INTEL_MEMORY_SYSTEM), | 375 | intel_memory_region_by_type(i915, INTEL_MEMORY_SYSTEM); |
| 198 | args->size); | 376 | |
| 377 | object_set_placements(obj, &mr, 1); | ||
| 378 | } | ||
| 379 | |||
| 380 | ret = i915_gem_setup(obj, args->size); | ||
| 199 | if (ret) | 381 | if (ret) |
| 200 | goto object_free; | 382 | goto object_free; |
| 201 | 383 | ||
| 202 | return i915_gem_publish(obj, file, &args->size, &args->handle); | 384 | return i915_gem_publish(obj, file, &args->size, &args->handle); |
| 203 | 385 | ||
| 204 | object_free: | 386 | object_free: |
| 387 | if (obj->mm.n_placements > 1) | ||
| 388 | kfree(placements_ext); | ||
| 205 | i915_gem_object_free(obj); | 389 | i915_gem_object_free(obj); |
| 206 | return ret; | 390 | return ret; |
| 207 | } | 391 | } |
| @@ -249,6 +249,9 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, · 248 unmodified lines | |||
| 249 | if (obj->ops->release) | 249 | if (obj->ops->release) |
| 250 | obj->ops->release(obj); | 250 | obj->ops->release(obj); |
| 251 | 251 | ||
| 252 | if (obj->mm.n_placements > 1) | ||
| 253 | kfree(obj->mm.placements); | ||
| 254 | |||
| 252 | /* But keep the pointer alive for RCU-protected lookups */ | 255 | /* But keep the pointer alive for RCU-protected lookups */ |
| 253 | call_rcu(&obj->rcu, __i915_gem_free_object_rcu); | 256 | call_rcu(&obj->rcu, __i915_gem_free_object_rcu); |
| 254 | cond_resched(); | 257 | cond_resched(); |
| @@ -219,6 +219,12 @@ struct drm_i915_gem_object { · 218 unmodified lines | |||
| 219 | atomic_t pages_pin_count; | 219 | atomic_t pages_pin_count; |
| 220 | atomic_t shrink_pin; | 220 | atomic_t shrink_pin; |
| 221 | 221 | ||
| 222 | /** | ||
| 223 | * Priority list of potential placements for this object. | ||
| 224 | */ | ||
| 225 | struct intel_memory_region **placements; | ||
| 226 | int n_placements; | ||
| 227 | |||
| 222 | /** | 228 | /** |
| 223 | * Memory region for this object. | 229 | * Memory region for this object. |
| 224 | */ | 230 | */ |
| @@ -842,6 +842,24 @@ static bool can_mmap(struct drm_i915_gem_object *obj, enum i915_mmap_type type) · 841 unmodified lines | |||
| 842 | return true; | 842 | return true; |
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | static void object_set_placements(struct drm_i915_gem_object *obj, | ||
| 846 | struct intel_memory_region **placements, | ||
| 847 | unsigned int n_placements) | ||
| 848 | { | ||
| 849 | GEM_BUG_ON(!n_placements); | ||
| 850 | |||
| 851 | if (n_placements == 1) { | ||
| 852 | struct drm_i915_private *i915 = to_i915(obj->base.dev); | ||
| 853 | struct intel_memory_region *mr = placements[0]; | ||
| 854 | |||
| 855 | obj->mm.placements = &i915->mm.regions[mr->id]; | ||
| 856 | obj->mm.n_placements = 1; | ||
| 857 | } else { | ||
| 858 | obj->mm.placements = placements; | ||
| 859 | obj->mm.n_placements = n_placements; | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 845 | #define expand32(x) (((x) << 0) | ((x) << 8) | ((x) << 16) | ((x) << 24)) | 863 | #define expand32(x) (((x) << 0) | ((x) << 8) | ((x) << 16) | ((x) << 24)) |
| 846 | static int __igt_mmap(struct drm_i915_private *i915, | 864 | static int __igt_mmap(struct drm_i915_private *i915, |
| 847 | struct drm_i915_gem_object *obj, | 865 | struct drm_i915_gem_object *obj, |
| @@ -950,6 +968,8 @@ static int igt_mmap(void *arg) · 102 unmodified lines | |||
| 950 | if (IS_ERR(obj)) | 968 | if (IS_ERR(obj)) |
| 951 | return PTR_ERR(obj); | 969 | return PTR_ERR(obj); |
| 952 | 970 | ||
| 971 | object_set_placements(obj, &mr, 1); | ||
| 972 | |||
| 953 | err = __igt_mmap(i915, obj, I915_MMAP_TYPE_GTT); | 973 | err = __igt_mmap(i915, obj, I915_MMAP_TYPE_GTT); |
| 954 | if (err == 0) | 974 | if (err == 0) |
| 955 | err = __igt_mmap(i915, obj, I915_MMAP_TYPE_WC); | 975 | err = __igt_mmap(i915, obj, I915_MMAP_TYPE_WC); |
| @@ -1068,6 +1088,8 @@ static int igt_mmap_access(void *arg) · 112 unmodified lines | |||
| 1068 | if (IS_ERR(obj)) | 1088 | if (IS_ERR(obj)) |
| 1069 | return PTR_ERR(obj); | 1089 | return PTR_ERR(obj); |
| 1070 | 1090 | ||
| 1091 | object_set_placements(obj, &mr, 1); | ||
| 1092 | |||
| 1071 | err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_GTT); | 1093 | err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_GTT); |
| 1072 | if (err == 0) | 1094 | if (err == 0) |
| 1073 | err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_WB); | 1095 | err = __igt_mmap_access(i915, obj, I915_MMAP_TYPE_WB); |
| @@ -1211,6 +1233,8 @@ static int igt_mmap_gpu(void *arg) · 137 unmodified lines | |||
| 1211 | if (IS_ERR(obj)) | 1233 | if (IS_ERR(obj)) |
| 1212 | return PTR_ERR(obj); | 1234 | return PTR_ERR(obj); |
| 1213 | 1235 | ||
| 1236 | object_set_placements(obj, &mr, 1); | ||
| 1237 | |||
| 1214 | err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_GTT); | 1238 | err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_GTT); |
| 1215 | if (err == 0) | 1239 | if (err == 0) |
| 1216 | err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_WC); | 1240 | err = __igt_mmap_gpu(i915, obj, I915_MMAP_TYPE_WC); |
| @@ -1354,6 +1378,8 @@ static int igt_mmap_revoke(void *arg) · 137 unmodified lines | |||
| 1354 | if (IS_ERR(obj)) | 1378 | if (IS_ERR(obj)) |
| 1355 | return PTR_ERR(obj); | 1379 | return PTR_ERR(obj); |
| 1356 | 1380 | ||
| 1381 | object_set_placements(obj, &mr, 1); | ||
| 1382 | |||
| 1357 | err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_GTT); | 1383 | err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_GTT); |
| 1358 | if (err == 0) | 1384 | if (err == 0) |
| 1359 | err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_WC); | 1385 | err = __igt_mmap_revoke(i915, obj, I915_MMAP_TYPE_WC); |
| @@ -28,6 +28,22 @@ static const struct { · 27 unmodified lines | |||
| 28 | }, | 28 | }, |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | struct intel_memory_region * | ||
| 32 | intel_memory_region_lookup(struct drm_i915_private *i915, | ||
| 33 | u16 class, u16 instance) | ||
| 34 | { | ||
| 35 | struct intel_memory_region *mr; | ||
| 36 | int id; | ||
| 37 | |||
| 38 | /* XXX: consider maybe converting to an rb tree at some point */ | ||
| 39 | for_each_memory_region(mr, i915, id) { | ||
| 40 | if (mr->type == class && mr->instance == instance) | ||
| 41 | return mr; | ||
| 42 | } | ||
| 43 | |||
| 44 | return NULL; | ||
| 45 | } | ||
| 46 | |||
| 31 | struct intel_memory_region * | 47 | struct intel_memory_region * |
| 32 | intel_memory_region_by_type(struct drm_i915_private *i915, | 48 | intel_memory_region_by_type(struct drm_i915_private *i915, |
| 33 | enum intel_memory_type mem_type) | 49 | enum intel_memory_type mem_type) |
| @@ -97,6 +97,10 @@ struct intel_memory_region { · 96 unmodified lines | |||
| 97 | } objects; | 97 | } objects; |
| 98 | }; | 98 | }; |
| 99 | 99 | ||
| 100 | struct intel_memory_region * | ||
| 101 | intel_memory_region_lookup(struct drm_i915_private *i915, | ||
| 102 | u16 class, u16 instance); | ||
| 103 | |||
| 100 | int intel_memory_region_init_buddy(struct intel_memory_region *mem); | 104 | int intel_memory_region_init_buddy(struct intel_memory_region *mem); |
| 101 | void intel_memory_region_release_buddy(struct intel_memory_region *mem); | 105 | void intel_memory_region_release_buddy(struct intel_memory_region *mem); |
| 102 | 106 | ||
| @@ -2616,6 +2616,11 @@ struct drm_i915_gem_create_ext { · 2615 unmodified lines | |||
| 2616 | * | 2616 | * |
| 2617 | * The (page-aligned) allocated size for the object will be returned. | 2617 | * The (page-aligned) allocated size for the object will be returned. |
| 2618 | * | 2618 | * |
| 2619 | * Note that for some devices we have might have further minimum | ||
| 2620 | * page-size restrictions(larger than 4K), like for device local-memory. | ||
| 2621 | * However in general the final size here should always reflect any | ||
| 2622 | * rounding up, if for example using the I915_GEM_CREATE_EXT_MEMORY_REGIONS | ||
| 2623 | * extension to place the object in device local-memory. | ||
| 2619 | */ | 2624 | */ |
| 2620 | __u64 size; | 2625 | __u64 size; |
| 2621 | /** | 2626 | /** |
| @@ -2636,10 +2641,67 @@ struct drm_i915_gem_create_ext { · 14 unmodified lines | |||
| 2636 | * If we don't supply any extensions then we get the same old gem_create | 2641 | * If we don't supply any extensions then we get the same old gem_create |
| 2637 | * behaviour. | 2642 | * behaviour. |
| 2638 | * | 2643 | * |
| 2644 | * For I915_GEM_CREATE_EXT_MEMORY_REGIONS usage see | ||
| 2645 | * struct drm_i915_gem_create_ext_memory_regions. | ||
| 2639 | */ | 2646 | */ |
| 2647 | #define I915_GEM_CREATE_EXT_MEMORY_REGIONS 0 | ||
| 2640 | __u64 extensions; | 2648 | __u64 extensions; |
| 2641 | }; | 2649 | }; |
| 2642 | 2650 | ||
| 2651 | /** | ||
| 2652 | * struct drm_i915_gem_create_ext_memory_regions - The | ||
| 2653 | * I915_GEM_CREATE_EXT_MEMORY_REGIONS extension. | ||
| 2654 | * | ||
| 2655 | * Set the object with the desired set of placements/regions in priority | ||
| 2656 | * order. Each entry must be unique and supported by the device. | ||
| 2657 | * | ||
| 2658 | * This is provided as an array of struct drm_i915_gem_memory_class_instance, or | ||
| 2659 | * an equivalent layout of class:instance pair encodings. See struct | ||
| 2660 | * drm_i915_query_memory_regions and DRM_I915_QUERY_MEMORY_REGIONS for how to | ||
| 2661 | * query the supported regions for a device. | ||
| 2662 | * | ||
| 2663 | * As an example, on discrete devices, if we wish to set the placement as | ||
| 2664 | * device local-memory we can do something like: | ||
| 2665 | * | ||
| 2666 | * .. code-block:: C | ||
| 2667 | * | ||
| 2668 | * struct drm_i915_gem_memory_class_instance region_lmem = { | ||
| 2669 | * .memory_class = I915_MEMORY_CLASS_DEVICE, | ||
| 2670 | * .memory_instance = 0, | ||
| 2671 | * }; | ||
| 2672 | * struct drm_i915_gem_create_ext_memory_regions regions = { | ||
| 2673 | * .base = { .name = I915_GEM_CREATE_EXT_MEMORY_REGIONS }, | ||
| 2674 | * .regions = (uintptr_t)®ion_lmem, | ||
| 2675 | * .num_regions = 1, | ||
| 2676 | * }; | ||
| 2677 | * struct drm_i915_gem_create_ext create_ext = { | ||
| 2678 | * .size = 16 * PAGE_SIZE, | ||
| 2679 | * .extensions = (uintptr_t)®ions, | ||
| 2680 | * }; | ||
| 2681 | * | ||
| 2682 | * int err = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext); | ||
| 2683 | * if (err) ... | ||
| 2684 | * | ||
| 2685 | * At which point we get the object handle in &drm_i915_gem_create_ext.handle, | ||
| 2686 | * along with the final object size in &drm_i915_gem_create_ext.size, which | ||
| 2687 | * should account for any rounding up, if required. | ||
| 2688 | */ | ||
| 2689 | struct drm_i915_gem_create_ext_memory_regions { | ||
| 2690 | /** @base: Extension link. See struct i915_user_extension. */ | ||
| 2691 | struct i915_user_extension base; | ||
| 2692 | |||
| 2693 | /** @pad: MBZ */ | ||
| 2694 | __u32 pad; | ||
| 2695 | /** @num_regions: Number of elements in the @regions array. */ | ||
| 2696 | __u32 num_regions; | ||
| 2697 | /** | ||
| 2698 | * @regions: The regions/placements array. | ||
| 2699 | * | ||
| 2700 | * An array of struct drm_i915_gem_memory_class_instance. | ||
| 2701 | */ | ||
| 2702 | __u64 regions; | ||
| 2703 | }; | ||
| 2704 | |||
| 2643 | #if defined(__cplusplus) | 2705 | #if defined(__cplusplus) |
| 2644 | } | 2706 | } |
| 2645 | #endif | 2707 | #endif |