summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c847
1 files changed, 449 insertions, 398 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 6f5ea00973e0..599052d07ae8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1,55 +1,44 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright 2009-2016 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
- * "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.
+ * Copyright (c) 2009-2025 Broadcom. All Rights Reserved. The term
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
*
**************************************************************************/
-#include <linux/console.h>
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/mem_encrypt.h>
+#include "vmwgfx_drv.h"
-#include <drm/drm_aperture.h>
+#include "vmwgfx_bo.h"
+#include "vmwgfx_binding.h"
+#include "vmwgfx_devcaps.h"
+#include "vmwgfx_mksstat.h"
+#include "vmwgfx_vkms.h"
+#include "ttm_object.h"
+
+#include <drm/clients/drm_client_setup.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_ttm.h>
+#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
+#include <drm/drm_module.h>
#include <drm/drm_sysfs.h>
-#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_range_manager.h>
#include <drm/ttm/ttm_placement.h>
#include <generated/utsrelease.h>
-#include "ttm_object.h"
-#include "vmwgfx_binding.h"
-#include "vmwgfx_drv.h"
-
-#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
-
-#define VMW_MIN_INITIAL_WIDTH 800
-#define VMW_MIN_INITIAL_HEIGHT 600
+#ifdef CONFIG_X86
+#include <asm/hypervisor.h>
+#endif
-#define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE)
+#include <linux/aperture.h>
+#include <linux/cc_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/vmalloc.h>
+#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
/*
* Fully encoded drm commands. Might move to vmw_drm.h
@@ -147,113 +136,120 @@
#define DRM_IOCTL_VMW_MSG \
DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_MSG, \
struct drm_vmw_msg_arg)
-
-/*
- * The core DRM version of this macro doesn't account for
- * DRM_COMMAND_BASE.
- */
-
-#define VMW_IOCTL_DEF(ioctl, func, flags) \
- [DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_IOCTL_##ioctl, flags, func}
+#define DRM_IOCTL_VMW_MKSSTAT_RESET \
+ DRM_IO(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_RESET)
+#define DRM_IOCTL_VMW_MKSSTAT_ADD \
+ DRM_IOWR(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_ADD, \
+ struct drm_vmw_mksstat_add_arg)
+#define DRM_IOCTL_VMW_MKSSTAT_REMOVE \
+ DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_REMOVE, \
+ struct drm_vmw_mksstat_remove_arg)
/*
* Ioctl definitions.
*/
static const struct drm_ioctl_desc vmw_ioctls[] = {
- VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
- vmw_kms_cursor_bypass_ioctl,
- DRM_MASTER),
-
- VMW_IOCTL_DEF(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
- DRM_MASTER),
- VMW_IOCTL_DEF(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
- DRM_MASTER),
- VMW_IOCTL_DEF(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
- DRM_MASTER),
-
- VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
- vmw_fence_obj_signaled_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
- DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GET_PARAM, vmw_getparam_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_ALLOC_DMABUF, vmw_gem_object_create_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CURSOR_BYPASS,
+ vmw_kms_cursor_bypass_ioctl,
+ DRM_MASTER),
+
+ DRM_IOCTL_DEF_DRV(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
+ DRM_MASTER),
+ DRM_IOCTL_DEF_DRV(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
+ DRM_MASTER),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
+ DRM_MASTER),
+
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_EXECBUF, vmw_execbuf_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_SIGNALED,
+ vmw_fence_obj_signaled_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
+ DRM_RENDER_ALLOW),
/* these allow direct access to the framebuffers mark as master only */
- VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
- DRM_MASTER | DRM_AUTH),
- VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
- vmw_present_readback_ioctl,
- DRM_MASTER | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(VMW_PRESENT, vmw_present_ioctl,
+ DRM_MASTER | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(VMW_PRESENT_READBACK,
+ vmw_present_readback_ioctl,
+ DRM_MASTER | DRM_AUTH),
/*
* The permissions of the below ioctl are overridden in
* vmw_generic_ioctl(). We require either
* DRM_MASTER or capable(CAP_SYS_ADMIN).
*/
- VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
- vmw_kms_update_layout_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CREATE_SHADER,
- vmw_shader_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_UNREF_SHADER,
- vmw_shader_destroy_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
- vmw_gb_surface_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
- vmw_gb_surface_reference_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_SYNCCPU,
- vmw_user_bo_synccpu_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
- vmw_extended_context_define_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE_EXT,
- vmw_gb_surface_define_ext_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT,
- vmw_gb_surface_reference_ext_ioctl,
- DRM_RENDER_ALLOW),
- VMW_IOCTL_DEF(VMW_MSG,
- vmw_msg_ioctl,
- DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UPDATE_LAYOUT,
+ vmw_kms_update_layout_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_SHADER,
+ vmw_shader_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_UNREF_SHADER,
+ vmw_shader_destroy_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_CREATE,
+ vmw_gb_surface_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_REF,
+ vmw_gb_surface_reference_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_SYNCCPU,
+ vmw_user_bo_synccpu_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_CREATE_EXTENDED_CONTEXT,
+ vmw_extended_context_define_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_CREATE_EXT,
+ vmw_gb_surface_define_ext_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_REF_EXT,
+ vmw_gb_surface_reference_ext_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MSG,
+ vmw_msg_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_RESET,
+ vmw_mksstat_reset_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_ADD,
+ vmw_mksstat_add_ioctl,
+ DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_REMOVE,
+ vmw_mksstat_remove_ioctl,
+ DRM_RENDER_ALLOW),
};
static const struct pci_device_id vmw_pci_id_list[] = {
- { PCI_DEVICE(0x15ad, VMWGFX_PCI_ID_SVGA2) },
- { PCI_DEVICE(0x15ad, VMWGFX_PCI_ID_SVGA3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_VMWARE, VMWGFX_PCI_ID_SVGA2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_VMWARE, VMWGFX_PCI_ID_SVGA3) },
{ }
};
MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
-static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
-static int vmw_force_iommu;
static int vmw_restrict_iommu;
static int vmw_force_coherent;
static int vmw_restrict_dma_mask;
@@ -263,10 +259,6 @@ static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr);
-MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
-module_param_named(enable_fbdev, enable_fbdev, int, 0600);
-MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages");
-module_param_named(force_dma_api, vmw_force_iommu, int, 0600);
MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
@@ -277,62 +269,93 @@ MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
-static void vmw_print_capabilities2(uint32_t capabilities2)
+struct bitmap_name {
+ uint32 value;
+ const char *name;
+};
+
+static const struct bitmap_name cap1_names[] = {
+ { SVGA_CAP_RECT_COPY, "rect copy" },
+ { SVGA_CAP_CURSOR, "cursor" },
+ { SVGA_CAP_CURSOR_BYPASS, "cursor bypass" },
+ { SVGA_CAP_CURSOR_BYPASS_2, "cursor bypass 2" },
+ { SVGA_CAP_8BIT_EMULATION, "8bit emulation" },
+ { SVGA_CAP_ALPHA_CURSOR, "alpha cursor" },
+ { SVGA_CAP_3D, "3D" },
+ { SVGA_CAP_EXTENDED_FIFO, "extended fifo" },
+ { SVGA_CAP_MULTIMON, "multimon" },
+ { SVGA_CAP_PITCHLOCK, "pitchlock" },
+ { SVGA_CAP_IRQMASK, "irq mask" },
+ { SVGA_CAP_DISPLAY_TOPOLOGY, "display topology" },
+ { SVGA_CAP_GMR, "gmr" },
+ { SVGA_CAP_TRACES, "traces" },
+ { SVGA_CAP_GMR2, "gmr2" },
+ { SVGA_CAP_SCREEN_OBJECT_2, "screen object 2" },
+ { SVGA_CAP_COMMAND_BUFFERS, "command buffers" },
+ { SVGA_CAP_CMD_BUFFERS_2, "command buffers 2" },
+ { SVGA_CAP_GBOBJECTS, "gbobject" },
+ { SVGA_CAP_DX, "dx" },
+ { SVGA_CAP_HP_CMD_QUEUE, "hp cmd queue" },
+ { SVGA_CAP_NO_BB_RESTRICTION, "no bb restriction" },
+ { SVGA_CAP_CAP2_REGISTER, "cap2 register" },
+};
+
+
+static const struct bitmap_name cap2_names[] = {
+ { SVGA_CAP2_GROW_OTABLE, "grow otable" },
+ { SVGA_CAP2_INTRA_SURFACE_COPY, "intra surface copy" },
+ { SVGA_CAP2_DX2, "dx2" },
+ { SVGA_CAP2_GB_MEMSIZE_2, "gb memsize 2" },
+ { SVGA_CAP2_SCREENDMA_REG, "screendma reg" },
+ { SVGA_CAP2_OTABLE_PTDEPTH_2, "otable ptdepth2" },
+ { SVGA_CAP2_NON_MS_TO_MS_STRETCHBLT, "non ms to ms stretchblt" },
+ { SVGA_CAP2_CURSOR_MOB, "cursor mob" },
+ { SVGA_CAP2_MSHINT, "mshint" },
+ { SVGA_CAP2_CB_MAX_SIZE_4MB, "cb max size 4mb" },
+ { SVGA_CAP2_DX3, "dx3" },
+ { SVGA_CAP2_FRAME_TYPE, "frame type" },
+ { SVGA_CAP2_COTABLE_COPY, "cotable copy" },
+ { SVGA_CAP2_TRACE_FULL_FB, "trace full fb" },
+ { SVGA_CAP2_EXTRA_REGS, "extra regs" },
+ { SVGA_CAP2_LO_STAGING, "lo staging" },
+};
+
+static void vmw_print_bitmap(struct drm_device *drm,
+ const char *prefix, uint32_t bitmap,
+ const struct bitmap_name *bnames,
+ uint32_t num_names)
{
- DRM_INFO("Capabilities2:\n");
- if (capabilities2 & SVGA_CAP2_GROW_OTABLE)
- DRM_INFO(" Grow oTable.\n");
- if (capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)
- DRM_INFO(" IntraSurface copy.\n");
- if (capabilities2 & SVGA_CAP2_DX3)
- DRM_INFO(" DX3.\n");
+ char buf[512];
+ uint32_t i;
+ uint32_t offset = 0;
+ for (i = 0; i < num_names; ++i) {
+ if ((bitmap & bnames[i].value) != 0) {
+ offset += snprintf(buf + offset,
+ ARRAY_SIZE(buf) - offset,
+ "%s, ", bnames[i].name);
+ bitmap &= ~bnames[i].value;
+ }
+ }
+
+ drm_info(drm, "%s: %s\n", prefix, buf);
+ if (bitmap != 0)
+ drm_dbg(drm, "%s: unknown enums: %x\n", prefix, bitmap);
}
-static void vmw_print_capabilities(uint32_t capabilities)
+
+static void vmw_print_sm_type(struct vmw_private *dev_priv)
{
- DRM_INFO("Capabilities:\n");
- if (capabilities & SVGA_CAP_RECT_COPY)
- DRM_INFO(" Rect copy.\n");
- if (capabilities & SVGA_CAP_CURSOR)
- DRM_INFO(" Cursor.\n");
- if (capabilities & SVGA_CAP_CURSOR_BYPASS)
- DRM_INFO(" Cursor bypass.\n");
- if (capabilities & SVGA_CAP_CURSOR_BYPASS_2)
- DRM_INFO(" Cursor bypass 2.\n");
- if (capabilities & SVGA_CAP_8BIT_EMULATION)
- DRM_INFO(" 8bit emulation.\n");
- if (capabilities & SVGA_CAP_ALPHA_CURSOR)
- DRM_INFO(" Alpha cursor.\n");
- if (capabilities & SVGA_CAP_3D)
- DRM_INFO(" 3D.\n");
- if (capabilities & SVGA_CAP_EXTENDED_FIFO)
- DRM_INFO(" Extended Fifo.\n");
- if (capabilities & SVGA_CAP_MULTIMON)
- DRM_INFO(" Multimon.\n");
- if (capabilities & SVGA_CAP_PITCHLOCK)
- DRM_INFO(" Pitchlock.\n");
- if (capabilities & SVGA_CAP_IRQMASK)
- DRM_INFO(" Irq mask.\n");
- if (capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)
- DRM_INFO(" Display Topology.\n");
- if (capabilities & SVGA_CAP_GMR)
- DRM_INFO(" GMR.\n");
- if (capabilities & SVGA_CAP_TRACES)
- DRM_INFO(" Traces.\n");
- if (capabilities & SVGA_CAP_GMR2)
- DRM_INFO(" GMR2.\n");
- if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
- DRM_INFO(" Screen Object 2.\n");
- if (capabilities & SVGA_CAP_COMMAND_BUFFERS)
- DRM_INFO(" Command Buffers.\n");
- if (capabilities & SVGA_CAP_CMD_BUFFERS_2)
- DRM_INFO(" Command Buffers 2.\n");
- if (capabilities & SVGA_CAP_GBOBJECTS)
- DRM_INFO(" Guest Backed Resources.\n");
- if (capabilities & SVGA_CAP_DX)
- DRM_INFO(" DX Features.\n");
- if (capabilities & SVGA_CAP_HP_CMD_QUEUE)
- DRM_INFO(" HP Command Queue.\n");
+ static const char *names[] = {
+ [VMW_SM_LEGACY] = "Legacy",
+ [VMW_SM_4] = "SM4",
+ [VMW_SM_4_1] = "SM4_1",
+ [VMW_SM_5] = "SM_5",
+ [VMW_SM_5_1X] = "SM_5_1X",
+ [VMW_SM_MAX] = "Invalid"
+ };
+ BUILD_BUG_ON(ARRAY_SIZE(names) != (VMW_SM_MAX + 1));
+ drm_info(&dev_priv->drm, "Available shader model: %s.\n",
+ names[dev_priv->sm_type]);
}
/**
@@ -351,31 +374,29 @@ static void vmw_print_capabilities(uint32_t capabilities)
static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
{
int ret;
- struct vmw_buffer_object *vbo;
+ struct vmw_bo *vbo;
struct ttm_bo_kmap_obj map;
volatile SVGA3dQueryResult *result;
bool dummy;
+ struct vmw_bo_params bo_params = {
+ .domain = VMW_BO_DOMAIN_SYS,
+ .busy_domain = VMW_BO_DOMAIN_SYS,
+ .bo_type = ttm_bo_type_kernel,
+ .size = PAGE_SIZE,
+ .pin = true,
+ .keep_resv = true,
+ };
/*
* Create the vbo as pinned, so that a tryreserve will
* immediately succeed. This is because we're the only
* user of the bo currently.
*/
- vbo = kzalloc(sizeof(*vbo), GFP_KERNEL);
- if (!vbo)
- return -ENOMEM;
-
- ret = vmw_bo_init(dev_priv, vbo, PAGE_SIZE,
- &vmw_sys_placement, false, true,
- &vmw_bo_bo_free);
+ ret = vmw_bo_create(dev_priv, &bo_params, &vbo);
if (unlikely(ret != 0))
return ret;
- ret = ttm_bo_reserve(&vbo->base, false, true, NULL);
- BUG_ON(ret != 0);
- vmw_bo_pin_reserved(vbo, true);
-
- ret = ttm_bo_kmap(&vbo->base, 0, 1, &map);
+ ret = ttm_bo_kmap(&vbo->tbo, 0, 1, &map);
if (likely(ret == 0)) {
result = ttm_kmap_obj_virtual(&map, &dummy);
result->totalSize = sizeof(*result);
@@ -384,7 +405,7 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
ttm_bo_kunmap(&map);
}
vmw_bo_pin_reserved(vbo, false);
- ttm_bo_unreserve(&vbo->base);
+ ttm_bo_unreserve(&vbo->tbo);
if (unlikely(ret != 0)) {
DRM_ERROR("Dummy query buffer map failed.\n");
@@ -399,10 +420,6 @@ static int vmw_device_init(struct vmw_private *dev_priv)
{
bool uses_fb_traces = false;
- DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
- DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
- DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
-
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
@@ -423,8 +440,10 @@ static int vmw_device_init(struct vmw_private *dev_priv)
vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1);
}
- dev_priv->last_read_seqno = vmw_fence_read(dev_priv);
- atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
+ u32 seqno = vmw_fence_read(dev_priv);
+
+ atomic_set(&dev_priv->last_read_seqno, seqno);
+ atomic_set(&dev_priv->marker_seq, seqno);
return 0;
}
@@ -437,7 +456,7 @@ static void vmw_device_fini(struct vmw_private *vmw)
while (vmw_read(vmw, SVGA_REG_BUSY) != 0)
;
- vmw->last_read_seqno = vmw_fence_read(vmw);
+ atomic_set(&vmw->last_read_seqno, vmw_fence_read(vmw));
vmw_write(vmw, SVGA_REG_CONFIG_DONE,
vmw->config_done_state);
@@ -593,8 +612,8 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
width = vmw_read(dev_priv, SVGA_REG_WIDTH);
height = vmw_read(dev_priv, SVGA_REG_HEIGHT);
- width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH);
- height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT);
+ width = max_t(uint32_t, width, VMWGFX_MIN_INITIAL_WIDTH);
+ height = max_t(uint32_t, height, VMWGFX_MIN_INITIAL_HEIGHT);
if (width > dev_priv->fb_max_width ||
height > dev_priv->fb_max_height) {
@@ -603,8 +622,8 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
* This is a host error and shouldn't occur.
*/
- width = VMW_MIN_INITIAL_WIDTH;
- height = VMW_MIN_INITIAL_HEIGHT;
+ width = VMWGFX_MIN_INITIAL_WIDTH;
+ height = VMWGFX_MIN_INITIAL_HEIGHT;
}
dev_priv->initial_width = width;
@@ -626,23 +645,24 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
static int vmw_dma_select_mode(struct vmw_private *dev_priv)
{
static const char *names[vmw_dma_map_max] = {
- [vmw_dma_phys] = "Using physical TTM page addresses.",
[vmw_dma_alloc_coherent] = "Using coherent TTM pages.",
[vmw_dma_map_populate] = "Caching DMA mappings.",
[vmw_dma_map_bind] = "Giving up DMA mappings early."};
- /* TTM currently doesn't fully support SEV encryption. */
- if (mem_encrypt_active())
- return -EINVAL;
-
- if (vmw_force_coherent)
+ /*
+ * When running with SEV we always want dma mappings, because
+ * otherwise ttm tt pool pages will bounce through swiotlb running
+ * out of available space.
+ */
+ if (vmw_force_coherent || cc_platform_has(CC_ATTR_MEM_ENCRYPT))
dev_priv->map_mode = vmw_dma_alloc_coherent;
else if (vmw_restrict_iommu)
dev_priv->map_mode = vmw_dma_map_bind;
else
dev_priv->map_mode = vmw_dma_map_populate;
- DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
+ drm_info(&dev_priv->drm,
+ "DMA map mode: %s\n", names[dev_priv->map_mode]);
return 0;
}
@@ -660,9 +680,9 @@ static int vmw_dma_masks(struct vmw_private *dev_priv)
int ret = 0;
ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
- if (dev_priv->map_mode != vmw_dma_phys &&
- (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
- DRM_INFO("Restricting DMA addresses to 44 bits.\n");
+ if (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask) {
+ drm_info(&dev_priv->drm,
+ "Restricting DMA addresses to 44 bits.\n");
return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
}
@@ -672,27 +692,19 @@ static int vmw_dma_masks(struct vmw_private *dev_priv)
static int vmw_vram_manager_init(struct vmw_private *dev_priv)
{
int ret;
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- ret = vmw_thp_init(dev_priv);
-#else
ret = ttm_range_man_init(&dev_priv->bdev, TTM_PL_VRAM, false,
dev_priv->vram_size >> PAGE_SHIFT);
-#endif
ttm_resource_manager_set_used(ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM), false);
return ret;
}
static void vmw_vram_manager_fini(struct vmw_private *dev_priv)
{
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- vmw_thp_fini(dev_priv);
-#else
ttm_range_man_fini(&dev_priv->bdev, TTM_PL_VRAM);
-#endif
}
static int vmw_setup_pci_resources(struct vmw_private *dev,
- unsigned long pci_id)
+ u32 pci_id)
{
resource_size_t rmmio_start;
resource_size_t rmmio_size;
@@ -703,7 +715,7 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
pci_set_master(pdev);
- ret = pci_request_regions(pdev, "vmwgfx probe");
+ ret = pcim_request_all_regions(pdev, "vmwgfx probe");
if (ret)
return ret;
@@ -714,14 +726,15 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
dev->vram_start = pci_resource_start(pdev, 2);
dev->vram_size = pci_resource_len(pdev, 2);
- DRM_INFO("Register MMIO at 0x%pa size is %llu kiB\n",
+ drm_info(&dev->drm,
+ "Register MMIO at 0x%pa size is %llu KiB\n",
&rmmio_start, (uint64_t)rmmio_size / 1024);
dev->rmmio = devm_ioremap(dev->drm.dev,
rmmio_start,
rmmio_size);
if (!dev->rmmio) {
- DRM_ERROR("Failed mapping registers mmio memory.\n");
- pci_release_regions(pdev);
+ drm_err(&dev->drm,
+ "Failed mapping registers mmio memory.\n");
return -ENOMEM;
}
} else if (pci_id == VMWGFX_PCI_ID_SVGA2) {
@@ -731,20 +744,20 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
fifo_start = pci_resource_start(pdev, 2);
fifo_size = pci_resource_len(pdev, 2);
- DRM_INFO("FIFO at %pa size is %llu kiB\n",
+ drm_info(&dev->drm,
+ "FIFO at %pa size is %llu KiB\n",
&fifo_start, (uint64_t)fifo_size / 1024);
dev->fifo_mem = devm_memremap(dev->drm.dev,
fifo_start,
fifo_size,
- MEMREMAP_WB);
+ MEMREMAP_WB | MEMREMAP_DEC);
if (IS_ERR(dev->fifo_mem)) {
- DRM_ERROR("Failed mapping FIFO memory.\n");
- pci_release_regions(pdev);
+ drm_err(&dev->drm,
+ "Failed mapping FIFO memory.\n");
return PTR_ERR(dev->fifo_mem);
}
} else {
- pci_release_regions(pdev);
return -EINVAL;
}
@@ -754,7 +767,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
* size will be equal to or bigger than the size reported by
* SVGA_REG_VRAM_SIZE.
*/
- DRM_INFO("VRAM at %pa size is %llu kiB\n",
+ drm_info(&dev->drm,
+ "VRAM at %pa size is %llu KiB\n",
&dev->vram_start, (uint64_t)dev->vram_size / 1024);
return 0;
@@ -768,31 +782,67 @@ static int vmw_detect_version(struct vmw_private *dev)
SVGA_ID_3 : SVGA_ID_2);
svga_id = vmw_read(dev, SVGA_REG_ID);
if (svga_id != SVGA_ID_2 && svga_id != SVGA_ID_3) {
- DRM_ERROR("Unsupported SVGA ID 0x%x on chipset 0x%x\n",
- svga_id, dev->vmw_chipset);
+ drm_err(&dev->drm,
+ "Unsupported SVGA ID 0x%x on chipset 0x%x\n",
+ svga_id, dev->pci_id);
return -ENOSYS;
}
BUG_ON(vmw_is_svga_v3(dev) && (svga_id != SVGA_ID_3));
- DRM_INFO("Running on SVGA version %d.\n", (svga_id & 0xff));
+ drm_info(&dev->drm,
+ "Running on SVGA version %d.\n", (svga_id & 0xff));
return 0;
}
+static void vmw_write_driver_id(struct vmw_private *dev)
+{
+ if ((dev->capabilities2 & SVGA_CAP2_DX2) != 0) {
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_ID,
+ SVGA_REG_GUEST_DRIVER_ID_LINUX);
+
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION1,
+ LINUX_VERSION_MAJOR << 24 |
+ LINUX_VERSION_PATCHLEVEL << 16 |
+ LINUX_VERSION_SUBLEVEL);
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION2,
+ VMWGFX_DRIVER_MAJOR << 24 |
+ VMWGFX_DRIVER_MINOR << 16 |
+ VMWGFX_DRIVER_PATCHLEVEL);
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION3, 0);
+
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_ID,
+ SVGA_REG_GUEST_DRIVER_ID_SUBMIT);
+ }
+}
+
+static void vmw_sw_context_init(struct vmw_private *dev_priv)
+{
+ struct vmw_sw_context *sw_context = &dev_priv->ctx;
+
+ hash_init(sw_context->res_ht);
+}
+
+static void vmw_sw_context_fini(struct vmw_private *dev_priv)
+{
+ struct vmw_sw_context *sw_context = &dev_priv->ctx;
+
+ vfree(sw_context->cmd_bounce);
+ if (sw_context->staged_bindings)
+ vmw_binding_state_free(sw_context->staged_bindings);
+}
+
static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
{
int ret;
enum vmw_res_type i;
bool refuse_dma = false;
- struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
- dev_priv->vmw_chipset = pci_id;
- dev_priv->drm.dev_private = dev_priv;
+ vmw_sw_context_init(dev_priv);
mutex_init(&dev_priv->cmdbuf_mutex);
mutex_init(&dev_priv->binding_mutex);
spin_lock_init(&dev_priv->resource_lock);
spin_lock_init(&dev_priv->hw_lock);
spin_lock_init(&dev_priv->waiter_lock);
- spin_lock_init(&dev_priv->cap_lock);
spin_lock_init(&dev_priv->cursor_lock);
ret = vmw_setup_pci_resources(dev_priv, pci_id);
@@ -800,7 +850,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
return ret;
ret = vmw_detect_version(dev_priv);
if (ret)
- goto out_no_pci_or_version;
+ return ret;
for (i = vmw_res_context; i < vmw_res_max; ++i) {
@@ -817,22 +867,37 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->assume_16bpp = !!vmw_assume_16bpp;
- dev_priv->enable_fb = enable_fbdev;
-
-
dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
-
+ vmw_print_bitmap(&dev_priv->drm, "Capabilities",
+ dev_priv->capabilities,
+ cap1_names, ARRAY_SIZE(cap1_names));
if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER) {
dev_priv->capabilities2 = vmw_read(dev_priv, SVGA_REG_CAP2);
+ vmw_print_bitmap(&dev_priv->drm, "Capabilities2",
+ dev_priv->capabilities2,
+ cap2_names, ARRAY_SIZE(cap2_names));
+ }
+
+ if (!vmwgfx_supported(dev_priv)) {
+ vmw_disable_backdoor();
+ drm_err_once(&dev_priv->drm,
+ "vmwgfx seems to be running on an unsupported hypervisor.");
+ drm_err_once(&dev_priv->drm,
+ "This configuration is likely broken.");
+ drm_err_once(&dev_priv->drm,
+ "Please switch to a supported graphics device to avoid problems.");
}
+ vmw_vkms_init(dev_priv);
ret = vmw_dma_select_mode(dev_priv);
if (unlikely(ret != 0)) {
- DRM_INFO("Restricting capabilities since DMA not available.\n");
+ drm_info(&dev_priv->drm,
+ "Restricting capabilities since DMA not available.\n");
refuse_dma = true;
if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
- DRM_INFO("Disabling 3D acceleration.\n");
+ drm_info(&dev_priv->drm,
+ "Disabling 3D acceleration.\n");
}
dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
@@ -870,17 +935,9 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
vmw_read(dev_priv,
SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
- /*
- * Workaround for low memory 2D VMs to compensate for the
- * allocation taken by fbdev
- */
- if (!(dev_priv->capabilities & SVGA_CAP_3D))
- mem_size *= 3;
-
dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
- dev_priv->prim_bb_mem =
- vmw_read(dev_priv,
- SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);
+ dev_priv->max_primary_mem =
+ vmw_read(dev_priv, SVGA_REG_MAX_PRIMARY_MEM);
dev_priv->max_mob_size =
vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
dev_priv->stdu_max_width =
@@ -899,14 +956,17 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
} else {
dev_priv->texture_max_width = 8192;
dev_priv->texture_max_height = 8192;
- dev_priv->prim_bb_mem = dev_priv->vram_size;
+ dev_priv->max_primary_mem = dev_priv->vram_size;
}
+ drm_info(&dev_priv->drm,
+ "Legacy memory limits: VRAM = %llu KiB, FIFO = %llu KiB, surface = %u KiB\n",
+ (u64)dev_priv->vram_size / 1024,
+ (u64)dev_priv->fifo_mem_size / 1024,
+ dev_priv->memory_size / 1024);
- vmw_print_capabilities(dev_priv->capabilities);
- if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER)
- vmw_print_capabilities2(dev_priv->capabilities2);
- DRM_INFO("Supports command queues = %d\n",
- vmw_cmd_supported((dev_priv)));
+ drm_info(&dev_priv->drm,
+ "MOB limits: max mob size = %u KiB, max mob pages = %u\n",
+ dev_priv->max_mob_size / 1024, dev_priv->max_mob_pages);
ret = vmw_dma_masks(dev_priv);
if (unlikely(ret != 0))
@@ -915,15 +975,16 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dma_set_max_seg_size(dev_priv->drm.dev, U32_MAX);
if (dev_priv->capabilities & SVGA_CAP_GMR2) {
- DRM_INFO("Max GMR ids is %u\n",
+ drm_info(&dev_priv->drm,
+ "Max GMR ids is %u\n",
(unsigned)dev_priv->max_gmr_ids);
- DRM_INFO("Max number of GMR pages is %u\n",
+ drm_info(&dev_priv->drm,
+ "Max number of GMR pages is %u\n",
(unsigned)dev_priv->max_gmr_pages);
- DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
- (unsigned)dev_priv->memory_size / 1024);
}
- DRM_INFO("Maximum display memory size is %llu kiB\n",
- (uint64_t)dev_priv->prim_bb_mem / 1024);
+ drm_info(&dev_priv->drm,
+ "Maximum display memory size is %llu KiB\n",
+ (uint64_t)dev_priv->max_primary_mem / 1024);
/* Need mmio memory to check for fifo pitchlock cap. */
if (!(dev_priv->capabilities & SVGA_CAP_DISPLAY_TOPOLOGY) &&
@@ -934,19 +995,20 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
goto out_err0;
}
- dev_priv->tdev = ttm_object_device_init(&ttm_mem_glob, 12,
- &vmw_prime_dmabuf_ops);
+ dev_priv->tdev = ttm_object_device_init(&vmw_prime_dmabuf_ops);
if (unlikely(dev_priv->tdev == NULL)) {
- DRM_ERROR("Unable to initialize TTM object management.\n");
+ drm_err(&dev_priv->drm,
+ "Unable to initialize TTM object management.\n");
ret = -ENOMEM;
goto out_err0;
}
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
- ret = vmw_irq_install(&dev_priv->drm, pdev->irq);
+ ret = vmw_irq_install(dev_priv);
if (ret != 0) {
- DRM_ERROR("Failed installing irq: %d\n", ret);
+ drm_err(&dev_priv->drm,
+ "Failed installing irq: %d\n", ret);
goto out_no_irq;
}
}
@@ -957,17 +1019,15 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
goto out_no_fman;
}
- drm_vma_offset_manager_init(&dev_priv->vma_manager,
- DRM_FILE_PAGE_OFFSET_START,
- DRM_FILE_PAGE_OFFSET_SIZE);
ret = ttm_device_init(&dev_priv->bdev, &vmw_bo_driver,
dev_priv->drm.dev,
dev_priv->drm.anon_inode->i_mapping,
- &dev_priv->vma_manager,
- dev_priv->map_mode == vmw_dma_alloc_coherent,
- false);
+ dev_priv->drm.vma_offset_manager,
+ (dev_priv->map_mode == vmw_dma_alloc_coherent) ?
+ TTM_ALLOCATION_POOL_USE_DMA_ALLOC : 0);
if (unlikely(ret != 0)) {
- DRM_ERROR("Failed initializing TTM buffer object driver.\n");
+ drm_err(&dev_priv->drm,
+ "Failed initializing TTM buffer object driver.\n");
goto out_no_bdev;
}
@@ -978,7 +1038,15 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
ret = vmw_vram_manager_init(dev_priv);
if (unlikely(ret != 0)) {
- DRM_ERROR("Failed initializing memory manager for VRAM.\n");
+ drm_err(&dev_priv->drm,
+ "Failed initializing memory manager for VRAM.\n");
+ goto out_no_vram;
+ }
+
+ ret = vmw_devcaps_create(dev_priv);
+ if (unlikely(ret != 0)) {
+ drm_err(&dev_priv->drm,
+ "Failed initializing device caps.\n");
goto out_no_vram;
}
@@ -992,7 +1060,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
refuse_dma ||
vmw_gmrid_man_init(dev_priv, VMW_PL_GMR) != 0) {
- DRM_INFO("No GMR memory available. "
+ drm_info(&dev_priv->drm,
+ "No GMR memory available. "
"Graphics memory resources are very limited.\n");
dev_priv->has_gmr = false;
}
@@ -1001,35 +1070,36 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->has_mob = true;
if (vmw_gmrid_man_init(dev_priv, VMW_PL_MOB) != 0) {
- DRM_INFO("No MOB memory available. "
+ drm_info(&dev_priv->drm,
+ "No MOB memory available. "
+ "3D will be disabled.\n");
+ dev_priv->has_mob = false;
+ }
+ if (vmw_sys_man_init(dev_priv) != 0) {
+ drm_info(&dev_priv->drm,
+ "No MOB page table memory available. "
"3D will be disabled.\n");
dev_priv->has_mob = false;
}
}
if (dev_priv->has_mob && (dev_priv->capabilities & SVGA_CAP_DX)) {
- spin_lock(&dev_priv->cap_lock);
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_DXCONTEXT);
- if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_DXCONTEXT))
dev_priv->sm_type = VMW_SM_4;
- spin_unlock(&dev_priv->cap_lock);
}
- vmw_validation_mem_init_ttm(dev_priv, VMWGFX_VALIDATION_MEM_GRAN);
-
/* SVGA_CAP2_DX2 (DefineGBSurface_v3) is needed for SM4_1 support */
if (has_sm4_context(dev_priv) &&
(dev_priv->capabilities2 & SVGA_CAP2_DX2)) {
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_SM41);
-
- if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_SM41))
dev_priv->sm_type = VMW_SM_4_1;
-
if (has_sm4_1_context(dev_priv) &&
- (dev_priv->capabilities2 & SVGA_CAP2_DX3)) {
- vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_SM5);
- if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+ (dev_priv->capabilities2 & SVGA_CAP2_DX3)) {
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_SM5)) {
dev_priv->sm_type = VMW_SM_5;
+ if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_GL43))
+ dev_priv->sm_type = VMW_SM_5_1X;
+ }
}
}
@@ -1042,23 +1112,11 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
if (ret)
goto out_no_fifo;
- if (dev_priv->sm_type == VMW_SM_5)
- DRM_INFO("SM5 support available.\n");
- if (dev_priv->sm_type == VMW_SM_4_1)
- DRM_INFO("SM4_1 support available.\n");
- if (dev_priv->sm_type == VMW_SM_4)
- DRM_INFO("SM4 support available.\n");
- DRM_INFO("Running without reservation semaphore\n");
-
+ vmw_print_sm_type(dev_priv);
vmw_host_printf("vmwgfx: Module Version: %d.%d.%d (kernel: %s)",
VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR,
VMWGFX_DRIVER_PATCHLEVEL, UTS_RELEASE);
-
- if (dev_priv->enable_fb) {
- vmw_fifo_resource_inc(dev_priv);
- vmw_svga_enable(dev_priv);
- vmw_fb_init(dev_priv);
- }
+ vmw_write_driver_id(dev_priv);
dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
register_pm_notifier(&dev_priv->pm_nb);
@@ -1069,10 +1127,13 @@ out_no_fifo:
vmw_overlay_close(dev_priv);
vmw_kms_close(dev_priv);
out_no_kms:
- if (dev_priv->has_mob)
+ if (dev_priv->has_mob) {
vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB);
+ vmw_sys_man_fini(dev_priv);
+ }
if (dev_priv->has_gmr)
vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR);
+ vmw_devcaps_destroy(dev_priv);
vmw_vram_manager_fini(dev_priv);
out_no_vram:
ttm_device_fini(&dev_priv->bdev);
@@ -1089,29 +1150,23 @@ out_err0:
if (dev_priv->ctx.staged_bindings)
vmw_binding_state_free(dev_priv->ctx.staged_bindings);
-out_no_pci_or_version:
- pci_release_regions(pdev);
+
return ret;
}
static void vmw_driver_unload(struct drm_device *dev)
{
struct vmw_private *dev_priv = vmw_priv(dev);
- struct pci_dev *pdev = to_pci_dev(dev->dev);
enum vmw_res_type i;
unregister_pm_notifier(&dev_priv->pm_nb);
- if (dev_priv->ctx.res_ht_initialized)
- drm_ht_remove(&dev_priv->ctx.res_ht);
- vfree(dev_priv->ctx.cmd_bounce);
- if (dev_priv->enable_fb) {
- vmw_fb_off(dev_priv);
- vmw_fb_close(dev_priv);
- vmw_fifo_resource_dec(dev_priv);
- vmw_svga_disable(dev_priv);
- }
+ vmw_sw_context_fini(dev_priv);
+ vmw_fifo_resource_dec(dev_priv);
+
+ vmw_svga_disable(dev_priv);
+ vmw_vkms_cleanup(dev_priv);
vmw_kms_close(dev_priv);
vmw_overlay_close(dev_priv);
@@ -1119,24 +1174,24 @@ static void vmw_driver_unload(struct drm_device *dev)
vmw_gmrid_man_fini(dev_priv, VMW_PL_GMR);
vmw_release_device_early(dev_priv);
- if (dev_priv->has_mob)
+ if (dev_priv->has_mob) {
vmw_gmrid_man_fini(dev_priv, VMW_PL_MOB);
+ vmw_sys_man_fini(dev_priv);
+ }
+ vmw_devcaps_destroy(dev_priv);
vmw_vram_manager_fini(dev_priv);
ttm_device_fini(&dev_priv->bdev);
- drm_vma_offset_manager_destroy(&dev_priv->vma_manager);
vmw_release_device_late(dev_priv);
vmw_fence_manager_takedown(dev_priv->fman);
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
vmw_irq_uninstall(&dev_priv->drm);
ttm_object_device_release(&dev_priv->tdev);
- if (dev_priv->ctx.staged_bindings)
- vmw_binding_state_free(dev_priv->ctx.staged_bindings);
for (i = vmw_res_context; i < vmw_res_max; ++i)
idr_destroy(&dev_priv->res_idr[i]);
- pci_release_regions(pdev);
+ vmw_mksstat_remove_all(dev_priv);
}
static void vmw_postclose(struct drm_device *dev,
@@ -1158,7 +1213,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
if (unlikely(!vmw_fp))
return ret;
- vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
+ vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev);
if (unlikely(vmw_fp->tfile == NULL))
goto out_no_tfile;
@@ -1243,11 +1298,22 @@ static void vmw_master_set(struct drm_device *dev,
static void vmw_master_drop(struct drm_device *dev,
struct drm_file *file_priv)
{
- struct vmw_private *dev_priv = vmw_priv(dev);
+}
- vmw_kms_legacy_hotspot_clear(dev_priv);
- if (!dev_priv->enable_fb)
- vmw_svga_disable(dev_priv);
+bool vmwgfx_supported(struct vmw_private *vmw)
+{
+#if defined(CONFIG_X86)
+ return hypervisor_is_type(X86_HYPER_VMWARE);
+#elif defined(CONFIG_ARM64)
+ /*
+ * On aarch64 only svga3 is supported
+ */
+ return vmw->pci_id == VMWGFX_PCI_ID_SVGA3;
+#else
+ drm_warn_once(&vmw->drm,
+ "vmwgfx is running on an unknown architecture.");
+ return false;
+#endif
}
/**
@@ -1332,21 +1398,28 @@ static void vmw_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
- ttm_mem_global_release(&ttm_mem_glob);
drm_dev_unregister(dev);
vmw_driver_unload(dev);
}
-static unsigned long
-vmw_get_unmapped_area(struct file *file, unsigned long uaddr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
+static void vmw_debugfs_resource_managers_init(struct vmw_private *vmw)
{
- struct drm_file *file_priv = file->private_data;
- struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev);
-
- return drm_get_unmapped_area(file, uaddr, len, pgoff, flags,
- &dev_priv->vma_manager);
+ struct drm_minor *minor = vmw->drm.primary;
+ struct dentry *root = minor->debugfs_root;
+
+ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, TTM_PL_SYSTEM),
+ root, "system_ttm");
+ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, TTM_PL_VRAM),
+ root, "vram_ttm");
+ if (vmw->has_gmr)
+ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_GMR),
+ root, "gmr_ttm");
+ if (vmw->has_mob) {
+ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_MOB),
+ root, "mob_ttm");
+ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_SYSTEM),
+ root, "system_mob_ttm");
+ }
}
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
@@ -1436,25 +1509,19 @@ static int vmw_pm_freeze(struct device *kdev)
DRM_ERROR("Failed to freeze modesetting.\n");
return ret;
}
- if (dev_priv->enable_fb)
- vmw_fb_off(dev_priv);
vmw_execbuf_release_pinned_bo(dev_priv);
vmw_resource_evict_all(dev_priv);
vmw_release_device_early(dev_priv);
while (ttm_device_swapout(&dev_priv->bdev, &ctx, GFP_KERNEL) > 0);
- if (dev_priv->enable_fb)
- vmw_fifo_resource_dec(dev_priv);
+ vmw_fifo_resource_dec(dev_priv);
if (atomic_read(&dev_priv->num_fifo_resources) != 0) {
DRM_ERROR("Can't hibernate while 3D resources are active.\n");
- if (dev_priv->enable_fb)
- vmw_fifo_resource_inc(dev_priv);
+ vmw_fifo_resource_inc(dev_priv);
WARN_ON(vmw_request_device_late(dev_priv));
dev_priv->suspend_locked = false;
if (dev_priv->suspend_state)
vmw_kms_resume(dev);
- if (dev_priv->enable_fb)
- vmw_fb_on(dev_priv);
return -EBUSY;
}
@@ -1474,24 +1541,19 @@ static int vmw_pm_restore(struct device *kdev)
vmw_detect_version(dev_priv);
- if (dev_priv->enable_fb)
- vmw_fifo_resource_inc(dev_priv);
+ vmw_fifo_resource_inc(dev_priv);
ret = vmw_request_device(dev_priv);
if (ret)
return ret;
- if (dev_priv->enable_fb)
- __vmw_svga_enable(dev_priv);
+ __vmw_svga_enable(dev_priv);
vmw_fence_fifo_up(dev_priv->fman);
dev_priv->suspend_locked = false;
if (dev_priv->suspend_state)
vmw_kms_resume(&dev_priv->drm);
- if (dev_priv->enable_fb)
- vmw_fb_on(dev_priv);
-
return 0;
}
@@ -1508,19 +1570,19 @@ static const struct file_operations vmwgfx_driver_fops = {
.open = drm_open,
.release = drm_release,
.unlocked_ioctl = vmw_unlocked_ioctl,
- .mmap = vmw_mmap,
+ .mmap = drm_gem_mmap,
.poll = drm_poll,
.read = drm_read,
#if defined(CONFIG_COMPAT)
.compat_ioctl = vmw_compat_ioctl,
#endif
.llseek = noop_llseek,
- .get_unmapped_area = vmw_get_unmapped_area,
+ .fop_flags = FOP_UNSIGNED_OFFSET,
};
static const struct drm_driver driver = {
.driver_features =
- DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC,
+ DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_GEM | DRIVER_CURSOR_HOTSPOT,
.ioctls = vmw_ioctls,
.num_ioctls = ARRAY_SIZE(vmw_ioctls),
.master_set = vmw_master_set,
@@ -1529,16 +1591,17 @@ static const struct drm_driver driver = {
.postclose = vmw_postclose,
.dumb_create = vmw_dumb_create,
- .dumb_map_offset = vmw_dumb_map_offset,
- .dumb_destroy = vmw_dumb_destroy,
+ .dumb_map_offset = drm_gem_ttm_dumb_map_offset,
.prime_fd_to_handle = vmw_prime_fd_to_handle,
.prime_handle_to_fd = vmw_prime_handle_to_fd,
+ .gem_prime_import_sg_table = vmw_prime_import_sg_table,
+
+ DRM_FBDEV_TTM_DRIVER_OPS,
.fops = &vmwgfx_driver_fops,
.name = VMWGFX_DRIVER_NAME,
.desc = VMWGFX_DRIVER_DESC,
- .date = VMWGFX_DRIVER_DATE,
.major = VMWGFX_DRIVER_MAJOR,
.minor = VMWGFX_DRIVER_MINOR,
.patchlevel = VMWGFX_DRIVER_PATCHLEVEL
@@ -1559,58 +1622,46 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct vmw_private *vmw;
int ret;
- ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "svgadrmfb");
+ ret = aperture_remove_conflicting_pci_devices(pdev, driver.name);
if (ret)
- return ret;
+ goto out_error;
ret = pcim_enable_device(pdev);
if (ret)
- return ret;
+ goto out_error;
vmw = devm_drm_dev_alloc(&pdev->dev, &driver,
struct vmw_private, drm);
- if (IS_ERR(vmw))
- return PTR_ERR(vmw);
+ if (IS_ERR(vmw)) {
+ ret = PTR_ERR(vmw);
+ goto out_error;
+ }
pci_set_drvdata(pdev, &vmw->drm);
- ret = ttm_mem_global_init(&ttm_mem_glob, &pdev->dev);
- if (ret)
- return ret;
-
ret = vmw_driver_load(vmw, ent->device);
if (ret)
- return ret;
+ goto out_error;
ret = drm_dev_register(&vmw->drm, 0);
- if (ret) {
- vmw_driver_unload(&vmw->drm);
- return ret;
- }
-
- return 0;
-}
+ if (ret)
+ goto out_unload;
-static int __init vmwgfx_init(void)
-{
- int ret;
+ vmw_fifo_resource_inc(vmw);
+ vmw_svga_enable(vmw);
+ drm_client_setup(&vmw->drm, NULL);
- if (vgacon_text_force())
- return -EINVAL;
+ vmw_debugfs_gem_init(vmw);
+ vmw_debugfs_resource_managers_init(vmw);
- ret = pci_register_driver(&vmw_pci_driver);
- if (ret)
- DRM_ERROR("Failed initializing DRM.\n");
+ return 0;
+out_unload:
+ vmw_driver_unload(&vmw->drm);
+out_error:
return ret;
}
-static void __exit vmwgfx_exit(void)
-{
- pci_unregister_driver(&vmw_pci_driver);
-}
-
-module_init(vmwgfx_init);
-module_exit(vmwgfx_exit);
+drm_module_pci_driver(vmw_pci_driver);
MODULE_AUTHOR("VMware Inc. and others");
MODULE_DESCRIPTION("Standalone drm driver for the VMware SVGA device");