Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR MIT
0002 /**************************************************************************
0003  *
0004  * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA
0005  *
0006  * Permission is hereby granted, free of charge, to any person obtaining a
0007  * copy of this software and associated documentation files (the
0008  * "Software"), to deal in the Software without restriction, including
0009  * without limitation the rights to use, copy, modify, merge, publish,
0010  * distribute, sub license, and/or sell copies of the Software, and to
0011  * permit persons to whom the Software is furnished to do so, subject to
0012  * the following conditions:
0013  *
0014  * The above copyright notice and this permission notice (including the
0015  * next paragraph) shall be included in all copies or substantial portions
0016  * of the Software.
0017  *
0018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0019  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0020  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
0021  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
0022  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
0023  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
0024  * USE OR OTHER DEALINGS IN THE SOFTWARE.
0025  *
0026  **************************************************************************/
0027 
0028 #include "vmwgfx_drv.h"
0029 #include "vmwgfx_devcaps.h"
0030 #include "vmwgfx_kms.h"
0031 
0032 #include <drm/vmwgfx_drm.h>
0033 #include <linux/pci.h>
0034 
0035 int vmw_getparam_ioctl(struct drm_device *dev, void *data,
0036                struct drm_file *file_priv)
0037 {
0038     struct vmw_private *dev_priv = vmw_priv(dev);
0039     struct drm_vmw_getparam_arg *param =
0040         (struct drm_vmw_getparam_arg *)data;
0041     struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
0042 
0043     switch (param->param) {
0044     case DRM_VMW_PARAM_NUM_STREAMS:
0045         param->value = vmw_overlay_num_overlays(dev_priv);
0046         break;
0047     case DRM_VMW_PARAM_NUM_FREE_STREAMS:
0048         param->value = vmw_overlay_num_free_overlays(dev_priv);
0049         break;
0050     case DRM_VMW_PARAM_3D:
0051         param->value = vmw_supports_3d(dev_priv) ? 1 : 0;
0052         break;
0053     case DRM_VMW_PARAM_HW_CAPS:
0054         param->value = dev_priv->capabilities;
0055         break;
0056     case DRM_VMW_PARAM_HW_CAPS2:
0057         param->value = dev_priv->capabilities2;
0058         break;
0059     case DRM_VMW_PARAM_FIFO_CAPS:
0060         param->value = vmw_fifo_caps(dev_priv);
0061         break;
0062     case DRM_VMW_PARAM_MAX_FB_SIZE:
0063         param->value = dev_priv->max_primary_mem;
0064         break;
0065     case DRM_VMW_PARAM_FIFO_HW_VERSION:
0066     {
0067         if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
0068             param->value = SVGA3D_HWVERSION_WS8_B1;
0069         else
0070             param->value = vmw_fifo_mem_read(
0071                            dev_priv,
0072                            ((vmw_fifo_caps(dev_priv) &
0073                          SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ?
0074                             SVGA_FIFO_3D_HWVERSION_REVISED :
0075                             SVGA_FIFO_3D_HWVERSION));
0076         break;
0077     }
0078     case DRM_VMW_PARAM_MAX_SURF_MEMORY:
0079         if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
0080             !vmw_fp->gb_aware)
0081             param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;
0082         else
0083             param->value = dev_priv->memory_size;
0084         break;
0085     case DRM_VMW_PARAM_3D_CAPS_SIZE:
0086         param->value = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
0087         break;
0088     case DRM_VMW_PARAM_MAX_MOB_MEMORY:
0089         vmw_fp->gb_aware = true;
0090         param->value = dev_priv->max_mob_pages * PAGE_SIZE;
0091         break;
0092     case DRM_VMW_PARAM_MAX_MOB_SIZE:
0093         param->value = dev_priv->max_mob_size;
0094         break;
0095     case DRM_VMW_PARAM_SCREEN_TARGET:
0096         param->value =
0097             (dev_priv->active_display_unit == vmw_du_screen_target);
0098         break;
0099     case DRM_VMW_PARAM_DX:
0100         param->value = has_sm4_context(dev_priv);
0101         break;
0102     case DRM_VMW_PARAM_SM4_1:
0103         param->value = has_sm4_1_context(dev_priv);
0104         break;
0105     case DRM_VMW_PARAM_SM5:
0106         param->value = has_sm5_context(dev_priv);
0107         break;
0108     case DRM_VMW_PARAM_GL43:
0109         param->value = has_gl43_context(dev_priv);
0110         break;
0111     case DRM_VMW_PARAM_DEVICE_ID:
0112         param->value = to_pci_dev(dev_priv->drm.dev)->device;
0113         break;
0114     default:
0115         return -EINVAL;
0116     }
0117 
0118     return 0;
0119 }
0120 
0121 
0122 int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
0123              struct drm_file *file_priv)
0124 {
0125     struct drm_vmw_get_3d_cap_arg *arg =
0126         (struct drm_vmw_get_3d_cap_arg *) data;
0127     struct vmw_private *dev_priv = vmw_priv(dev);
0128     uint32_t size;
0129     void __user *buffer = (void __user *)((unsigned long)(arg->buffer));
0130     void *bounce = NULL;
0131     int ret;
0132     struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
0133 
0134     if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) {
0135         VMW_DEBUG_USER("Illegal GET_3D_CAP argument.\n");
0136         return -EINVAL;
0137     }
0138 
0139     size = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware);
0140     if (unlikely(size == 0)) {
0141         DRM_ERROR("Failed to figure out the devcaps size (no 3D).\n");
0142         return -ENOMEM;
0143     }
0144 
0145     if (arg->max_size < size)
0146         size = arg->max_size;
0147 
0148     bounce = vzalloc(size);
0149     if (unlikely(bounce == NULL)) {
0150         DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
0151         return -ENOMEM;
0152     }
0153 
0154     ret = vmw_devcaps_copy(dev_priv, vmw_fp->gb_aware, bounce, size);
0155     if (unlikely (ret != 0))
0156         goto out_err;
0157 
0158     ret = copy_to_user(buffer, bounce, size);
0159     if (ret)
0160         ret = -EFAULT;
0161 out_err:
0162     vfree(bounce);
0163 
0164     if (unlikely(ret != 0))
0165         DRM_ERROR("Failed to report 3D caps info.\n");
0166 
0167     return ret;
0168 }
0169 
0170 int vmw_present_ioctl(struct drm_device *dev, void *data,
0171               struct drm_file *file_priv)
0172 {
0173     struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
0174     struct vmw_private *dev_priv = vmw_priv(dev);
0175     struct drm_vmw_present_arg *arg =
0176         (struct drm_vmw_present_arg *)data;
0177     struct vmw_surface *surface;
0178     struct drm_vmw_rect __user *clips_ptr;
0179     struct drm_vmw_rect *clips = NULL;
0180     struct drm_framebuffer *fb;
0181     struct vmw_framebuffer *vfb;
0182     struct vmw_resource *res;
0183     uint32_t num_clips;
0184     int ret;
0185 
0186     num_clips = arg->num_clips;
0187     clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
0188 
0189     if (unlikely(num_clips == 0))
0190         return 0;
0191 
0192     if (clips_ptr == NULL) {
0193         VMW_DEBUG_USER("Variable clips_ptr must be specified.\n");
0194         ret = -EINVAL;
0195         goto out_clips;
0196     }
0197 
0198     clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
0199     if (clips == NULL) {
0200         DRM_ERROR("Failed to allocate clip rect list.\n");
0201         ret = -ENOMEM;
0202         goto out_clips;
0203     }
0204 
0205     ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
0206     if (ret) {
0207         DRM_ERROR("Failed to copy clip rects from userspace.\n");
0208         ret = -EFAULT;
0209         goto out_no_copy;
0210     }
0211 
0212     drm_modeset_lock_all(dev);
0213 
0214     fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
0215     if (!fb) {
0216         VMW_DEBUG_USER("Invalid framebuffer id.\n");
0217         ret = -ENOENT;
0218         goto out_no_fb;
0219     }
0220     vfb = vmw_framebuffer_to_vfb(fb);
0221 
0222     ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid,
0223                           user_surface_converter,
0224                           &res);
0225     if (ret)
0226         goto out_no_surface;
0227 
0228     surface = vmw_res_to_srf(res);
0229     ret = vmw_kms_present(dev_priv, file_priv,
0230                   vfb, surface, arg->sid,
0231                   arg->dest_x, arg->dest_y,
0232                   clips, num_clips);
0233 
0234     /* vmw_user_surface_lookup takes one ref so does new_fb */
0235     vmw_surface_unreference(&surface);
0236 
0237 out_no_surface:
0238     drm_framebuffer_put(fb);
0239 out_no_fb:
0240     drm_modeset_unlock_all(dev);
0241 out_no_copy:
0242     kfree(clips);
0243 out_clips:
0244     return ret;
0245 }
0246 
0247 int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
0248                    struct drm_file *file_priv)
0249 {
0250     struct vmw_private *dev_priv = vmw_priv(dev);
0251     struct drm_vmw_present_readback_arg *arg =
0252         (struct drm_vmw_present_readback_arg *)data;
0253     struct drm_vmw_fence_rep __user *user_fence_rep =
0254         (struct drm_vmw_fence_rep __user *)
0255         (unsigned long)arg->fence_rep;
0256     struct drm_vmw_rect __user *clips_ptr;
0257     struct drm_vmw_rect *clips = NULL;
0258     struct drm_framebuffer *fb;
0259     struct vmw_framebuffer *vfb;
0260     uint32_t num_clips;
0261     int ret;
0262 
0263     num_clips = arg->num_clips;
0264     clips_ptr = (struct drm_vmw_rect __user *)(unsigned long)arg->clips_ptr;
0265 
0266     if (unlikely(num_clips == 0))
0267         return 0;
0268 
0269     if (clips_ptr == NULL) {
0270         VMW_DEBUG_USER("Argument clips_ptr must be specified.\n");
0271         ret = -EINVAL;
0272         goto out_clips;
0273     }
0274 
0275     clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
0276     if (clips == NULL) {
0277         DRM_ERROR("Failed to allocate clip rect list.\n");
0278         ret = -ENOMEM;
0279         goto out_clips;
0280     }
0281 
0282     ret = copy_from_user(clips, clips_ptr, num_clips * sizeof(*clips));
0283     if (ret) {
0284         DRM_ERROR("Failed to copy clip rects from userspace.\n");
0285         ret = -EFAULT;
0286         goto out_no_copy;
0287     }
0288 
0289     drm_modeset_lock_all(dev);
0290 
0291     fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
0292     if (!fb) {
0293         VMW_DEBUG_USER("Invalid framebuffer id.\n");
0294         ret = -ENOENT;
0295         goto out_no_fb;
0296     }
0297 
0298     vfb = vmw_framebuffer_to_vfb(fb);
0299     if (!vfb->bo) {
0300         VMW_DEBUG_USER("Framebuffer not buffer backed.\n");
0301         ret = -EINVAL;
0302         goto out_no_ttm_lock;
0303     }
0304 
0305     ret = vmw_kms_readback(dev_priv, file_priv,
0306                    vfb, user_fence_rep,
0307                    clips, num_clips);
0308 
0309 out_no_ttm_lock:
0310     drm_framebuffer_put(fb);
0311 out_no_fb:
0312     drm_modeset_unlock_all(dev);
0313 out_no_copy:
0314     kfree(clips);
0315 out_clips:
0316     return ret;
0317 }