@@ -4257,10 +4257,8 @@ dxgkio_change_vidmem_reservation(struct dxgprocess *process, void *__user inargs
42574257 }
42584258
42594259 ret = dxgadapter_acquire_lock_shared (adapter );
4260- if (ret < 0 ) {
4261- adapter = NULL ;
4260+ if (ret < 0 )
42624261 goto cleanup ;
4263- }
42644262 adapter_locked = true;
42654263 args .adapter .v = 0 ;
42664264 ret = dxgvmb_send_change_vidmem_reservation (process , adapter ,
@@ -4299,10 +4297,8 @@ dxgkio_query_clock_calibration(struct dxgprocess *process, void *__user inargs)
42994297 }
43004298
43014299 ret = dxgadapter_acquire_lock_shared (adapter );
4302- if (ret < 0 ) {
4303- adapter = NULL ;
4300+ if (ret < 0 )
43044301 goto cleanup ;
4305- }
43064302 adapter_locked = true;
43074303
43084304 args .adapter = adapter -> host_handle ;
@@ -4349,10 +4345,8 @@ dxgkio_flush_heap_transitions(struct dxgprocess *process, void *__user inargs)
43494345 }
43504346
43514347 ret = dxgadapter_acquire_lock_shared (adapter );
4352- if (ret < 0 ) {
4353- adapter = NULL ;
4348+ if (ret < 0 )
43544349 goto cleanup ;
4355- }
43564350 adapter_locked = true;
43574351
43584352 args .adapter = adapter -> host_handle ;
@@ -4417,6 +4411,134 @@ dxgkio_invalidate_cache(struct dxgprocess *process, void *__user inargs)
44174411 return ret ;
44184412}
44194413
4414+ static int
4415+ build_test_command_buffer (struct dxgprocess * process ,
4416+ struct dxgadapter * adapter ,
4417+ struct d3dkmt_escape * args )
4418+ {
4419+ int ret ;
4420+ struct d3dddi_buildtestcommandbuffer cmd ;
4421+ struct d3dkmt_escape newargs = * args ;
4422+ u32 buf_size ;
4423+ struct d3dddi_buildtestcommandbuffer * buf = NULL ;
4424+ struct d3dddi_buildtestcommandbuffer * __user ucmd ;
4425+
4426+ ucmd = args -> priv_drv_data ;
4427+ if (args -> priv_drv_data_size <
4428+ sizeof (struct d3dddi_buildtestcommandbuffer )) {
4429+ DXG_ERR ("Invalid private data size" );
4430+ return - EINVAL ;
4431+ }
4432+ ret = copy_from_user (& cmd , ucmd , sizeof (cmd ));
4433+ if (ret ) {
4434+ DXG_ERR ("Failed to copy private data" );
4435+ return - EFAULT ;
4436+ }
4437+
4438+ if (cmd .dma_buffer_size < sizeof (u32 ) ||
4439+ cmd .dma_buffer_size > D3DDDI_MAXTESTBUFFERSIZE ||
4440+ cmd .dma_buffer_priv_data_size >
4441+ D3DDDI_MAXTESTBUFFERPRIVATEDRIVERDATASIZE ) {
4442+ DXG_ERR ("Invalid DMA buffer or private data size" );
4443+ return - EINVAL ;
4444+ }
4445+ /* Allocate a new buffer for the escape call */
4446+ buf_size = sizeof (struct d3dddi_buildtestcommandbuffer ) +
4447+ cmd .dma_buffer_size +
4448+ cmd .dma_buffer_priv_data_size ;
4449+ buf = vzalloc (buf_size );
4450+ if (buf == NULL ) {
4451+ ret = - ENOMEM ;
4452+ goto cleanup ;
4453+ }
4454+ * buf = cmd ;
4455+ buf -> dma_buffer = NULL ;
4456+ buf -> dma_buffer_priv_data = NULL ;
4457+
4458+ /* Replace private data in the escape arguments and call the host */
4459+ newargs .priv_drv_data = buf ;
4460+ newargs .priv_drv_data_size = buf_size ;
4461+ ret = dxgvmb_send_escape (process , adapter , & newargs , false);
4462+ if (ret ) {
4463+ DXG_ERR ("Host failed escape" );
4464+ goto cleanup ;
4465+ }
4466+
4467+ ret = copy_to_user (& ucmd -> dma_buffer_size , & buf -> dma_buffer_size ,
4468+ sizeof (u32 ));
4469+ if (ret ) {
4470+ DXG_ERR ("Failed to dma size to user" );
4471+ ret = - EFAULT ;
4472+ goto cleanup ;
4473+ }
4474+ ret = copy_to_user (& ucmd -> dma_buffer_priv_data_size ,
4475+ & buf -> dma_buffer_priv_data_size ,
4476+ sizeof (u32 ));
4477+ if (ret ) {
4478+ DXG_ERR ("Failed to dma private data size to user" );
4479+ ret = - EFAULT ;
4480+ goto cleanup ;
4481+ }
4482+ ret = copy_to_user (cmd .dma_buffer , (char * )buf + sizeof (* buf ),
4483+ buf -> dma_buffer_size );
4484+ if (ret ) {
4485+ DXG_ERR ("Failed to copy dma buffer to user" );
4486+ ret = - EFAULT ;
4487+ goto cleanup ;
4488+ }
4489+ if (buf -> dma_buffer_priv_data_size ) {
4490+ ret = copy_to_user (cmd .dma_buffer_priv_data ,
4491+ (char * )buf + sizeof (* buf ) + cmd .dma_buffer_size ,
4492+ buf -> dma_buffer_priv_data_size );
4493+ if (ret ) {
4494+ DXG_ERR ("Failed to copy private data to user" );
4495+ ret = - EFAULT ;
4496+ goto cleanup ;
4497+ }
4498+ }
4499+
4500+ cleanup :
4501+ if (buf )
4502+ vfree (buf );
4503+ return ret ;
4504+ }
4505+
4506+ static int
4507+ driver_known_escape (struct dxgprocess * process ,
4508+ struct dxgadapter * adapter ,
4509+ struct d3dkmt_escape * args )
4510+ {
4511+ enum d3dkmt_escapetype escape_type ;
4512+ int ret = 0 ;
4513+
4514+ if (args -> priv_drv_data_size < sizeof (enum d3dddi_knownescapetype ))
4515+ {
4516+ DXG_ERR ("Invalid private data size" );
4517+ return - EINVAL ;
4518+ }
4519+ ret = copy_from_user (& escape_type , args -> priv_drv_data ,
4520+ sizeof (escape_type ));
4521+ if (ret ) {
4522+ DXG_ERR ("Failed to read escape type" );
4523+ return - EFAULT ;
4524+ }
4525+ switch (escape_type ) {
4526+ case _D3DDDI_DRIVERESCAPETYPE_TRANSLATEALLOCATIONHANDLE :
4527+ case _D3DDDI_DRIVERESCAPETYPE_TRANSLATERESOURCEHANDLE :
4528+ /*
4529+ * The host and VM handles are the same
4530+ */
4531+ break ;
4532+ case _D3DDDI_DRIVERESCAPETYPE_BUILDTESTCOMMANDBUFFER :
4533+ ret = build_test_command_buffer (process , adapter , args );
4534+ break ;
4535+ default :
4536+ ret = dxgvmb_send_escape (process , adapter , args , true);
4537+ break ;
4538+ }
4539+ return ret ;
4540+ }
4541+
44204542static int
44214543dxgkio_escape (struct dxgprocess * process , void * __user inargs )
44224544{
@@ -4438,14 +4560,17 @@ dxgkio_escape(struct dxgprocess *process, void *__user inargs)
44384560 }
44394561
44404562 ret = dxgadapter_acquire_lock_shared (adapter );
4441- if (ret < 0 ) {
4442- adapter = NULL ;
4563+ if (ret < 0 )
44434564 goto cleanup ;
4444- }
44454565 adapter_locked = true;
44464566
44474567 args .adapter = adapter -> host_handle ;
4448- ret = dxgvmb_send_escape (process , adapter , & args );
4568+
4569+ if (args .type == _D3DKMT_ESCAPE_DRIVERPRIVATE &&
4570+ args .flags .driver_known_escape )
4571+ ret = driver_known_escape (process , adapter , & args );
4572+ else
4573+ ret = dxgvmb_send_escape (process , adapter , & args , true);
44494574
44504575cleanup :
44514576
@@ -4485,10 +4610,8 @@ dxgkio_query_vidmem_info(struct dxgprocess *process, void *__user inargs)
44854610 }
44864611
44874612 ret = dxgadapter_acquire_lock_shared (adapter );
4488- if (ret < 0 ) {
4489- adapter = NULL ;
4613+ if (ret < 0 )
44904614 goto cleanup ;
4491- }
44924615 adapter_locked = true;
44934616
44944617 args .adapter = adapter -> host_handle ;
@@ -5323,9 +5446,9 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
53235446{
53245447 struct d3dkmt_isfeatureenabled args ;
53255448 struct dxgadapter * adapter = NULL ;
5326- struct dxgglobal * dxgglobal = dxggbl ();
53275449 struct d3dkmt_isfeatureenabled * __user uargs = inargs ;
53285450 int ret ;
5451+ bool adapter_locked = false;
53295452
53305453 ret = copy_from_user (& args , inargs , sizeof (args ));
53315454 if (ret ) {
@@ -5340,11 +5463,10 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
53405463 goto cleanup ;
53415464 }
53425465
5343- if (adapter ) {
5344- ret = dxgadapter_acquire_lock_shared (adapter );
5345- if (ret < 0 )
5346- goto cleanup ;
5347- }
5466+ ret = dxgadapter_acquire_lock_shared (adapter );
5467+ if (ret < 0 )
5468+ goto cleanup ;
5469+ adapter_locked = true;
53485470
53495471 ret = dxgvmb_send_is_feature_enabled (adapter , & args );
53505472 if (ret )
@@ -5354,10 +5476,10 @@ dxgkio_is_feature_enabled(struct dxgprocess *process, void *__user inargs)
53545476
53555477cleanup :
53565478
5357- if (adapter ) {
5479+ if (adapter_locked )
53585480 dxgadapter_release_lock_shared (adapter );
5481+ if (adapter )
53595482 kref_put (& adapter -> adapter_kref , dxgadapter_release );
5360- }
53615483
53625484 DXG_TRACE_IOCTL_END (ret );
53635485 return ret ;
0 commit comments