diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 236 |
1 files changed, 54 insertions, 182 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 5ec24fd801cd..835d1eed8dd9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -26,14 +26,12 @@ **************************************************************************/ #include "vmwgfx_drv.h" -#include <drm/vmwgfx_drm.h> +#include "vmwgfx_devcaps.h" #include "vmwgfx_kms.h" -#include "device_include/svga3d_caps.h" -struct svga_3d_compat_cap { - SVGA3dCapsRecordHeader header; - SVGA3dCapPair pairs[SVGA3D_DEVCAP_MAX]; -}; +#include <drm/vmwgfx_drm.h> +#include <linux/pci.h> +#include <linux/vmalloc.h> int vmw_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -51,33 +49,31 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, param->value = vmw_overlay_num_free_overlays(dev_priv); break; case DRM_VMW_PARAM_3D: - param->value = vmw_fifo_have_3d(dev_priv) ? 1 : 0; + param->value = vmw_supports_3d(dev_priv) ? 1 : 0; break; case DRM_VMW_PARAM_HW_CAPS: param->value = dev_priv->capabilities; break; + case DRM_VMW_PARAM_HW_CAPS2: + param->value = dev_priv->capabilities2; + break; case DRM_VMW_PARAM_FIFO_CAPS: - param->value = dev_priv->fifo.capabilities; + param->value = vmw_fifo_caps(dev_priv); break; case DRM_VMW_PARAM_MAX_FB_SIZE: - param->value = dev_priv->prim_bb_mem; + param->value = dev_priv->max_primary_mem; break; case DRM_VMW_PARAM_FIFO_HW_VERSION: { - u32 *fifo_mem = dev_priv->mmio_virt; - const struct vmw_fifo_state *fifo = &dev_priv->fifo; - - if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) { + if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) param->value = SVGA3D_HWVERSION_WS8_B1; - break; - } - - param->value = - vmw_mmio_read(fifo_mem + - ((fifo->capabilities & - SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ? - SVGA_FIFO_3D_HWVERSION_REVISED : - SVGA_FIFO_3D_HWVERSION)); + else + param->value = vmw_fifo_mem_read( + dev_priv, + ((vmw_fifo_caps(dev_priv) & + SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ? + SVGA_FIFO_3D_HWVERSION_REVISED : + SVGA_FIFO_3D_HWVERSION)); break; } case DRM_VMW_PARAM_MAX_SURF_MEMORY: @@ -88,16 +84,7 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, param->value = dev_priv->memory_size; break; case DRM_VMW_PARAM_3D_CAPS_SIZE: - if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) && - vmw_fp->gb_aware) - param->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t); - else if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) - param->value = sizeof(struct svga_3d_compat_cap) + - sizeof(uint32_t); - else - param->value = (SVGA_FIFO_3D_CAPS_LAST - - SVGA_FIFO_3D_CAPS + 1) * - sizeof(uint32_t); + param->value = vmw_devcaps_size(dev_priv, vmw_fp->gb_aware); break; case DRM_VMW_PARAM_MAX_MOB_MEMORY: vmw_fp->gb_aware = true; @@ -111,7 +98,19 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, (dev_priv->active_display_unit == vmw_du_screen_target); break; case DRM_VMW_PARAM_DX: - param->value = dev_priv->has_dx; + param->value = has_sm4_context(dev_priv); + break; + case DRM_VMW_PARAM_SM4_1: + param->value = has_sm4_1_context(dev_priv); + break; + case DRM_VMW_PARAM_SM5: + param->value = has_sm5_context(dev_priv); + break; + case DRM_VMW_PARAM_GL43: + param->value = has_gl43_context(dev_priv); + break; + case DRM_VMW_PARAM_DEVICE_ID: + param->value = to_pci_dev(dev_priv->drm.dev)->device; break; default: return -EINVAL; @@ -120,55 +119,6 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, return 0; } -static u32 vmw_mask_multisample(unsigned int cap, u32 fmt_value) -{ - /* If the header is updated, update the format test as well! */ - BUILD_BUG_ON(SVGA3D_DEVCAP_DXFMT_BC5_UNORM + 1 != SVGA3D_DEVCAP_MAX); - - if (cap >= SVGA3D_DEVCAP_DXFMT_X8R8G8B8 && - cap <= SVGA3D_DEVCAP_DXFMT_BC5_UNORM) - fmt_value &= ~(SVGADX_DXFMT_MULTISAMPLE_2 | - SVGADX_DXFMT_MULTISAMPLE_4 | - SVGADX_DXFMT_MULTISAMPLE_8); - else if (cap == SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES) - return 0; - - return fmt_value; -} - -static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce, - size_t size) -{ - struct svga_3d_compat_cap *compat_cap = - (struct svga_3d_compat_cap *) bounce; - unsigned int i; - size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs); - unsigned int max_size; - - if (size < pair_offset) - return -EINVAL; - - max_size = (size - pair_offset) / sizeof(SVGA3dCapPair); - - if (max_size > SVGA3D_DEVCAP_MAX) - max_size = SVGA3D_DEVCAP_MAX; - - compat_cap->header.length = - (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32); - compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS; - - spin_lock(&dev_priv->cap_lock); - for (i = 0; i < max_size; ++i) { - vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); - compat_cap->pairs[i][0] = i; - compat_cap->pairs[i][1] = vmw_mask_multisample - (i, vmw_read(dev_priv, SVGA_REG_DEV_CAP)); - } - spin_unlock(&dev_priv->cap_lock); - - return 0; -} - int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -177,25 +127,21 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, (struct drm_vmw_get_3d_cap_arg *) data; struct vmw_private *dev_priv = vmw_priv(dev); uint32_t size; - u32 *fifo_mem; void __user *buffer = (void __user *)((unsigned long)(arg->buffer)); - void *bounce; + void *bounce = NULL; int ret; - bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS); struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); if (unlikely(arg->pad64 != 0 || arg->max_size == 0)) { - DRM_ERROR("Illegal GET_3D_CAP argument.\n"); + VMW_DEBUG_USER("Illegal GET_3D_CAP argument.\n"); return -EINVAL; } - if (gb_objects && vmw_fp->gb_aware) - size = SVGA3D_DEVCAP_MAX * sizeof(uint32_t); - else if (gb_objects) - size = sizeof(struct svga_3d_compat_cap) + sizeof(uint32_t); - else - size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) * - sizeof(uint32_t); + 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; + } if (arg->max_size < size) size = arg->max_size; @@ -206,29 +152,9 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, return -ENOMEM; } - if (gb_objects && vmw_fp->gb_aware) { - int i, num; - uint32_t *bounce32 = (uint32_t *) bounce; - - num = size / sizeof(uint32_t); - if (num > SVGA3D_DEVCAP_MAX) - num = SVGA3D_DEVCAP_MAX; - - spin_lock(&dev_priv->cap_lock); - for (i = 0; i < num; ++i) { - vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); - *bounce32++ = vmw_mask_multisample - (i, vmw_read(dev_priv, SVGA_REG_DEV_CAP)); - } - spin_unlock(&dev_priv->cap_lock); - } else if (gb_objects) { - ret = vmw_fill_compat_cap(dev_priv, bounce, size); - if (unlikely(ret != 0)) - goto out_err; - } else { - fifo_mem = dev_priv->mmio_virt; - memcpy(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size); - } + ret = vmw_devcaps_copy(dev_priv, vmw_fp->gb_aware, bounce, size); + if (unlikely (ret != 0)) + goto out_err; ret = copy_to_user(buffer, bounce, size); if (ret) @@ -265,7 +191,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, return 0; if (clips_ptr == NULL) { - DRM_ERROR("Variable clips_ptr must be specified.\n"); + VMW_DEBUG_USER("Variable clips_ptr must be specified.\n"); ret = -EINVAL; goto out_clips; } @@ -286,18 +212,14 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); - fb = drm_framebuffer_lookup(dev, arg->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id); if (!fb) { - DRM_ERROR("Invalid framebuffer id.\n"); + VMW_DEBUG_USER("Invalid framebuffer id.\n"); ret = -ENOENT; goto out_no_fb; } vfb = vmw_framebuffer_to_vfb(fb); - ret = ttm_read_lock(&dev_priv->reservation_sem, true); - if (unlikely(ret != 0)) - goto out_no_ttm_lock; - ret = vmw_user_resource_lookup_handle(dev_priv, tfile, arg->sid, user_surface_converter, &res); @@ -314,9 +236,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, vmw_surface_unreference(&surface); out_no_surface: - ttm_read_unlock(&dev_priv->reservation_sem); -out_no_ttm_lock: - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); out_no_fb: drm_modeset_unlock_all(dev); out_no_copy: @@ -348,7 +268,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, return 0; if (clips_ptr == NULL) { - DRM_ERROR("Argument clips_ptr must be specified.\n"); + VMW_DEBUG_USER("Argument clips_ptr must be specified.\n"); ret = -EINVAL; goto out_clips; } @@ -369,31 +289,26 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); - fb = drm_framebuffer_lookup(dev, arg->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id); if (!fb) { - DRM_ERROR("Invalid framebuffer id.\n"); + VMW_DEBUG_USER("Invalid framebuffer id.\n"); ret = -ENOENT; goto out_no_fb; } vfb = vmw_framebuffer_to_vfb(fb); - if (!vfb->dmabuf) { - DRM_ERROR("Framebuffer not dmabuf backed.\n"); + if (!vfb->bo) { + VMW_DEBUG_USER("Framebuffer not buffer backed.\n"); ret = -EINVAL; goto out_no_ttm_lock; } - ret = ttm_read_lock(&dev_priv->reservation_sem, true); - if (unlikely(ret != 0)) - goto out_no_ttm_lock; - ret = vmw_kms_readback(dev_priv, file_priv, vfb, user_fence_rep, clips, num_clips); - ttm_read_unlock(&dev_priv->reservation_sem); out_no_ttm_lock: - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); out_no_fb: drm_modeset_unlock_all(dev); out_no_copy: @@ -401,46 +316,3 @@ out_no_copy: out_clips: return ret; } - - -/** - * vmw_fops_poll - wrapper around the drm_poll function - * - * @filp: See the linux fops poll documentation. - * @wait: See the linux fops poll documentation. - * - * Wrapper around the drm_poll function that makes sure the device is - * processing the fifo if drm_poll decides to wait. - */ -unsigned int vmw_fops_poll(struct file *filp, struct poll_table_struct *wait) -{ - struct drm_file *file_priv = filp->private_data; - struct vmw_private *dev_priv = - vmw_priv(file_priv->minor->dev); - - vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); - return drm_poll(filp, wait); -} - - -/** - * vmw_fops_read - wrapper around the drm_read function - * - * @filp: See the linux fops read documentation. - * @buffer: See the linux fops read documentation. - * @count: See the linux fops read documentation. - * offset: See the linux fops read documentation. - * - * Wrapper around the drm_read function that makes sure the device is - * processing the fifo if drm_read decides to wait. - */ -ssize_t vmw_fops_read(struct file *filp, char __user *buffer, - size_t count, loff_t *offset) -{ - struct drm_file *file_priv = filp->private_data; - struct vmw_private *dev_priv = - vmw_priv(file_priv->minor->dev); - - vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC); - return drm_read(filp, buffer, count, offset); -} |
