2017-02-13 17:15:17 +00:00
/*
* Copyright © 2016 Intel Corporation
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE .
*
*/
2017-07-18 18:30:28 +01:00
# include <linux/pm_domain.h>
2017-02-13 17:15:17 +00:00
# include <linux/pm_runtime.h>
2017-02-13 17:15:19 +00:00
# include "mock_engine.h"
# include "mock_context.h"
# include "mock_request.h"
2017-02-13 17:15:17 +00:00
# include "mock_gem_device.h"
# include "mock_gem_object.h"
2017-02-13 17:15:18 +00:00
# include "mock_gtt.h"
2017-04-12 10:21:43 +01:00
# include "mock_uncore.h"
2017-02-13 17:15:17 +00:00
2017-02-13 17:15:19 +00:00
void mock_device_flush ( struct drm_i915_private * i915 )
{
struct intel_engine_cs * engine ;
enum intel_engine_id id ;
lockdep_assert_held ( & i915 - > drm . struct_mutex ) ;
for_each_engine ( engine , i915 , id )
mock_engine_flush ( engine ) ;
i915_gem_retire_requests ( i915 ) ;
}
2017-02-13 17:15:17 +00:00
static void mock_device_release ( struct drm_device * dev )
{
struct drm_i915_private * i915 = to_i915 ( dev ) ;
2017-02-13 17:15:19 +00:00
struct intel_engine_cs * engine ;
enum intel_engine_id id ;
mutex_lock ( & i915 - > drm . struct_mutex ) ;
mock_device_flush ( i915 ) ;
2017-07-19 14:59:57 +01:00
i915_gem_contexts_lost ( i915 ) ;
2017-02-13 17:15:19 +00:00
mutex_unlock ( & i915 - > drm . struct_mutex ) ;
2017-02-13 17:15:17 +00:00
2017-02-13 17:15:19 +00:00
cancel_delayed_work_sync ( & i915 - > gt . retire_work ) ;
cancel_delayed_work_sync ( & i915 - > gt . idle_work ) ;
2017-07-18 14:41:24 +01:00
i915_gem_drain_workqueue ( i915 ) ;
2017-02-13 17:15:19 +00:00
mutex_lock ( & i915 - > drm . struct_mutex ) ;
for_each_engine ( engine , i915 , id )
mock_engine_free ( engine ) ;
2017-06-20 12:05:45 +01:00
i915_gem_contexts_fini ( i915 ) ;
2017-02-13 17:15:19 +00:00
mutex_unlock ( & i915 - > drm . struct_mutex ) ;
drain_workqueue ( i915 - > wq ) ;
2017-02-13 17:15:17 +00:00
i915_gem_drain_freed_objects ( i915 ) ;
2017-02-13 17:15:18 +00:00
mutex_lock ( & i915 - > drm . struct_mutex ) ;
mock_fini_ggtt ( i915 ) ;
i915_gem_timeline_fini ( & i915 - > gt . global_timeline ) ;
mutex_unlock ( & i915 - > drm . struct_mutex ) ;
2017-02-13 17:15:19 +00:00
destroy_workqueue ( i915 - > wq ) ;
2017-05-17 13:10:04 +01:00
kmem_cache_destroy ( i915 - > priorities ) ;
2017-02-13 17:15:19 +00:00
kmem_cache_destroy ( i915 - > dependencies ) ;
kmem_cache_destroy ( i915 - > requests ) ;
2017-02-13 17:15:18 +00:00
kmem_cache_destroy ( i915 - > vmas ) ;
2017-02-13 17:15:17 +00:00
kmem_cache_destroy ( i915 - > objects ) ;
drm_dev_fini ( & i915 - > drm ) ;
put_device ( & i915 - > drm . pdev - > dev ) ;
}
static struct drm_driver mock_driver = {
. name = " mock " ,
. driver_features = DRIVER_GEM ,
. release = mock_device_release ,
. gem_close_object = i915_gem_close_object ,
. gem_free_object_unlocked = i915_gem_free_object ,
} ;
static void release_dev ( struct device * dev )
{
struct pci_dev * pdev = to_pci_dev ( dev ) ;
kfree ( pdev ) ;
}
2017-02-13 17:15:19 +00:00
static void mock_retire_work_handler ( struct work_struct * work )
{
}
static void mock_idle_work_handler ( struct work_struct * work )
{
}
2017-07-18 18:30:28 +01:00
static int pm_domain_resume ( struct device * dev )
{
return pm_generic_runtime_resume ( dev ) ;
}
static int pm_domain_suspend ( struct device * dev )
{
return pm_generic_runtime_suspend ( dev ) ;
}
static struct dev_pm_domain pm_domain = {
. ops = {
. runtime_suspend = pm_domain_suspend ,
. runtime_resume = pm_domain_resume ,
} ,
} ;
2017-02-13 17:15:17 +00:00
struct drm_i915_private * mock_gem_device ( void )
{
struct drm_i915_private * i915 ;
2017-02-13 17:15:19 +00:00
struct intel_engine_cs * engine ;
enum intel_engine_id id ;
2017-02-13 17:15:17 +00:00
struct pci_dev * pdev ;
int err ;
pdev = kzalloc ( sizeof ( * pdev ) + sizeof ( * i915 ) , GFP_KERNEL ) ;
if ( ! pdev )
goto err ;
device_initialize ( & pdev - > dev ) ;
2017-05-18 10:46:15 +01:00
pdev - > class = PCI_BASE_CLASS_DISPLAY < < 16 ;
2017-02-13 17:15:17 +00:00
pdev - > dev . release = release_dev ;
dev_set_name ( & pdev - > dev , " mock " ) ;
dma_coerce_mask_and_coherent ( & pdev - > dev , DMA_BIT_MASK ( 32 ) ) ;
2017-09-18 17:46:52 +01:00
# if IS_ENABLED(CONFIG_IOMMU_API)
2017-09-14 17:22:40 +01:00
/* hack to disable iommu for the fake device; force identity mapping */
pdev - > dev . archdata . iommu = ( void * ) - 1 ;
2017-09-18 17:46:52 +01:00
# endif
2017-09-14 17:22:40 +01:00
2017-07-18 18:30:28 +01:00
dev_pm_domain_set ( & pdev - > dev , & pm_domain ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2017-02-13 17:15:17 +00:00
pm_runtime_dont_use_autosuspend ( & pdev - > dev ) ;
2017-07-18 18:30:28 +01:00
WARN_ON ( pm_runtime_get_sync ( & pdev - > dev ) ) ;
2017-02-13 17:15:17 +00:00
i915 = ( struct drm_i915_private * ) ( pdev + 1 ) ;
pci_set_drvdata ( pdev , i915 ) ;
err = drm_dev_init ( & i915 - > drm , & mock_driver , & pdev - > dev ) ;
if ( err ) {
pr_err ( " Failed to initialise mock GEM device: err=%d \n " , err ) ;
goto put_device ;
}
i915 - > drm . pdev = pdev ;
i915 - > drm . dev_private = i915 ;
2017-02-13 17:15:18 +00:00
/* Using the global GTT may ask questions about KMS users, so prepare */
drm_mode_config_init ( & i915 - > drm ) ;
2017-02-13 17:15:17 +00:00
mkwrite_device_info ( i915 ) - > gen = - 1 ;
spin_lock_init ( & i915 - > mm . object_stat_lock ) ;
2017-04-12 10:21:43 +01:00
mock_uncore_init ( i915 ) ;
2017-02-13 17:15:17 +00:00
2017-02-13 17:15:19 +00:00
init_waitqueue_head ( & i915 - > gpu_error . wait_queue ) ;
init_waitqueue_head ( & i915 - > gpu_error . reset_queue ) ;
i915 - > wq = alloc_ordered_workqueue ( " mock " , 0 ) ;
if ( ! i915 - > wq )
goto put_device ;
2017-02-13 17:15:17 +00:00
INIT_WORK ( & i915 - > mm . free_work , __i915_gem_free_work ) ;
init_llist_head ( & i915 - > mm . free_list ) ;
2017-02-13 17:15:18 +00:00
INIT_LIST_HEAD ( & i915 - > mm . unbound_list ) ;
INIT_LIST_HEAD ( & i915 - > mm . bound_list ) ;
2017-02-13 17:15:17 +00:00
2017-06-20 12:05:46 +01:00
mock_init_contexts ( i915 ) ;
2017-02-13 17:15:19 +00:00
INIT_DELAYED_WORK ( & i915 - > gt . retire_work , mock_retire_work_handler ) ;
INIT_DELAYED_WORK ( & i915 - > gt . idle_work , mock_idle_work_handler ) ;
i915 - > gt . awake = true ;
2017-02-13 17:15:17 +00:00
i915 - > objects = KMEM_CACHE ( mock_object , SLAB_HWCACHE_ALIGN ) ;
if ( ! i915 - > objects )
2017-02-13 17:15:19 +00:00
goto err_wq ;
2017-02-13 17:15:17 +00:00
2017-02-13 17:15:18 +00:00
i915 - > vmas = KMEM_CACHE ( i915_vma , SLAB_HWCACHE_ALIGN ) ;
if ( ! i915 - > vmas )
goto err_objects ;
2017-02-13 17:15:19 +00:00
i915 - > requests = KMEM_CACHE ( mock_request ,
SLAB_HWCACHE_ALIGN |
SLAB_RECLAIM_ACCOUNT |
2017-05-10 09:50:55 -07:00
SLAB_TYPESAFE_BY_RCU ) ;
2017-02-13 17:15:19 +00:00
if ( ! i915 - > requests )
goto err_vmas ;
i915 - > dependencies = KMEM_CACHE ( i915_dependency ,
SLAB_HWCACHE_ALIGN |
SLAB_RECLAIM_ACCOUNT ) ;
if ( ! i915 - > dependencies )
goto err_requests ;
2017-05-17 13:10:04 +01:00
i915 - > priorities = KMEM_CACHE ( i915_priolist , SLAB_HWCACHE_ALIGN ) ;
if ( ! i915 - > priorities )
goto err_dependencies ;
2017-02-13 17:15:18 +00:00
mutex_lock ( & i915 - > drm . struct_mutex ) ;
INIT_LIST_HEAD ( & i915 - > gt . timelines ) ;
err = i915_gem_timeline_init__global ( i915 ) ;
if ( err ) {
mutex_unlock ( & i915 - > drm . struct_mutex ) ;
2017-05-17 13:10:04 +01:00
goto err_priorities ;
2017-02-13 17:15:18 +00:00
}
mock_init_ggtt ( i915 ) ;
mutex_unlock ( & i915 - > drm . struct_mutex ) ;
2017-02-13 17:15:19 +00:00
mkwrite_device_info ( i915 ) - > ring_mask = BIT ( 0 ) ;
2017-08-09 17:39:30 +01:00
i915 - > engine [ RCS ] = mock_engine ( i915 , " mock " , RCS ) ;
2017-02-13 17:15:19 +00:00
if ( ! i915 - > engine [ RCS ] )
2017-07-20 00:35:03 +02:00
goto err_priorities ;
2017-02-13 17:15:19 +00:00
i915 - > kernel_context = mock_context ( i915 , NULL ) ;
if ( ! i915 - > kernel_context )
goto err_engine ;
2017-10-05 11:59:27 +01:00
i915 - > preempt_context = mock_context ( i915 , NULL ) ;
if ( ! i915 - > preempt_context )
goto err_kernel_context ;
2017-02-13 17:15:17 +00:00
return i915 ;
2017-10-05 11:59:27 +01:00
err_kernel_context :
i915_gem_context_put ( i915 - > kernel_context ) ;
2017-02-13 17:15:19 +00:00
err_engine :
for_each_engine ( engine , i915 , id )
mock_engine_free ( engine ) ;
2017-05-17 13:10:04 +01:00
err_priorities :
kmem_cache_destroy ( i915 - > priorities ) ;
2017-02-13 17:15:19 +00:00
err_dependencies :
kmem_cache_destroy ( i915 - > dependencies ) ;
err_requests :
kmem_cache_destroy ( i915 - > requests ) ;
2017-02-13 17:15:18 +00:00
err_vmas :
kmem_cache_destroy ( i915 - > vmas ) ;
err_objects :
kmem_cache_destroy ( i915 - > objects ) ;
2017-02-13 17:15:19 +00:00
err_wq :
destroy_workqueue ( i915 - > wq ) ;
2017-02-13 17:15:17 +00:00
put_device :
put_device ( & pdev - > dev ) ;
err :
return NULL ;
}