1 | // SPDX-License-Identifier: MIT |
2 | /* |
3 | * Copyright © 2019-2021 Intel Corporation |
4 | */ |
5 | |
6 | #include <drm/ttm/ttm_placement.h> |
7 | #include <linux/scatterlist.h> |
8 | |
9 | #include "gem/i915_gem_region.h" |
10 | #include "intel_memory_region.h" |
11 | #include "intel_region_ttm.h" |
12 | |
13 | #include "mock_region.h" |
14 | |
15 | static void mock_region_put_pages(struct drm_i915_gem_object *obj, |
16 | struct sg_table *pages) |
17 | { |
18 | i915_refct_sgt_put(rsgt: obj->mm.rsgt); |
19 | obj->mm.rsgt = NULL; |
20 | intel_region_ttm_resource_free(mem: obj->mm.region, res: obj->mm.res); |
21 | } |
22 | |
23 | static int mock_region_get_pages(struct drm_i915_gem_object *obj) |
24 | { |
25 | struct sg_table *pages; |
26 | int err; |
27 | |
28 | obj->mm.res = intel_region_ttm_resource_alloc(mem: obj->mm.region, |
29 | offset: obj->bo_offset, |
30 | size: obj->base.size, |
31 | flags: obj->flags); |
32 | if (IS_ERR(ptr: obj->mm.res)) |
33 | return PTR_ERR(ptr: obj->mm.res); |
34 | |
35 | obj->mm.rsgt = intel_region_ttm_resource_to_rsgt(mem: obj->mm.region, |
36 | res: obj->mm.res, |
37 | page_alignment: obj->mm.region->min_page_size); |
38 | if (IS_ERR(ptr: obj->mm.rsgt)) { |
39 | err = PTR_ERR(ptr: obj->mm.rsgt); |
40 | goto err_free_resource; |
41 | } |
42 | |
43 | pages = &obj->mm.rsgt->table; |
44 | __i915_gem_object_set_pages(obj, pages); |
45 | |
46 | return 0; |
47 | |
48 | err_free_resource: |
49 | intel_region_ttm_resource_free(mem: obj->mm.region, res: obj->mm.res); |
50 | return err; |
51 | } |
52 | |
53 | static const struct drm_i915_gem_object_ops mock_region_obj_ops = { |
54 | .name = "mock-region" , |
55 | .get_pages = mock_region_get_pages, |
56 | .put_pages = mock_region_put_pages, |
57 | .release = i915_gem_object_release_memory_region, |
58 | }; |
59 | |
60 | static int mock_object_init(struct intel_memory_region *mem, |
61 | struct drm_i915_gem_object *obj, |
62 | resource_size_t offset, |
63 | resource_size_t size, |
64 | resource_size_t page_size, |
65 | unsigned int flags) |
66 | { |
67 | static struct lock_class_key lock_class; |
68 | struct drm_i915_private *i915 = mem->i915; |
69 | |
70 | if (size > resource_size(res: &mem->region)) |
71 | return -E2BIG; |
72 | |
73 | drm_gem_private_object_init(dev: &i915->drm, obj: &obj->base, size); |
74 | i915_gem_object_init(obj, ops: &mock_region_obj_ops, key: &lock_class, alloc_flags: flags); |
75 | |
76 | obj->bo_offset = offset; |
77 | |
78 | obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; |
79 | |
80 | i915_gem_object_set_cache_coherency(obj, cache_level: I915_CACHE_NONE); |
81 | |
82 | i915_gem_object_init_memory_region(obj, mem); |
83 | |
84 | return 0; |
85 | } |
86 | |
87 | static int mock_region_fini(struct intel_memory_region *mem) |
88 | { |
89 | struct drm_i915_private *i915 = mem->i915; |
90 | int instance = mem->instance; |
91 | int ret; |
92 | |
93 | ret = intel_region_ttm_fini(mem); |
94 | ida_free(&i915->selftest.mock_region_instances, id: instance); |
95 | |
96 | return ret; |
97 | } |
98 | |
99 | static const struct intel_memory_region_ops mock_region_ops = { |
100 | .init = intel_region_ttm_init, |
101 | .release = mock_region_fini, |
102 | .init_object = mock_object_init, |
103 | }; |
104 | |
105 | struct intel_memory_region * |
106 | mock_region_create(struct drm_i915_private *i915, |
107 | resource_size_t start, |
108 | resource_size_t size, |
109 | resource_size_t min_page_size, |
110 | resource_size_t io_start, |
111 | resource_size_t io_size) |
112 | { |
113 | int instance = ida_alloc_max(ida: &i915->selftest.mock_region_instances, |
114 | TTM_NUM_MEM_TYPES - TTM_PL_PRIV - 1, |
115 | GFP_KERNEL); |
116 | |
117 | if (instance < 0) |
118 | return ERR_PTR(error: instance); |
119 | |
120 | return intel_memory_region_create(i915, start, size, min_page_size, |
121 | io_start, io_size, |
122 | type: INTEL_MEMORY_MOCK, instance, |
123 | ops: &mock_region_ops); |
124 | } |
125 | |