Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2016 Intel Corporation
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice (including the next
0012  * paragraph) shall be included in all copies or substantial portions of the
0013  * Software.
0014  *
0015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0020  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
0021  * IN THE SOFTWARE.
0022  *
0023  */
0024 
0025 #include <linux/pm_domain.h>
0026 #include <linux/pm_runtime.h>
0027 #include <linux/iommu.h>
0028 
0029 #include <drm/drm_managed.h>
0030 
0031 #include "gt/intel_gt.h"
0032 #include "gt/intel_gt_requests.h"
0033 #include "gt/mock_engine.h"
0034 #include "intel_memory_region.h"
0035 #include "intel_region_ttm.h"
0036 
0037 #include "mock_request.h"
0038 #include "mock_gem_device.h"
0039 #include "mock_gtt.h"
0040 #include "mock_uncore.h"
0041 #include "mock_region.h"
0042 
0043 #include "gem/selftests/mock_context.h"
0044 #include "gem/selftests/mock_gem_object.h"
0045 
0046 void mock_device_flush(struct drm_i915_private *i915)
0047 {
0048     struct intel_gt *gt = to_gt(i915);
0049     struct intel_engine_cs *engine;
0050     enum intel_engine_id id;
0051 
0052     do {
0053         for_each_engine(engine, gt, id)
0054             mock_engine_flush(engine);
0055     } while (intel_gt_retire_requests_timeout(gt, MAX_SCHEDULE_TIMEOUT,
0056                           NULL));
0057 }
0058 
0059 static void mock_device_release(struct drm_device *dev)
0060 {
0061     struct drm_i915_private *i915 = to_i915(dev);
0062 
0063     if (!i915->do_release)
0064         goto out;
0065 
0066     mock_device_flush(i915);
0067     intel_gt_driver_remove(to_gt(i915));
0068 
0069     i915_gem_drain_workqueue(i915);
0070     i915_gem_drain_freed_objects(i915);
0071 
0072     mock_fini_ggtt(to_gt(i915)->ggtt);
0073     destroy_workqueue(i915->wq);
0074 
0075     intel_region_ttm_device_fini(i915);
0076     intel_gt_driver_late_release_all(i915);
0077     intel_memory_regions_driver_release(i915);
0078 
0079     drm_mode_config_cleanup(&i915->drm);
0080 
0081 out:
0082     i915_params_free(&i915->params);
0083 }
0084 
0085 static const struct drm_driver mock_driver = {
0086     .name = "mock",
0087     .driver_features = DRIVER_GEM,
0088     .release = mock_device_release,
0089 };
0090 
0091 static void release_dev(struct device *dev)
0092 {
0093     struct pci_dev *pdev = to_pci_dev(dev);
0094 
0095     kfree(pdev);
0096 }
0097 
0098 static int pm_domain_resume(struct device *dev)
0099 {
0100     return pm_generic_runtime_resume(dev);
0101 }
0102 
0103 static int pm_domain_suspend(struct device *dev)
0104 {
0105     return pm_generic_runtime_suspend(dev);
0106 }
0107 
0108 static struct dev_pm_domain pm_domain = {
0109     .ops = {
0110         .runtime_suspend = pm_domain_suspend,
0111         .runtime_resume = pm_domain_resume,
0112     },
0113 };
0114 
0115 static void mock_gt_probe(struct drm_i915_private *i915)
0116 {
0117     i915->gt[0] = &i915->gt0;
0118 }
0119 
0120 struct drm_i915_private *mock_gem_device(void)
0121 {
0122 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
0123     static struct dev_iommu fake_iommu = { .priv = (void *)-1 };
0124 #endif
0125     struct drm_i915_private *i915;
0126     struct pci_dev *pdev;
0127     int ret;
0128 
0129     pdev = kzalloc(sizeof(*pdev), GFP_KERNEL);
0130     if (!pdev)
0131         return NULL;
0132     device_initialize(&pdev->dev);
0133     pdev->class = PCI_BASE_CLASS_DISPLAY << 16;
0134     pdev->dev.release = release_dev;
0135     dev_set_name(&pdev->dev, "mock");
0136     dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
0137 
0138 #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU)
0139     /* HACK to disable iommu for the fake device; force identity mapping */
0140     pdev->dev.iommu = &fake_iommu;
0141 #endif
0142     if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
0143         put_device(&pdev->dev);
0144         return NULL;
0145     }
0146 
0147     i915 = devm_drm_dev_alloc(&pdev->dev, &mock_driver,
0148                   struct drm_i915_private, drm);
0149     if (IS_ERR(i915)) {
0150         pr_err("Failed to allocate mock GEM device: err=%ld\n", PTR_ERR(i915));
0151         devres_release_group(&pdev->dev, NULL);
0152         put_device(&pdev->dev);
0153 
0154         return NULL;
0155     }
0156 
0157     pci_set_drvdata(pdev, i915);
0158 
0159     dev_pm_domain_set(&pdev->dev, &pm_domain);
0160     pm_runtime_enable(&pdev->dev);
0161     pm_runtime_dont_use_autosuspend(&pdev->dev);
0162     if (pm_runtime_enabled(&pdev->dev))
0163         WARN_ON(pm_runtime_get_sync(&pdev->dev));
0164 
0165 
0166     i915_params_copy(&i915->params, &i915_modparams);
0167 
0168     intel_runtime_pm_init_early(&i915->runtime_pm);
0169     /* wakeref tracking has significant overhead */
0170     i915->runtime_pm.no_wakeref_tracking = true;
0171 
0172     /* Using the global GTT may ask questions about KMS users, so prepare */
0173     drm_mode_config_init(&i915->drm);
0174 
0175     mkwrite_device_info(i915)->graphics.ver = -1;
0176 
0177     mkwrite_device_info(i915)->page_sizes =
0178         I915_GTT_PAGE_SIZE_4K |
0179         I915_GTT_PAGE_SIZE_64K |
0180         I915_GTT_PAGE_SIZE_2M;
0181 
0182     mkwrite_device_info(i915)->memory_regions = REGION_SMEM;
0183     intel_memory_regions_hw_probe(i915);
0184 
0185     spin_lock_init(&i915->gpu_error.lock);
0186 
0187     i915_gem_init__mm(i915);
0188     intel_root_gt_init_early(i915);
0189     mock_uncore_init(&i915->uncore, i915);
0190     atomic_inc(&to_gt(i915)->wakeref.count); /* disable; no hw support */
0191     to_gt(i915)->awake = -ENODEV;
0192     mock_gt_probe(i915);
0193 
0194     ret = intel_region_ttm_device_init(i915);
0195     if (ret)
0196         goto err_ttm;
0197 
0198     i915->wq = alloc_ordered_workqueue("mock", 0);
0199     if (!i915->wq)
0200         goto err_drv;
0201 
0202     mock_init_contexts(i915);
0203 
0204     /* allocate the ggtt */
0205     ret = intel_gt_assign_ggtt(to_gt(i915));
0206     if (ret)
0207         goto err_unlock;
0208 
0209     mock_init_ggtt(to_gt(i915));
0210     to_gt(i915)->vm = i915_vm_get(&to_gt(i915)->ggtt->vm);
0211 
0212     mkwrite_device_info(i915)->platform_engine_mask = BIT(0);
0213     to_gt(i915)->info.engine_mask = BIT(0);
0214 
0215     to_gt(i915)->engine[RCS0] = mock_engine(i915, "mock", RCS0);
0216     if (!to_gt(i915)->engine[RCS0])
0217         goto err_unlock;
0218 
0219     if (mock_engine_init(to_gt(i915)->engine[RCS0]))
0220         goto err_context;
0221 
0222     __clear_bit(I915_WEDGED, &to_gt(i915)->reset.flags);
0223     intel_engines_driver_register(i915);
0224 
0225     i915->do_release = true;
0226     ida_init(&i915->selftest.mock_region_instances);
0227 
0228     return i915;
0229 
0230 err_context:
0231     intel_gt_driver_remove(to_gt(i915));
0232 err_unlock:
0233     destroy_workqueue(i915->wq);
0234 err_drv:
0235     intel_region_ttm_device_fini(i915);
0236 err_ttm:
0237     intel_gt_driver_late_release_all(i915);
0238     intel_memory_regions_driver_release(i915);
0239     drm_mode_config_cleanup(&i915->drm);
0240     mock_destroy_device(i915);
0241 
0242     return NULL;
0243 }
0244 
0245 void mock_destroy_device(struct drm_i915_private *i915)
0246 {
0247     struct device *dev = i915->drm.dev;
0248 
0249     devres_release_group(dev, NULL);
0250     put_device(dev);
0251 }