2018-05-07 01:16:26 +02:00
// SPDX-License-Identifier: GPL-2.0 OR MIT
2009-12-10 00:19:58 +00:00
/**************************************************************************
*
2018-05-07 01:16:26 +02:00
* Copyright 2009 - 2015 VMware , Inc . , Palo Alto , CA . , USA
2009-12-10 00:19:58 +00:00
*
* 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 , sub license , 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 NON - INFRINGEMENT . IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS , AUTHORS AND / OR ITS SUPPLIERS 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 .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "vmwgfx_drv.h"
2021-06-09 13:22:59 -04:00
# include "vmwgfx_devcaps.h"
2012-10-02 18:01:07 +01:00
# include <drm/vmwgfx_drm.h>
2011-10-04 20:13:26 +02:00
# include "vmwgfx_kms.h"
2014-01-31 10:21:10 +01:00
2009-12-10 00:19:58 +00:00
int vmw_getparam_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct vmw_private * dev_priv = vmw_priv ( dev ) ;
struct drm_vmw_getparam_arg * param =
( struct drm_vmw_getparam_arg * ) data ;
2014-01-31 10:21:10 +01:00
struct vmw_fpriv * vmw_fp = vmw_fpriv ( file_priv ) ;
2009-12-10 00:19:58 +00:00
switch ( param - > param ) {
case DRM_VMW_PARAM_NUM_STREAMS :
param - > value = vmw_overlay_num_overlays ( dev_priv ) ;
break ;
case DRM_VMW_PARAM_NUM_FREE_STREAMS :
param - > value = vmw_overlay_num_free_overlays ( dev_priv ) ;
break ;
case DRM_VMW_PARAM_3D :
2020-11-18 12:54:19 -05:00
param - > value = vmw_supports_3d ( dev_priv ) ? 1 : 0 ;
2009-12-10 00:19:58 +00:00
break ;
2010-02-09 19:41:55 +00:00
case DRM_VMW_PARAM_HW_CAPS :
param - > value = dev_priv - > capabilities ;
break ;
2018-06-18 16:44:48 -07:00
case DRM_VMW_PARAM_HW_CAPS2 :
param - > value = dev_priv - > capabilities2 ;
break ;
2010-02-09 19:41:55 +00:00
case DRM_VMW_PARAM_FIFO_CAPS :
2021-05-05 15:10:07 -04:00
param - > value = vmw_fifo_caps ( dev_priv ) ;
2010-02-09 19:41:55 +00:00
break ;
2010-10-05 12:43:06 +02:00
case DRM_VMW_PARAM_MAX_FB_SIZE :
2021-06-15 14:23:33 -04:00
param - > value = dev_priv - > max_primary_mem ;
2010-10-05 12:43:06 +02:00
break ;
2011-09-01 20:18:41 +00:00
case DRM_VMW_PARAM_FIFO_HW_VERSION :
{
2014-01-31 10:21:10 +01:00
if ( ( dev_priv - > capabilities & SVGA_CAP_GBOBJECTS ) ) {
param - > value = SVGA3D_HWVERSION_WS8_B1 ;
break ;
}
2011-11-28 13:19:08 +01:00
param - > value =
2020-11-04 13:46:09 -05:00
vmw_fifo_mem_read ( dev_priv ,
2021-05-05 15:10:07 -04:00
( ( vmw_fifo_caps ( dev_priv ) &
2020-11-04 13:46:09 -05:00
SVGA_FIFO_CAP_3D_HWVERSION_REVISED ) ?
SVGA_FIFO_3D_HWVERSION_REVISED :
SVGA_FIFO_3D_HWVERSION ) ) ;
2011-09-01 20:18:41 +00:00
break ;
}
2012-11-21 10:37:20 +01:00
case DRM_VMW_PARAM_MAX_SURF_MEMORY :
2014-01-31 10:21:10 +01:00
if ( ( dev_priv - > capabilities & SVGA_CAP_GBOBJECTS ) & &
! vmw_fp - > gb_aware )
param - > value = dev_priv - > max_mob_pages * PAGE_SIZE / 2 ;
else
param - > value = dev_priv - > memory_size ;
2012-11-21 10:37:20 +01:00
break ;
case DRM_VMW_PARAM_3D_CAPS_SIZE :
2021-06-09 13:22:59 -04:00
param - > value = vmw_devcaps_size ( dev_priv , vmw_fp - > gb_aware ) ;
2012-11-21 10:37:20 +01:00
break ;
2012-11-21 12:34:47 +01:00
case DRM_VMW_PARAM_MAX_MOB_MEMORY :
2014-01-31 10:21:10 +01:00
vmw_fp - > gb_aware = true ;
2012-11-21 12:34:47 +01:00
param - > value = dev_priv - > max_mob_pages * PAGE_SIZE ;
break ;
2014-02-12 12:07:38 +01:00
case DRM_VMW_PARAM_MAX_MOB_SIZE :
param - > value = dev_priv - > max_mob_size ;
break ;
2015-06-26 01:42:06 -07:00
case DRM_VMW_PARAM_SCREEN_TARGET :
param - > value =
( dev_priv - > active_display_unit = = vmw_du_screen_target ) ;
break ;
2015-08-10 10:39:35 -07:00
case DRM_VMW_PARAM_DX :
2018-12-13 11:44:42 -08:00
param - > value = has_sm4_context ( dev_priv ) ;
2015-08-10 10:39:35 -07:00
break ;
2018-06-20 15:09:43 -07:00
case DRM_VMW_PARAM_SM4_1 :
2018-12-13 11:44:42 -08:00
param - > value = has_sm4_1_context ( dev_priv ) ;
2018-06-20 15:09:43 -07:00
break ;
2018-12-13 14:23:46 -08:00
case DRM_VMW_PARAM_SM5 :
param - > value = has_sm5_context ( dev_priv ) ;
break ;
2009-12-10 00:19:58 +00:00
default :
return - EINVAL ;
}
return 0 ;
}
2011-09-01 20:18:41 +00:00
int vmw_get_cap_3d_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct drm_vmw_get_3d_cap_arg * arg =
( struct drm_vmw_get_3d_cap_arg * ) data ;
struct vmw_private * dev_priv = vmw_priv ( dev ) ;
uint32_t size ;
void __user * buffer = ( void __user * ) ( ( unsigned long ) ( arg - > buffer ) ) ;
2021-06-09 13:22:59 -04:00
void * bounce = NULL ;
2011-09-01 20:18:41 +00:00
int ret ;
2014-01-31 10:21:10 +01:00
struct vmw_fpriv * vmw_fp = vmw_fpriv ( file_priv ) ;
2011-09-01 20:18:41 +00:00
2017-03-27 11:15:12 +02:00
if ( unlikely ( arg - > pad64 ! = 0 | | arg - > max_size = = 0 ) ) {
2019-02-11 11:46:27 -08:00
VMW_DEBUG_USER ( " Illegal GET_3D_CAP argument. \n " ) ;
2011-09-01 20:18:41 +00:00
return - EINVAL ;
}
2021-06-09 13:22:59 -04:00
size = vmw_devcaps_size ( dev_priv , vmw_fp - > gb_aware ) ;
if ( unlikely ( size = = 0 ) ) {
DRM_ERROR ( " Failed to figure out the devcaps size (no 3D). \n " ) ;
return - ENOMEM ;
}
2011-09-01 20:18:41 +00:00
if ( arg - > max_size < size )
size = arg - > max_size ;
2014-01-31 10:21:10 +01:00
bounce = vzalloc ( size ) ;
2011-09-01 20:18:41 +00:00
if ( unlikely ( bounce = = NULL ) ) {
DRM_ERROR ( " Failed to allocate bounce buffer for 3D caps. \n " ) ;
return - ENOMEM ;
}
2021-06-09 13:22:59 -04:00
ret = vmw_devcaps_copy ( dev_priv , vmw_fp - > gb_aware , bounce , size ) ;
if ( unlikely ( ret ! = 0 ) )
goto out_err ;
2011-09-01 20:18:41 +00:00
ret = copy_to_user ( buffer , bounce , size ) ;
2012-11-12 11:07:24 +00:00
if ( ret )
ret = - EFAULT ;
2014-01-31 10:21:10 +01:00
out_err :
2011-09-01 20:18:41 +00:00
vfree ( bounce ) ;
if ( unlikely ( ret ! = 0 ) )
DRM_ERROR ( " Failed to report 3D caps info. \n " ) ;
return ret ;
}
2011-10-04 20:13:26 +02:00
int vmw_present_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct ttm_object_file * tfile = vmw_fpriv ( file_priv ) - > tfile ;
struct vmw_private * dev_priv = vmw_priv ( dev ) ;
struct drm_vmw_present_arg * arg =
( struct drm_vmw_present_arg * ) data ;
struct vmw_surface * surface ;
struct drm_vmw_rect __user * clips_ptr ;
struct drm_vmw_rect * clips = NULL ;
2012-12-02 21:53:40 +01:00
struct drm_framebuffer * fb ;
2011-10-04 20:13:26 +02:00
struct vmw_framebuffer * vfb ;
2012-11-20 12:19:35 +00:00
struct vmw_resource * res ;
2011-10-04 20:13:26 +02:00
uint32_t num_clips ;
int ret ;
num_clips = arg - > num_clips ;
2015-04-02 02:39:45 -07:00
clips_ptr = ( struct drm_vmw_rect __user * ) ( unsigned long ) arg - > clips_ptr ;
2011-10-04 20:13:26 +02:00
if ( unlikely ( num_clips = = 0 ) )
return 0 ;
if ( clips_ptr = = NULL ) {
2019-02-11 11:46:27 -08:00
VMW_DEBUG_USER ( " Variable clips_ptr must be specified. \n " ) ;
2011-10-04 20:13:26 +02:00
ret = - EINVAL ;
goto out_clips ;
}
2011-11-29 22:08:00 +01:00
clips = kcalloc ( num_clips , sizeof ( * clips ) , GFP_KERNEL ) ;
2011-10-04 20:13:26 +02:00
if ( clips = = NULL ) {
DRM_ERROR ( " Failed to allocate clip rect list. \n " ) ;
ret = - ENOMEM ;
goto out_clips ;
}
ret = copy_from_user ( clips , clips_ptr , num_clips * sizeof ( * clips ) ) ;
if ( ret ) {
DRM_ERROR ( " Failed to copy clip rects from userspace. \n " ) ;
2011-10-18 09:09:19 +03:00
ret = - EFAULT ;
2011-10-04 20:13:26 +02:00
goto out_no_copy ;
}
2012-12-02 01:48:38 +01:00
drm_modeset_lock_all ( dev ) ;
2011-10-04 20:13:26 +02:00
2017-03-14 23:25:07 -07:00
fb = drm_framebuffer_lookup ( dev , file_priv , arg - > fb_id ) ;
2012-12-02 21:53:40 +01:00
if ( ! fb ) {
2019-02-11 11:46:27 -08:00
VMW_DEBUG_USER ( " Invalid framebuffer id. \n " ) ;
2013-10-17 13:35:06 +03:00
ret = - ENOENT ;
2011-10-04 20:13:26 +02:00
goto out_no_fb ;
}
2012-12-02 21:53:40 +01:00
vfb = vmw_framebuffer_to_vfb ( fb ) ;
2011-10-04 20:13:26 +02:00
2012-11-20 12:19:35 +00:00
ret = vmw_user_resource_lookup_handle ( dev_priv , tfile , arg - > sid ,
user_surface_converter ,
& res ) ;
2011-10-04 20:13:26 +02:00
if ( ret )
goto out_no_surface ;
2012-11-20 12:19:35 +00:00
surface = vmw_res_to_srf ( res ) ;
2011-10-04 20:13:26 +02:00
ret = vmw_kms_present ( dev_priv , file_priv ,
vfb , surface , arg - > sid ,
arg - > dest_x , arg - > dest_y ,
clips , num_clips ) ;
/* vmw_user_surface_lookup takes one ref so does new_fb */
vmw_surface_unreference ( & surface ) ;
out_no_surface :
2018-03-11 17:33:13 -06:00
drm_framebuffer_put ( fb ) ;
2011-10-04 20:13:26 +02:00
out_no_fb :
2012-12-02 01:48:38 +01:00
drm_modeset_unlock_all ( dev ) ;
2011-10-04 20:13:26 +02:00
out_no_copy :
kfree ( clips ) ;
out_clips :
return ret ;
}
int vmw_present_readback_ioctl ( struct drm_device * dev , void * data ,
struct drm_file * file_priv )
{
struct vmw_private * dev_priv = vmw_priv ( dev ) ;
struct drm_vmw_present_readback_arg * arg =
( struct drm_vmw_present_readback_arg * ) data ;
struct drm_vmw_fence_rep __user * user_fence_rep =
( struct drm_vmw_fence_rep __user * )
( unsigned long ) arg - > fence_rep ;
struct drm_vmw_rect __user * clips_ptr ;
struct drm_vmw_rect * clips = NULL ;
2012-12-02 21:53:40 +01:00
struct drm_framebuffer * fb ;
2011-10-04 20:13:26 +02:00
struct vmw_framebuffer * vfb ;
uint32_t num_clips ;
int ret ;
num_clips = arg - > num_clips ;
2015-04-02 02:39:45 -07:00
clips_ptr = ( struct drm_vmw_rect __user * ) ( unsigned long ) arg - > clips_ptr ;
2011-10-04 20:13:26 +02:00
if ( unlikely ( num_clips = = 0 ) )
return 0 ;
if ( clips_ptr = = NULL ) {
2019-02-11 11:46:27 -08:00
VMW_DEBUG_USER ( " Argument clips_ptr must be specified. \n " ) ;
2011-10-04 20:13:26 +02:00
ret = - EINVAL ;
goto out_clips ;
}
2011-11-29 22:08:00 +01:00
clips = kcalloc ( num_clips , sizeof ( * clips ) , GFP_KERNEL ) ;
2011-10-04 20:13:26 +02:00
if ( clips = = NULL ) {
DRM_ERROR ( " Failed to allocate clip rect list. \n " ) ;
ret = - ENOMEM ;
goto out_clips ;
}
ret = copy_from_user ( clips , clips_ptr , num_clips * sizeof ( * clips ) ) ;
if ( ret ) {
DRM_ERROR ( " Failed to copy clip rects from userspace. \n " ) ;
2011-10-18 09:09:19 +03:00
ret = - EFAULT ;
2011-10-04 20:13:26 +02:00
goto out_no_copy ;
}
2012-12-02 01:48:38 +01:00
drm_modeset_lock_all ( dev ) ;
2011-10-04 20:13:26 +02:00
2017-03-14 23:25:07 -07:00
fb = drm_framebuffer_lookup ( dev , file_priv , arg - > fb_id ) ;
2012-12-02 21:53:40 +01:00
if ( ! fb ) {
2019-02-11 11:46:27 -08:00
VMW_DEBUG_USER ( " Invalid framebuffer id. \n " ) ;
2013-10-17 13:35:06 +03:00
ret = - ENOENT ;
2011-10-04 20:13:26 +02:00
goto out_no_fb ;
}
2012-12-02 21:53:40 +01:00
vfb = vmw_framebuffer_to_vfb ( fb ) ;
2018-06-19 15:02:16 +02:00
if ( ! vfb - > bo ) {
2019-02-11 11:46:27 -08:00
VMW_DEBUG_USER ( " Framebuffer not buffer backed. \n " ) ;
2011-10-04 20:13:26 +02:00
ret = - EINVAL ;
2012-12-11 16:28:34 +01:00
goto out_no_ttm_lock ;
2011-10-04 20:13:26 +02:00
}
ret = vmw_kms_readback ( dev_priv , file_priv ,
vfb , user_fence_rep ,
clips , num_clips ) ;
out_no_ttm_lock :
2018-03-11 17:33:13 -06:00
drm_framebuffer_put ( fb ) ;
2011-10-04 20:13:26 +02:00
out_no_fb :
2012-12-02 01:48:38 +01:00
drm_modeset_unlock_all ( dev ) ;
2011-10-04 20:13:26 +02:00
out_no_copy :
kfree ( clips ) ;
out_clips :
return ret ;
}