brintos

brintos / linux-shallow public Read only

0
0
Text · 8.6 KiB · 835d1ee Raw
319 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR MIT2/**************************************************************************3 *4 * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA5 *6 * Permission is hereby granted, free of charge, to any person obtaining a7 * copy of this software and associated documentation files (the8 * "Software"), to deal in the Software without restriction, including9 * without limitation the rights to use, copy, modify, merge, publish,10 * distribute, sub license, and/or sell copies of the Software, and to11 * permit persons to whom the Software is furnished to do so, subject to12 * the following conditions:13 *14 * The above copyright notice and this permission notice (including the15 * next paragraph) shall be included in all copies or substantial portions16 * of the Software.17 *18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE24 * USE OR OTHER DEALINGS IN THE SOFTWARE.25 *26 **************************************************************************/27 28#include "vmwgfx_drv.h"29#include "vmwgfx_devcaps.h"30#include "vmwgfx_kms.h"31 32#include <drm/vmwgfx_drm.h>33#include <linux/pci.h>34#include <linux/vmalloc.h>35 36int vmw_getparam_ioctl(struct drm_device *dev, void *data,37		       struct drm_file *file_priv)38{39	struct vmw_private *dev_priv = vmw_priv(dev);40	struct drm_vmw_getparam_arg *param =41	    (struct drm_vmw_getparam_arg *)data;42	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);43 44	switch (param->param) {45	case DRM_VMW_PARAM_NUM_STREAMS:46		param->value = vmw_overlay_num_overlays(dev_priv);47		break;48	case DRM_VMW_PARAM_NUM_FREE_STREAMS:49		param->value = vmw_overlay_num_free_overlays(dev_priv);50		break;51	case DRM_VMW_PARAM_3D:52		param->value = vmw_supports_3d(dev_priv) ? 1 : 0;53		break;54	case DRM_VMW_PARAM_HW_CAPS:55		param->value = dev_priv->capabilities;56		break;57	case DRM_VMW_PARAM_HW_CAPS2:58		param->value = dev_priv->capabilities2;59		break;60	case DRM_VMW_PARAM_FIFO_CAPS:61		param->value = vmw_fifo_caps(dev_priv);62		break;63	case DRM_VMW_PARAM_MAX_FB_SIZE:64		param->value = dev_priv->max_primary_mem;65		break;66	case DRM_VMW_PARAM_FIFO_HW_VERSION:67	{68		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS))69			param->value = SVGA3D_HWVERSION_WS8_B1;70		else71			param->value = vmw_fifo_mem_read(72					       dev_priv,73					       ((vmw_fifo_caps(dev_priv) &74						 SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?75							SVGA_FIFO_3D_HWVERSION_REVISED :76							SVGA_FIFO_3D_HWVERSION));77		break;78	}79	case DRM_VMW_PARAM_MAX_SURF_MEMORY:80		if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&81		    !vmw_fp->gb_aware)82			param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;83		else84			param->value = dev_priv->memory_size;85		break;86	case DRM_VMW_PARAM_3D_CAPS_SIZE:87		param->value = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);88		break;89	case DRM_VMW_PARAM_MAX_MOB_MEMORY:90		vmw_fp->gb_aware = true;91		param->value = dev_priv->max_mob_pages * PAGE_SIZE;92		break;93	case DRM_VMW_PARAM_MAX_MOB_SIZE:94		param->value = dev_priv->max_mob_size;95		break;96	case DRM_VMW_PARAM_SCREEN_TARGET:97		param->value =98			(dev_priv->active_display_unit == vmw_du_screen_target);99		break;100	case DRM_VMW_PARAM_DX:101		param->value = has_sm4_context(dev_priv);102		break;103	case DRM_VMW_PARAM_SM4_1:104		param->value = has_sm4_1_context(dev_priv);105		break;106	case DRM_VMW_PARAM_SM5:107		param->value = has_sm5_context(dev_priv);108		break;109	case DRM_VMW_PARAM_GL43:110		param->value = has_gl43_context(dev_priv);111		break;112	case DRM_VMW_PARAM_DEVICE_ID:113		param->value = to_pci_dev(dev_priv->drm.dev)->device;114		break;115	default:116		return -EINVAL;117	}118 119	return 0;120}121 122 123int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,124			 struct drm_file *file_priv)125{126	struct drm_vmw_get_3d_cap_arg *arg =127		(struct drm_vmw_get_3d_cap_arg *) data;128	struct vmw_private *dev_priv = vmw_priv(dev);129	uint32_t size;130	void __user *buffer = (void __user *)((unsigned long)(arg->buffer));131	void *bounce = NULL;132	int ret;133	struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);134 135	if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {136		VMW_DEBUG_USER("Illegal GET_3D_CAP argument.\n");137		return -EINVAL;138	}139 140	size = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);141	if (unlikely(size == 0)) {142		DRM_ERROR("Failed to figure out the devcaps size (no 3D).\n");143		return -ENOMEM;144	}145 146	if (arg->max_size < size)147		size = arg->max_size;148 149	bounce = vzalloc(size);150	if (unlikely(bounce == NULL)) {151		DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");152		return -ENOMEM;153	}154 155	ret = vmw_devcaps_copy(dev_priv, vmw_fp->gb_aware, bounce, size);156	if (unlikely (ret != 0))157		goto out_err;158 159	ret = copy_to_user(buffer, bounce, size);160	if (ret)161		ret = -EFAULT;162out_err:163	vfree(bounce);164 165	if (unlikely(ret != 0))166		DRM_ERROR("Failed to report 3D caps info.\n");167 168	return ret;169}170 171int vmw_present_ioctl(struct drm_device *dev, void *data,172		      struct drm_file *file_priv)173{174	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;175	struct vmw_private *dev_priv = vmw_priv(dev);176	struct drm_vmw_present_arg *arg =177		(struct drm_vmw_present_arg *)data;178	struct vmw_surface *surface;179	struct drm_vmw_rect __user *clips_ptr;180	struct drm_vmw_rect *clips = NULL;181	struct drm_framebuffer *fb;182	struct vmw_framebuffer *vfb;183	struct vmw_resource *res;184	uint32_t num_clips;185	int ret;186 187	num_clips = arg->num_clips;188	clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;189 190	if (unlikely(num_clips == 0))191		return 0;192 193	if (clips_ptr == NULL) {194		VMW_DEBUG_USER("Variable clips_ptr must be specified.\n");195		ret = -EINVAL;196		goto out_clips;197	}198 199	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);200	if (clips == NULL) {201		DRM_ERROR("Failed to allocate clip rect list.\n");202		ret = -ENOMEM;203		goto out_clips;204	}205 206	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));207	if (ret) {208		DRM_ERROR("Failed to copy clip rects from userspace.\n");209		ret = -EFAULT;210		goto out_no_copy;211	}212 213	drm_modeset_lock_all(dev);214 215	fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);216	if (!fb) {217		VMW_DEBUG_USER("Invalid framebuffer id.\n");218		ret = -ENOENT;219		goto out_no_fb;220	}221	vfb = vmw_framebuffer_to_vfb(fb);222 223	ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,224					      user_surface_converter,225					      &res);226	if (ret)227		goto out_no_surface;228 229	surface = vmw_res_to_srf(res);230	ret = vmw_kms_present(dev_priv, file_priv,231			      vfb, surface, arg->sid,232			      arg->dest_x, arg->dest_y,233			      clips, num_clips);234 235	/* vmw_user_surface_lookup takes one ref so does new_fb */236	vmw_surface_unreference(&surface);237 238out_no_surface:239	drm_framebuffer_put(fb);240out_no_fb:241	drm_modeset_unlock_all(dev);242out_no_copy:243	kfree(clips);244out_clips:245	return ret;246}247 248int vmw_present_readback_ioctl(struct drm_device *dev, void *data,249			       struct drm_file *file_priv)250{251	struct vmw_private *dev_priv = vmw_priv(dev);252	struct drm_vmw_present_readback_arg *arg =253		(struct drm_vmw_present_readback_arg *)data;254	struct drm_vmw_fence_rep __user *user_fence_rep =255		(struct drm_vmw_fence_rep __user *)256		(unsigned long)arg->fence_rep;257	struct drm_vmw_rect __user *clips_ptr;258	struct drm_vmw_rect *clips = NULL;259	struct drm_framebuffer *fb;260	struct vmw_framebuffer *vfb;261	uint32_t num_clips;262	int ret;263 264	num_clips = arg->num_clips;265	clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;266 267	if (unlikely(num_clips == 0))268		return 0;269 270	if (clips_ptr == NULL) {271		VMW_DEBUG_USER("Argument clips_ptr must be specified.\n");272		ret = -EINVAL;273		goto out_clips;274	}275 276	clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);277	if (clips == NULL) {278		DRM_ERROR("Failed to allocate clip rect list.\n");279		ret = -ENOMEM;280		goto out_clips;281	}282 283	ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));284	if (ret) {285		DRM_ERROR("Failed to copy clip rects from userspace.\n");286		ret = -EFAULT;287		goto out_no_copy;288	}289 290	drm_modeset_lock_all(dev);291 292	fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);293	if (!fb) {294		VMW_DEBUG_USER("Invalid framebuffer id.\n");295		ret = -ENOENT;296		goto out_no_fb;297	}298 299	vfb = vmw_framebuffer_to_vfb(fb);300	if (!vfb->bo) {301		VMW_DEBUG_USER("Framebuffer not buffer backed.\n");302		ret = -EINVAL;303		goto out_no_ttm_lock;304	}305 306	ret = vmw_kms_readback(dev_priv, file_priv,307			       vfb, user_fence_rep,308			       clips, num_clips);309 310out_no_ttm_lock:311	drm_framebuffer_put(fb);312out_no_fb:313	drm_modeset_unlock_all(dev);314out_no_copy:315	kfree(clips);316out_clips:317	return ret;318}319