diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 169 |
1 files changed, 119 insertions, 50 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 399f70d340eb..6f5ea00973e0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -31,12 +31,13 @@ #include <linux/pci.h> #include <linux/mem_encrypt.h> +#include <drm/drm_aperture.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_ioctl.h> #include <drm/drm_sysfs.h> #include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_placement.h> +#include <generated/utsrelease.h> #include "ttm_object.h" #include "vmwgfx_binding.h" @@ -50,7 +51,7 @@ #define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) -/** +/* * Fully encoded drm commands. Might move to vmw_drm.h */ @@ -246,6 +247,7 @@ static const struct drm_ioctl_desc vmw_ioctls[] = { static const struct pci_device_id vmw_pci_id_list[] = { { PCI_DEVICE(0x15ad, VMWGFX_PCI_ID_SVGA2) }, + { PCI_DEVICE(0x15ad, VMWGFX_PCI_ID_SVGA3) }, { } }; MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); @@ -393,6 +395,60 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv) return ret; } +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); + + vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_ENABLE | + SVGA_REG_ENABLE_HIDE); + + uses_fb_traces = !vmw_cmd_supported(dev_priv) && + (dev_priv->capabilities & SVGA_CAP_TRACES) != 0; + + vmw_write(dev_priv, SVGA_REG_TRACES, uses_fb_traces); + dev_priv->fifo = vmw_fifo_create(dev_priv); + if (IS_ERR(dev_priv->fifo)) { + int err = PTR_ERR(dev_priv->fifo); + dev_priv->fifo = NULL; + return err; + } else if (!dev_priv->fifo) { + 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); + return 0; +} + +static void vmw_device_fini(struct vmw_private *vmw) +{ + /* + * Legacy sync + */ + vmw_write(vmw, SVGA_REG_SYNC, SVGA_SYNC_GENERIC); + while (vmw_read(vmw, SVGA_REG_BUSY) != 0) + ; + + vmw->last_read_seqno = vmw_fence_read(vmw); + + vmw_write(vmw, SVGA_REG_CONFIG_DONE, + vmw->config_done_state); + vmw_write(vmw, SVGA_REG_ENABLE, + vmw->enable_state); + vmw_write(vmw, SVGA_REG_TRACES, + vmw->traces_state); + + vmw_fifo_destroy(vmw); +} + /** * vmw_request_device_late - Perform late device setup * @@ -433,9 +489,9 @@ static int vmw_request_device(struct vmw_private *dev_priv) { int ret; - ret = vmw_fifo_init(dev_priv, &dev_priv->fifo); + ret = vmw_device_init(dev_priv); if (unlikely(ret != 0)) { - DRM_ERROR("Unable to initialize FIFO.\n"); + DRM_ERROR("Unable to initialize the device.\n"); return ret; } vmw_fence_fifo_up(dev_priv->fman); @@ -469,7 +525,7 @@ out_no_query_bo: vmw_cmdbuf_man_destroy(dev_priv->cman); out_no_mob: vmw_fence_fifo_down(dev_priv->fman); - vmw_fifo_release(dev_priv, &dev_priv->fifo); + vmw_device_fini(dev_priv); return ret; } @@ -517,7 +573,7 @@ static void vmw_release_device_late(struct vmw_private *dev_priv) if (dev_priv->cman) vmw_cmdbuf_man_destroy(dev_priv->cman); - vmw_fifo_release(dev_priv, &dev_priv->fifo); + vmw_device_fini(dev_priv); } /* @@ -638,6 +694,8 @@ static void vmw_vram_manager_fini(struct vmw_private *dev_priv) static int vmw_setup_pci_resources(struct vmw_private *dev, unsigned long pci_id) { + resource_size_t rmmio_start; + resource_size_t rmmio_size; resource_size_t fifo_start; resource_size_t fifo_size; int ret; @@ -649,23 +707,45 @@ static int vmw_setup_pci_resources(struct vmw_private *dev, if (ret) return ret; - dev->io_start = pci_resource_start(pdev, 0); - dev->vram_start = pci_resource_start(pdev, 1); - dev->vram_size = pci_resource_len(pdev, 1); - fifo_start = pci_resource_start(pdev, 2); - fifo_size = pci_resource_len(pdev, 2); - - DRM_INFO("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); - - if (IS_ERR(dev->fifo_mem)) { - DRM_ERROR("Failed mapping FIFO memory.\n"); + dev->pci_id = pci_id; + if (pci_id == VMWGFX_PCI_ID_SVGA3) { + rmmio_start = pci_resource_start(pdev, 0); + rmmio_size = pci_resource_len(pdev, 0); + 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", + &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); + return -ENOMEM; + } + } else if (pci_id == VMWGFX_PCI_ID_SVGA2) { + dev->io_start = pci_resource_start(pdev, 0); + dev->vram_start = pci_resource_start(pdev, 1); + dev->vram_size = pci_resource_len(pdev, 1); + fifo_start = pci_resource_start(pdev, 2); + fifo_size = pci_resource_len(pdev, 2); + + DRM_INFO("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); + + if (IS_ERR(dev->fifo_mem)) { + DRM_ERROR("Failed mapping FIFO memory.\n"); + pci_release_regions(pdev); + return PTR_ERR(dev->fifo_mem); + } + } else { pci_release_regions(pdev); - return PTR_ERR(dev->fifo_mem); + return -EINVAL; } /* @@ -684,13 +764,16 @@ static int vmw_detect_version(struct vmw_private *dev) { uint32_t svga_id; - vmw_write(dev, SVGA_REG_ID, SVGA_ID_2); + vmw_write(dev, SVGA_REG_ID, vmw_is_svga_v3(dev) ? + SVGA_ID_3 : SVGA_ID_2); svga_id = vmw_read(dev, SVGA_REG_ID); - if (svga_id != SVGA_ID_2) { + 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); 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)); return 0; } @@ -699,16 +782,13 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) int ret; enum vmw_res_type i; bool refuse_dma = false; - char host_log[100] = {0}; struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); dev_priv->vmw_chipset = pci_id; - dev_priv->last_read_seqno = (uint32_t) -100; dev_priv->drm.dev_private = dev_priv; mutex_init(&dev_priv->cmdbuf_mutex); mutex_init(&dev_priv->binding_mutex); - ttm_lock_init(&dev_priv->reservation_sem); spin_lock_init(&dev_priv->resource_lock); spin_lock_init(&dev_priv->hw_lock); spin_lock_init(&dev_priv->waiter_lock); @@ -724,7 +804,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) for (i = vmw_res_context; i < vmw_res_max; ++i) { - idr_init(&dev_priv->res_idr[i]); + idr_init_base(&dev_priv->res_idr[i], 1); INIT_LIST_HEAD(&dev_priv->res_lru[i]); } @@ -825,6 +905,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) 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))); ret = vmw_dma_masks(dev_priv); if (unlikely(ret != 0)) @@ -966,11 +1048,11 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) 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"); - snprintf(host_log, sizeof(host_log), "vmwgfx: Module Version: %d.%d.%d", - VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR, - VMWGFX_DRIVER_PATCHLEVEL); - vmw_host_log(host_log); + 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); @@ -1179,7 +1261,7 @@ static void __vmw_svga_enable(struct vmw_private *dev_priv) struct ttm_resource_manager *man = ttm_manager_type(&dev_priv->bdev, TTM_PL_VRAM); if (!ttm_resource_manager_used(man)) { - vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE); + vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_ENABLE); ttm_resource_manager_set_used(man, true); } } @@ -1191,9 +1273,7 @@ static void __vmw_svga_enable(struct vmw_private *dev_priv) */ void vmw_svga_enable(struct vmw_private *dev_priv) { - (void) ttm_read_lock(&dev_priv->reservation_sem, false); __vmw_svga_enable(dev_priv); - ttm_read_unlock(&dev_priv->reservation_sem); } /** @@ -1238,7 +1318,6 @@ void vmw_svga_disable(struct vmw_private *dev_priv) * */ vmw_kms_lost_device(&dev_priv->drm); - ttm_write_lock(&dev_priv->reservation_sem, false); if (ttm_resource_manager_used(man)) { if (ttm_resource_manager_evict_all(&dev_priv->bdev, man)) DRM_ERROR("Failed evicting VRAM buffers.\n"); @@ -1247,7 +1326,6 @@ void vmw_svga_disable(struct vmw_private *dev_priv) SVGA_REG_ENABLE_HIDE | SVGA_REG_ENABLE_ENABLE); } - ttm_write_unlock(&dev_priv->reservation_sem); } static void vmw_remove(struct pci_dev *pdev) @@ -1287,14 +1365,12 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, * Once user-space processes have been frozen, we can release * the lock again. */ - ttm_suspend_lock(&dev_priv->reservation_sem); dev_priv->suspend_locked = true; break; case PM_POST_HIBERNATION: case PM_POST_RESTORE: if (READ_ONCE(dev_priv->suspend_locked)) { dev_priv->suspend_locked = false; - ttm_suspend_unlock(&dev_priv->reservation_sem); } break; default: @@ -1353,20 +1429,16 @@ static int vmw_pm_freeze(struct device *kdev) int ret; /* - * Unlock for vmw_kms_suspend. * No user-space processes should be running now. */ - ttm_suspend_unlock(&dev_priv->reservation_sem); ret = vmw_kms_suspend(&dev_priv->drm); if (ret) { - ttm_suspend_lock(&dev_priv->reservation_sem); DRM_ERROR("Failed to freeze modesetting.\n"); return ret; } if (dev_priv->enable_fb) vmw_fb_off(dev_priv); - ttm_suspend_lock(&dev_priv->reservation_sem); vmw_execbuf_release_pinned_bo(dev_priv); vmw_resource_evict_all(dev_priv); vmw_release_device_early(dev_priv); @@ -1379,7 +1451,6 @@ static int vmw_pm_freeze(struct device *kdev) vmw_fifo_resource_inc(dev_priv); WARN_ON(vmw_request_device_late(dev_priv)); dev_priv->suspend_locked = false; - ttm_suspend_unlock(&dev_priv->reservation_sem); if (dev_priv->suspend_state) vmw_kms_resume(dev); if (dev_priv->enable_fb) @@ -1401,8 +1472,7 @@ static int vmw_pm_restore(struct device *kdev) struct vmw_private *dev_priv = vmw_priv(dev); int ret; - vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); - (void) vmw_read(dev_priv, SVGA_REG_ID); + vmw_detect_version(dev_priv); if (dev_priv->enable_fb) vmw_fifo_resource_inc(dev_priv); @@ -1416,7 +1486,6 @@ static int vmw_pm_restore(struct device *kdev) vmw_fence_fifo_up(dev_priv->fman); dev_priv->suspend_locked = false; - ttm_suspend_unlock(&dev_priv->reservation_sem); if (dev_priv->suspend_state) vmw_kms_resume(&dev_priv->drm); @@ -1440,8 +1509,8 @@ static const struct file_operations vmwgfx_driver_fops = { .release = drm_release, .unlocked_ioctl = vmw_unlocked_ioctl, .mmap = vmw_mmap, - .poll = vmw_fops_poll, - .read = vmw_fops_read, + .poll = drm_poll, + .read = drm_read, #if defined(CONFIG_COMPAT) .compat_ioctl = vmw_compat_ioctl, #endif @@ -1490,7 +1559,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct vmw_private *vmw; int ret; - ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, "svgadrmfb"); + ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, "svgadrmfb"); if (ret) return ret; |