Commit | Line | Data |
---|---|---|
66d9cb5d CW |
1 | /* |
2 | * Copyright © 2016 Intel Corporation | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice (including the next | |
12 | * paragraph) shall be included in all copies or substantial portions of the | |
13 | * Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
21 | * IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
1a0c1924 | 25 | #include <linux/pm_domain.h> |
66d9cb5d CW |
26 | #include <linux/pm_runtime.h> |
27 | ||
24635c51 | 28 | #include "gt/intel_gt.h" |
112ed2d3 CW |
29 | #include "gt/mock_engine.h" |
30 | ||
0daf0113 | 31 | #include "mock_request.h" |
66d9cb5d | 32 | #include "mock_gem_device.h" |
3b5bb0a3 | 33 | #include "mock_gtt.h" |
0757ac8f | 34 | #include "mock_uncore.h" |
66d9cb5d | 35 | |
10be98a7 CW |
36 | #include "gem/selftests/mock_context.h" |
37 | #include "gem/selftests/mock_gem_object.h" | |
38 | ||
0daf0113 CW |
39 | void mock_device_flush(struct drm_i915_private *i915) |
40 | { | |
41 | struct intel_engine_cs *engine; | |
42 | enum intel_engine_id id; | |
43 | ||
44 | lockdep_assert_held(&i915->drm.struct_mutex); | |
45 | ||
79ffac85 CW |
46 | do { |
47 | for_each_engine(engine, i915, id) | |
48 | mock_engine_flush(engine); | |
49 | } while (i915_retire_requests(i915)); | |
0daf0113 CW |
50 | } |
51 | ||
66d9cb5d CW |
52 | static void mock_device_release(struct drm_device *dev) |
53 | { | |
54 | struct drm_i915_private *i915 = to_i915(dev); | |
0daf0113 CW |
55 | struct intel_engine_cs *engine; |
56 | enum intel_engine_id id; | |
57 | ||
58 | mutex_lock(&i915->drm.struct_mutex); | |
59 | mock_device_flush(i915); | |
60 | mutex_unlock(&i915->drm.struct_mutex); | |
66d9cb5d | 61 | |
ae230631 | 62 | flush_work(&i915->gem.idle_work); |
3b19f16a | 63 | i915_gem_drain_workqueue(i915); |
0daf0113 CW |
64 | |
65 | mutex_lock(&i915->drm.struct_mutex); | |
66 | for_each_engine(engine, i915, id) | |
67 | mock_engine_free(engine); | |
829a0af2 | 68 | i915_gem_contexts_fini(i915); |
0daf0113 CW |
69 | mutex_unlock(&i915->drm.struct_mutex); |
70 | ||
f0c02c1b | 71 | intel_timelines_fini(i915); |
1e345568 | 72 | |
0daf0113 | 73 | drain_workqueue(i915->wq); |
66d9cb5d CW |
74 | i915_gem_drain_freed_objects(i915); |
75 | ||
3b5bb0a3 | 76 | mutex_lock(&i915->drm.struct_mutex); |
c95e7ce3 | 77 | mock_fini_ggtt(&i915->ggtt); |
3b5bb0a3 CW |
78 | mutex_unlock(&i915->drm.struct_mutex); |
79 | ||
0daf0113 CW |
80 | destroy_workqueue(i915->wq); |
81 | ||
465c403c MA |
82 | i915_gemfs_fini(i915); |
83 | ||
19553d57 CW |
84 | drm_mode_config_cleanup(&i915->drm); |
85 | ||
66d9cb5d CW |
86 | drm_dev_fini(&i915->drm); |
87 | put_device(&i915->drm.pdev->dev); | |
88 | } | |
89 | ||
90 | static struct drm_driver mock_driver = { | |
91 | .name = "mock", | |
92 | .driver_features = DRIVER_GEM, | |
93 | .release = mock_device_release, | |
94 | ||
95 | .gem_close_object = i915_gem_close_object, | |
96 | .gem_free_object_unlocked = i915_gem_free_object, | |
97 | }; | |
98 | ||
99 | static void release_dev(struct device *dev) | |
100 | { | |
101 | struct pci_dev *pdev = to_pci_dev(dev); | |
102 | ||
103 | kfree(pdev); | |
104 | } | |
105 | ||
0daf0113 CW |
106 | static void mock_retire_work_handler(struct work_struct *work) |
107 | { | |
108 | } | |
109 | ||
110 | static void mock_idle_work_handler(struct work_struct *work) | |
111 | { | |
112 | } | |
113 | ||
1a0c1924 CW |
114 | static int pm_domain_resume(struct device *dev) |
115 | { | |
116 | return pm_generic_runtime_resume(dev); | |
117 | } | |
118 | ||
119 | static int pm_domain_suspend(struct device *dev) | |
120 | { | |
121 | return pm_generic_runtime_suspend(dev); | |
122 | } | |
123 | ||
124 | static struct dev_pm_domain pm_domain = { | |
125 | .ops = { | |
126 | .runtime_suspend = pm_domain_suspend, | |
127 | .runtime_resume = pm_domain_resume, | |
128 | }, | |
129 | }; | |
130 | ||
66d9cb5d CW |
131 | struct drm_i915_private *mock_gem_device(void) |
132 | { | |
133 | struct drm_i915_private *i915; | |
134 | struct pci_dev *pdev; | |
135 | int err; | |
136 | ||
137 | pdev = kzalloc(sizeof(*pdev) + sizeof(*i915), GFP_KERNEL); | |
138 | if (!pdev) | |
139 | goto err; | |
140 | ||
141 | device_initialize(&pdev->dev); | |
29f31623 | 142 | pdev->class = PCI_BASE_CLASS_DISPLAY << 16; |
66d9cb5d CW |
143 | pdev->dev.release = release_dev; |
144 | dev_set_name(&pdev->dev, "mock"); | |
d58f0083 | 145 | dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); |
66d9cb5d | 146 | |
764d2997 | 147 | #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) |
b5891fb5 CW |
148 | /* hack to disable iommu for the fake device; force identity mapping */ |
149 | pdev->dev.archdata.iommu = (void *)-1; | |
f46f156e | 150 | #endif |
b5891fb5 | 151 | |
bd780f37 CW |
152 | i915 = (struct drm_i915_private *)(pdev + 1); |
153 | pci_set_drvdata(pdev, i915); | |
154 | ||
1a0c1924 CW |
155 | dev_pm_domain_set(&pdev->dev, &pm_domain); |
156 | pm_runtime_enable(&pdev->dev); | |
66d9cb5d | 157 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
07e070e1 CW |
158 | if (pm_runtime_enabled(&pdev->dev)) |
159 | WARN_ON(pm_runtime_get_sync(&pdev->dev)); | |
66d9cb5d | 160 | |
66d9cb5d CW |
161 | err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev); |
162 | if (err) { | |
163 | pr_err("Failed to initialise mock GEM device: err=%d\n", err); | |
164 | goto put_device; | |
165 | } | |
166 | i915->drm.pdev = pdev; | |
167 | i915->drm.dev_private = i915; | |
168 | ||
69c66355 | 169 | intel_runtime_pm_init_early(&i915->runtime_pm); |
d5b6c275 | 170 | |
3b5bb0a3 CW |
171 | /* Using the global GTT may ask questions about KMS users, so prepare */ |
172 | drm_mode_config_init(&i915->drm); | |
173 | ||
66d9cb5d CW |
174 | mkwrite_device_info(i915)->gen = -1; |
175 | ||
2a9654b2 | 176 | mkwrite_device_info(i915)->page_sizes = |
f1f3f982 | 177 | I915_GTT_PAGE_SIZE_4K | |
a883241c MA |
178 | I915_GTT_PAGE_SIZE_64K | |
179 | I915_GTT_PAGE_SIZE_2M; | |
2a9654b2 | 180 | |
f7de5027 | 181 | mock_uncore_init(&i915->uncore); |
9c52d1c8 | 182 | i915_gem_init__mm(i915); |
724e9564 | 183 | intel_gt_init_early(&i915->gt, i915); |
79ffac85 | 184 | atomic_inc(&i915->gt.wakeref.count); /* disable; no hw support */ |
66d9cb5d | 185 | |
0daf0113 CW |
186 | i915->wq = alloc_ordered_workqueue("mock", 0); |
187 | if (!i915->wq) | |
19553d57 | 188 | goto err_drv; |
0daf0113 | 189 | |
5f09a9c8 | 190 | mock_init_contexts(i915); |
0daf0113 | 191 | |
23c3c3d0 | 192 | INIT_DELAYED_WORK(&i915->gem.retire_work, mock_retire_work_handler); |
ae230631 | 193 | INIT_WORK(&i915->gem.idle_work, mock_idle_work_handler); |
0daf0113 CW |
194 | |
195 | i915->gt.awake = true; | |
196 | ||
f0c02c1b | 197 | intel_timelines_init(i915); |
1e345568 | 198 | |
643b450a | 199 | mutex_lock(&i915->drm.struct_mutex); |
1d7a99f5 | 200 | |
c95e7ce3 | 201 | mock_init_ggtt(i915, &i915->ggtt); |
3b5bb0a3 | 202 | |
8a68d464 | 203 | mkwrite_device_info(i915)->engine_mask = BIT(0); |
4a774ee3 | 204 | |
8a68d464 CW |
205 | i915->engine[RCS0] = mock_engine(i915, "mock", RCS0); |
206 | if (!i915->engine[RCS0]) | |
11334c6a CW |
207 | goto err_unlock; |
208 | ||
209 | i915->kernel_context = mock_context(i915, NULL); | |
210 | if (!i915->kernel_context) | |
211 | goto err_engine; | |
212 | ||
213 | if (mock_engine_init(i915->engine[RCS0])) | |
4a774ee3 | 214 | goto err_context; |
0daf0113 | 215 | |
1d7a99f5 CW |
216 | mutex_unlock(&i915->drm.struct_mutex); |
217 | ||
465c403c MA |
218 | WARN_ON(i915_gemfs_init(i915)); |
219 | ||
66d9cb5d CW |
220 | return i915; |
221 | ||
4a774ee3 CW |
222 | err_context: |
223 | i915_gem_contexts_fini(i915); | |
11334c6a CW |
224 | err_engine: |
225 | mock_engine_free(i915->engine[RCS0]); | |
1d7a99f5 CW |
226 | err_unlock: |
227 | mutex_unlock(&i915->drm.struct_mutex); | |
f0c02c1b | 228 | intel_timelines_fini(i915); |
0daf0113 | 229 | destroy_workqueue(i915->wq); |
19553d57 CW |
230 | err_drv: |
231 | drm_mode_config_cleanup(&i915->drm); | |
232 | drm_dev_fini(&i915->drm); | |
66d9cb5d CW |
233 | put_device: |
234 | put_device(&pdev->dev); | |
235 | err: | |
236 | return NULL; | |
237 | } |