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 | 26 | #include <linux/pm_runtime.h> |
01b9d4e2 | 27 | #include <linux/iommu.h> |
66d9cb5d | 28 | |
7fb81e9d DV |
29 | #include <drm/drm_managed.h> |
30 | ||
24635c51 | 31 | #include "gt/intel_gt.h" |
66101975 | 32 | #include "gt/intel_gt_requests.h" |
112ed2d3 | 33 | #include "gt/mock_engine.h" |
3fc794f2 | 34 | #include "intel_memory_region.h" |
d1487389 | 35 | #include "intel_region_ttm.h" |
112ed2d3 | 36 | |
0daf0113 | 37 | #include "mock_request.h" |
66d9cb5d | 38 | #include "mock_gem_device.h" |
3b5bb0a3 | 39 | #include "mock_gtt.h" |
0757ac8f | 40 | #include "mock_uncore.h" |
232a6eba | 41 | #include "mock_region.h" |
66d9cb5d | 42 | |
10be98a7 CW |
43 | #include "gem/selftests/mock_context.h" |
44 | #include "gem/selftests/mock_gem_object.h" | |
45 | ||
0daf0113 CW |
46 | void mock_device_flush(struct drm_i915_private *i915) |
47 | { | |
8c2699fa | 48 | struct intel_gt *gt = to_gt(i915); |
0daf0113 CW |
49 | struct intel_engine_cs *engine; |
50 | enum intel_engine_id id; | |
51 | ||
79ffac85 | 52 | do { |
6457099a | 53 | for_each_engine(engine, gt, id) |
79ffac85 | 54 | mock_engine_flush(engine); |
b97060a9 MB |
55 | } while (intel_gt_retire_requests_timeout(gt, MAX_SCHEDULE_TIMEOUT, |
56 | NULL)); | |
0daf0113 CW |
57 | } |
58 | ||
66d9cb5d CW |
59 | static void mock_device_release(struct drm_device *dev) |
60 | { | |
61 | struct drm_i915_private *i915 = to_i915(dev); | |
0daf0113 | 62 | |
7fb81e9d DV |
63 | if (!i915->do_release) |
64 | goto out; | |
65 | ||
0daf0113 | 66 | mock_device_flush(i915); |
8c2699fa | 67 | intel_gt_driver_remove(to_gt(i915)); |
66d9cb5d | 68 | |
3b19f16a | 69 | i915_gem_drain_workqueue(i915); |
66d9cb5d | 70 | |
17190a34 | 71 | mock_fini_ggtt(to_gt(i915)->ggtt); |
848a4e5c | 72 | destroy_workqueue(i915->unordered_wq); |
0daf0113 CW |
73 | destroy_workqueue(i915->wq); |
74 | ||
d1487389 | 75 | intel_region_ttm_device_fini(i915); |
bec68cc9 | 76 | intel_gt_driver_late_release_all(i915); |
3fc794f2 | 77 | intel_memory_regions_driver_release(i915); |
3aae9d08 | 78 | |
19553d57 CW |
79 | drm_mode_config_cleanup(&i915->drm); |
80 | ||
7fb81e9d | 81 | out: |
c499f6cb | 82 | i915_params_free(&i915->params); |
66d9cb5d CW |
83 | } |
84 | ||
70a59dd8 | 85 | static const struct drm_driver mock_driver = { |
66d9cb5d CW |
86 | .name = "mock", |
87 | .driver_features = DRIVER_GEM, | |
88 | .release = mock_device_release, | |
66d9cb5d CW |
89 | }; |
90 | ||
91 | static void release_dev(struct device *dev) | |
92 | { | |
93 | struct pci_dev *pdev = to_pci_dev(dev); | |
94 | ||
95 | kfree(pdev); | |
96 | } | |
97 | ||
1a0c1924 CW |
98 | static int pm_domain_resume(struct device *dev) |
99 | { | |
100 | return pm_generic_runtime_resume(dev); | |
101 | } | |
102 | ||
103 | static int pm_domain_suspend(struct device *dev) | |
104 | { | |
105 | return pm_generic_runtime_suspend(dev); | |
106 | } | |
107 | ||
108 | static struct dev_pm_domain pm_domain = { | |
109 | .ops = { | |
110 | .runtime_suspend = pm_domain_suspend, | |
111 | .runtime_resume = pm_domain_resume, | |
112 | }, | |
113 | }; | |
114 | ||
bec68cc9 TU |
115 | static void mock_gt_probe(struct drm_i915_private *i915) |
116 | { | |
70fff19a | 117 | i915->gt[0]->name = "Mock GT"; |
bec68cc9 TU |
118 | } |
119 | ||
ecc7a3ce JN |
120 | static const struct intel_device_info mock_info = { |
121 | .__runtime.graphics.ip.ver = -1, | |
122 | .__runtime.page_sizes = (I915_GTT_PAGE_SIZE_4K | | |
123 | I915_GTT_PAGE_SIZE_64K | | |
124 | I915_GTT_PAGE_SIZE_2M), | |
3797783b | 125 | .memory_regions = BIT(INTEL_REGION_SMEM), |
8776711e | 126 | .platform_engine_mask = BIT(0), |
ecc7a3ce JN |
127 | |
128 | /* simply use legacy cache level for mock device */ | |
129 | .max_pat_index = 3, | |
130 | .cachelevel_to_pat = { | |
131 | [I915_CACHE_NONE] = 0, | |
132 | [I915_CACHE_LLC] = 1, | |
133 | [I915_CACHE_L3_LLC] = 2, | |
134 | [I915_CACHE_WT] = 3, | |
135 | }, | |
136 | }; | |
137 | ||
66d9cb5d CW |
138 | struct drm_i915_private *mock_gem_device(void) |
139 | { | |
c96c8348 | 140 | #if IS_ENABLED(CONFIG_IOMMU_API) && IS_ENABLED(CONFIG_INTEL_IOMMU) |
9f9f4101 | 141 | static struct dev_iommu fake_iommu = { .priv = (void *)-1 }; |
01b9d4e2 | 142 | #endif |
9f9f4101 CW |
143 | struct drm_i915_private *i915; |
144 | struct pci_dev *pdev; | |
d1487389 | 145 | int ret; |
66d9cb5d | 146 | |
7fb81e9d | 147 | pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); |
66d9cb5d | 148 | if (!pdev) |
7fb81e9d | 149 | return NULL; |
66d9cb5d | 150 | device_initialize(&pdev->dev); |
29f31623 | 151 | pdev->class = PCI_BASE_CLASS_DISPLAY << 16; |
66d9cb5d CW |
152 | pdev->dev.release = release_dev; |
153 | dev_set_name(&pdev->dev, "mock"); | |
d58f0083 | 154 | dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); |
66d9cb5d | 155 | |
c96c8348 | 156 | #if IS_ENABLED(CONFIG_IOMMU_API) && IS_ENABLED(CONFIG_INTEL_IOMMU) |
9f9f4101 CW |
157 | /* HACK to disable iommu for the fake device; force identity mapping */ |
158 | pdev->dev.iommu = &fake_iommu; | |
f46f156e | 159 | #endif |
cd01269d DV |
160 | if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) { |
161 | put_device(&pdev->dev); | |
162 | return NULL; | |
163 | } | |
164 | ||
165 | i915 = devm_drm_dev_alloc(&pdev->dev, &mock_driver, | |
166 | struct drm_i915_private, drm); | |
167 | if (IS_ERR(i915)) { | |
168 | pr_err("Failed to allocate mock GEM device: err=%ld\n", PTR_ERR(i915)); | |
169 | devres_release_group(&pdev->dev, NULL); | |
170 | put_device(&pdev->dev); | |
171 | ||
172 | return NULL; | |
173 | } | |
b5891fb5 | 174 | |
83e5af59 | 175 | pci_set_drvdata(pdev, &i915->drm); |
bd780f37 | 176 | |
ecc7a3ce JN |
177 | /* Device parameters start as a copy of module parameters. */ |
178 | i915_params_copy(&i915->params, &i915_modparams); | |
179 | ||
180 | /* Set up device info and initial runtime info. */ | |
181 | intel_device_info_driver_create(i915, pdev->device, &mock_info); | |
182 | ||
b7f48bfd | 183 | intel_display_device_probe(pdev); |
93caca6a | 184 | |
1a0c1924 CW |
185 | dev_pm_domain_set(&pdev->dev, &pm_domain); |
186 | pm_runtime_enable(&pdev->dev); | |
66d9cb5d | 187 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
07e070e1 CW |
188 | if (pm_runtime_enabled(&pdev->dev)) |
189 | WARN_ON(pm_runtime_get_sync(&pdev->dev)); | |
66d9cb5d | 190 | |
69c66355 | 191 | intel_runtime_pm_init_early(&i915->runtime_pm); |
985a0256 VS |
192 | /* wakeref tracking has significant overhead */ |
193 | i915->runtime_pm.no_wakeref_tracking = true; | |
d5b6c275 | 194 | |
3b5bb0a3 CW |
195 | /* Using the global GTT may ask questions about KMS users, so prepare */ |
196 | drm_mode_config_init(&i915->drm); | |
197 | ||
3fc794f2 | 198 | intel_memory_regions_hw_probe(i915); |
da1184cd | 199 | |
9a7fc952 TU |
200 | spin_lock_init(&i915->gpu_error.lock); |
201 | ||
9c52d1c8 | 202 | i915_gem_init__mm(i915); |
bec68cc9 | 203 | intel_root_gt_init_early(i915); |
030def2c | 204 | mock_uncore_init(&i915->uncore, i915); |
8c2699fa | 205 | atomic_inc(&to_gt(i915)->wakeref.count); /* disable; no hw support */ |
61dabe82 | 206 | to_gt(i915)->awake = INTEL_WAKEREF_MOCK_GT; |
bec68cc9 | 207 | mock_gt_probe(i915); |
66d9cb5d | 208 | |
d1487389 TH |
209 | ret = intel_region_ttm_device_init(i915); |
210 | if (ret) | |
211 | goto err_ttm; | |
212 | ||
0daf0113 CW |
213 | i915->wq = alloc_ordered_workqueue("mock", 0); |
214 | if (!i915->wq) | |
19553d57 | 215 | goto err_drv; |
0daf0113 | 216 | |
848a4e5c LC |
217 | i915->unordered_wq = alloc_workqueue("mock-unordered", 0, 0); |
218 | if (!i915->unordered_wq) | |
219 | goto err_wq; | |
220 | ||
5f09a9c8 | 221 | mock_init_contexts(i915); |
0daf0113 | 222 | |
cdeea858 AS |
223 | /* allocate the ggtt */ |
224 | ret = intel_gt_assign_ggtt(to_gt(i915)); | |
225 | if (ret) | |
226 | goto err_unlock; | |
227 | ||
228 | mock_init_ggtt(to_gt(i915)); | |
229 | to_gt(i915)->vm = i915_vm_get(&to_gt(i915)->ggtt->vm); | |
3b5bb0a3 | 230 | |
8c2699fa | 231 | to_gt(i915)->info.engine_mask = BIT(0); |
4a774ee3 | 232 | |
8c2699fa AS |
233 | to_gt(i915)->engine[RCS0] = mock_engine(i915, "mock", RCS0); |
234 | if (!to_gt(i915)->engine[RCS0]) | |
11334c6a CW |
235 | goto err_unlock; |
236 | ||
8c2699fa | 237 | if (mock_engine_init(to_gt(i915)->engine[RCS0])) |
4a774ee3 | 238 | goto err_context; |
0daf0113 | 239 | |
8c2699fa | 240 | __clear_bit(I915_WEDGED, &to_gt(i915)->reset.flags); |
cbb153c5 | 241 | intel_engines_driver_register(i915); |
1d7a99f5 | 242 | |
7fb81e9d | 243 | i915->do_release = true; |
d1487389 | 244 | ida_init(&i915->selftest.mock_region_instances); |
7fb81e9d | 245 | |
66d9cb5d CW |
246 | return i915; |
247 | ||
4a774ee3 | 248 | err_context: |
8c2699fa | 249 | intel_gt_driver_remove(to_gt(i915)); |
1d7a99f5 | 250 | err_unlock: |
848a4e5c LC |
251 | destroy_workqueue(i915->unordered_wq); |
252 | err_wq: | |
0daf0113 | 253 | destroy_workqueue(i915->wq); |
19553d57 | 254 | err_drv: |
d1487389 TH |
255 | intel_region_ttm_device_fini(i915); |
256 | err_ttm: | |
bec68cc9 | 257 | intel_gt_driver_late_release_all(i915); |
3fc794f2 | 258 | intel_memory_regions_driver_release(i915); |
19553d57 | 259 | drm_mode_config_cleanup(&i915->drm); |
82be0d75 | 260 | mock_destroy_device(i915); |
7fb81e9d | 261 | |
66d9cb5d CW |
262 | return NULL; |
263 | } | |
82be0d75 DV |
264 | |
265 | void mock_destroy_device(struct drm_i915_private *i915) | |
266 | { | |
cd01269d DV |
267 | struct device *dev = i915->drm.dev; |
268 | ||
269 | devres_release_group(dev, NULL); | |
270 | put_device(dev); | |
82be0d75 | 271 | } |