mock_gem_device.c 7.0 KB

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