mock_gem_device.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. #include <linux/pm_domain.h>
  25. #include <linux/pm_runtime.h>
  26. #include "mock_engine.h"
  27. #include "mock_context.h"
  28. #include "mock_request.h"
  29. #include "mock_gem_device.h"
  30. #include "mock_gem_object.h"
  31. #include "mock_gtt.h"
  32. #include "mock_uncore.h"
  33. void mock_device_flush(struct drm_i915_private *i915)
  34. {
  35. struct intel_engine_cs *engine;
  36. enum intel_engine_id id;
  37. lockdep_assert_held(&i915->drm.struct_mutex);
  38. for_each_engine(engine, i915, id)
  39. mock_engine_flush(engine);
  40. i915_gem_retire_requests(i915);
  41. }
  42. static void mock_device_release(struct drm_device *dev)
  43. {
  44. struct drm_i915_private *i915 = to_i915(dev);
  45. struct intel_engine_cs *engine;
  46. enum intel_engine_id id;
  47. mutex_lock(&i915->drm.struct_mutex);
  48. mock_device_flush(i915);
  49. i915_gem_contexts_lost(i915);
  50. mutex_unlock(&i915->drm.struct_mutex);
  51. cancel_delayed_work_sync(&i915->gt.retire_work);
  52. cancel_delayed_work_sync(&i915->gt.idle_work);
  53. i915_gem_drain_workqueue(i915);
  54. mutex_lock(&i915->drm.struct_mutex);
  55. for_each_engine(engine, i915, id)
  56. mock_engine_free(engine);
  57. i915_gem_contexts_fini(i915);
  58. mutex_unlock(&i915->drm.struct_mutex);
  59. drain_workqueue(i915->wq);
  60. i915_gem_drain_freed_objects(i915);
  61. mutex_lock(&i915->drm.struct_mutex);
  62. mock_fini_ggtt(i915);
  63. i915_gem_timeline_fini(&i915->gt.global_timeline);
  64. mutex_unlock(&i915->drm.struct_mutex);
  65. destroy_workqueue(i915->wq);
  66. kmem_cache_destroy(i915->priorities);
  67. kmem_cache_destroy(i915->dependencies);
  68. kmem_cache_destroy(i915->requests);
  69. kmem_cache_destroy(i915->vmas);
  70. kmem_cache_destroy(i915->objects);
  71. i915_gemfs_fini(i915);
  72. drm_mode_config_cleanup(&i915->drm);
  73. drm_dev_fini(&i915->drm);
  74. put_device(&i915->drm.pdev->dev);
  75. }
  76. static struct drm_driver mock_driver = {
  77. .name = "mock",
  78. .driver_features = DRIVER_GEM,
  79. .release = mock_device_release,
  80. .gem_close_object = i915_gem_close_object,
  81. .gem_free_object_unlocked = i915_gem_free_object,
  82. };
  83. static void release_dev(struct device *dev)
  84. {
  85. struct pci_dev *pdev = to_pci_dev(dev);
  86. kfree(pdev);
  87. }
  88. static void mock_retire_work_handler(struct work_struct *work)
  89. {
  90. }
  91. static void mock_idle_work_handler(struct work_struct *work)
  92. {
  93. }
  94. static int pm_domain_resume(struct device *dev)
  95. {
  96. return pm_generic_runtime_resume(dev);
  97. }
  98. static int pm_domain_suspend(struct device *dev)
  99. {
  100. return pm_generic_runtime_suspend(dev);
  101. }
  102. static struct dev_pm_domain pm_domain = {
  103. .ops = {
  104. .runtime_suspend = pm_domain_suspend,
  105. .runtime_resume = pm_domain_resume,
  106. },
  107. };
  108. struct drm_i915_private *mock_gem_device(void)
  109. {
  110. struct drm_i915_private *i915;
  111. struct intel_engine_cs *engine;
  112. enum intel_engine_id id;
  113. struct pci_dev *pdev;
  114. int err;
  115. pdev = kzalloc(sizeof(*pdev) + sizeof(*i915), GFP_KERNEL);
  116. if (!pdev)
  117. goto err;
  118. device_initialize(&pdev->dev);
  119. pdev->class = PCI_BASE_CLASS_DISPLAY << 16;
  120. pdev->dev.release = release_dev;
  121. dev_set_name(&pdev->dev, "mock");
  122. dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
  123. #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
  124. /* hack to disable iommu for the fake device; force identity mapping */
  125. pdev->dev.archdata.iommu = (void *)-1;
  126. #endif
  127. dev_pm_domain_set(&pdev->dev, &pm_domain);
  128. pm_runtime_enable(&pdev->dev);
  129. pm_runtime_dont_use_autosuspend(&pdev->dev);
  130. WARN_ON(pm_runtime_get_sync(&pdev->dev));
  131. i915 = (struct drm_i915_private *)(pdev + 1);
  132. pci_set_drvdata(pdev, i915);
  133. err = drm_dev_init(&i915->drm, &mock_driver, &pdev->dev);
  134. if (err) {
  135. pr_err("Failed to initialise mock GEM device: err=%d\n", err);
  136. goto put_device;
  137. }
  138. i915->drm.pdev = pdev;
  139. i915->drm.dev_private = i915;
  140. /* Using the global GTT may ask questions about KMS users, so prepare */
  141. drm_mode_config_init(&i915->drm);
  142. mkwrite_device_info(i915)->gen = -1;
  143. mkwrite_device_info(i915)->page_sizes =
  144. I915_GTT_PAGE_SIZE_4K |
  145. I915_GTT_PAGE_SIZE_64K |
  146. I915_GTT_PAGE_SIZE_2M;
  147. mock_uncore_init(i915);
  148. i915_gem_init__mm(i915);
  149. init_waitqueue_head(&i915->gpu_error.wait_queue);
  150. init_waitqueue_head(&i915->gpu_error.reset_queue);
  151. i915->wq = alloc_ordered_workqueue("mock", 0);
  152. if (!i915->wq)
  153. goto err_drv;
  154. mock_init_contexts(i915);
  155. INIT_DELAYED_WORK(&i915->gt.retire_work, mock_retire_work_handler);
  156. INIT_DELAYED_WORK(&i915->gt.idle_work, mock_idle_work_handler);
  157. i915->gt.awake = true;
  158. i915->objects = KMEM_CACHE(mock_object, SLAB_HWCACHE_ALIGN);
  159. if (!i915->objects)
  160. goto err_wq;
  161. i915->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
  162. if (!i915->vmas)
  163. goto err_objects;
  164. i915->requests = KMEM_CACHE(mock_request,
  165. SLAB_HWCACHE_ALIGN |
  166. SLAB_RECLAIM_ACCOUNT |
  167. SLAB_TYPESAFE_BY_RCU);
  168. if (!i915->requests)
  169. goto err_vmas;
  170. i915->dependencies = KMEM_CACHE(i915_dependency,
  171. SLAB_HWCACHE_ALIGN |
  172. SLAB_RECLAIM_ACCOUNT);
  173. if (!i915->dependencies)
  174. goto err_requests;
  175. i915->priorities = KMEM_CACHE(i915_priolist, SLAB_HWCACHE_ALIGN);
  176. if (!i915->priorities)
  177. goto err_dependencies;
  178. mutex_lock(&i915->drm.struct_mutex);
  179. INIT_LIST_HEAD(&i915->gt.timelines);
  180. err = i915_gem_timeline_init__global(i915);
  181. if (err) {
  182. mutex_unlock(&i915->drm.struct_mutex);
  183. goto err_priorities;
  184. }
  185. mock_init_ggtt(i915);
  186. mutex_unlock(&i915->drm.struct_mutex);
  187. mkwrite_device_info(i915)->ring_mask = BIT(0);
  188. i915->engine[RCS] = mock_engine(i915, "mock", RCS);
  189. if (!i915->engine[RCS])
  190. goto err_priorities;
  191. i915->kernel_context = mock_context(i915, NULL);
  192. if (!i915->kernel_context)
  193. goto err_engine;
  194. i915->preempt_context = mock_context(i915, NULL);
  195. if (!i915->preempt_context)
  196. goto err_kernel_context;
  197. WARN_ON(i915_gemfs_init(i915));
  198. return i915;
  199. err_kernel_context:
  200. i915_gem_context_put(i915->kernel_context);
  201. err_engine:
  202. for_each_engine(engine, i915, id)
  203. mock_engine_free(engine);
  204. err_priorities:
  205. kmem_cache_destroy(i915->priorities);
  206. err_dependencies:
  207. kmem_cache_destroy(i915->dependencies);
  208. err_requests:
  209. kmem_cache_destroy(i915->requests);
  210. err_vmas:
  211. kmem_cache_destroy(i915->vmas);
  212. err_objects:
  213. kmem_cache_destroy(i915->objects);
  214. err_wq:
  215. destroy_workqueue(i915->wq);
  216. err_drv:
  217. drm_mode_config_cleanup(&i915->drm);
  218. drm_dev_fini(&i915->drm);
  219. put_device:
  220. put_device(&pdev->dev);
  221. err:
  222. return NULL;
  223. }