diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 87 |
1 files changed, 85 insertions, 2 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1a90f0a2f7e5..0b5c7818ebfb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <drm/ttm/ttm_bo_driver.h> | 32 | #include <drm/ttm/ttm_bo_driver.h> |
33 | #include <drm/ttm/ttm_object.h> | 33 | #include <drm/ttm/ttm_object.h> |
34 | #include <drm/ttm/ttm_module.h> | 34 | #include <drm/ttm/ttm_module.h> |
35 | #include <linux/dma_remapping.h> | ||
35 | 36 | ||
36 | #define VMWGFX_DRIVER_NAME "vmwgfx" | 37 | #define VMWGFX_DRIVER_NAME "vmwgfx" |
37 | #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices" | 38 | #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices" |
@@ -185,6 +186,9 @@ static struct pci_device_id vmw_pci_id_list[] = { | |||
185 | MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); | 186 | MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); |
186 | 187 | ||
187 | static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); | 188 | static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON); |
189 | static int vmw_force_iommu; | ||
190 | static int vmw_restrict_iommu; | ||
191 | static int vmw_force_coherent; | ||
188 | 192 | ||
189 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); | 193 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); |
190 | static void vmw_master_init(struct vmw_master *); | 194 | static void vmw_master_init(struct vmw_master *); |
@@ -193,6 +197,13 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | |||
193 | 197 | ||
194 | MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); | 198 | MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); |
195 | module_param_named(enable_fbdev, enable_fbdev, int, 0600); | 199 | module_param_named(enable_fbdev, enable_fbdev, int, 0600); |
200 | MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages"); | ||
201 | module_param_named(force_dma_api, vmw_force_iommu, int, 0600); | ||
202 | MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages"); | ||
203 | module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600); | ||
204 | MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages"); | ||
205 | module_param_named(force_coherent, vmw_force_coherent, int, 0600); | ||
206 | |||
196 | 207 | ||
197 | static void vmw_print_capabilities(uint32_t capabilities) | 208 | static void vmw_print_capabilities(uint32_t capabilities) |
198 | { | 209 | { |
@@ -427,12 +438,78 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv) | |||
427 | dev_priv->initial_height = height; | 438 | dev_priv->initial_height = height; |
428 | } | 439 | } |
429 | 440 | ||
441 | /** | ||
442 | * vmw_dma_select_mode - Determine how DMA mappings should be set up for this | ||
443 | * system. | ||
444 | * | ||
445 | * @dev_priv: Pointer to a struct vmw_private | ||
446 | * | ||
447 | * This functions tries to determine the IOMMU setup and what actions | ||
448 | * need to be taken by the driver to make system pages visible to the | ||
449 | * device. | ||
450 | * If this function decides that DMA is not possible, it returns -EINVAL. | ||
451 | * The driver may then try to disable features of the device that require | ||
452 | * DMA. | ||
453 | */ | ||
454 | static int vmw_dma_select_mode(struct vmw_private *dev_priv) | ||
455 | { | ||
456 | const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); | ||
457 | static const char *names[vmw_dma_map_max] = { | ||
458 | [vmw_dma_phys] = "Using physical TTM page addresses.", | ||
459 | [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", | ||
460 | [vmw_dma_map_populate] = "Keeping DMA mappings.", | ||
461 | [vmw_dma_map_bind] = "Giving up DMA mappings early."}; | ||
462 | |||
463 | #ifdef CONFIG_INTEL_IOMMU | ||
464 | if (intel_iommu_enabled) { | ||
465 | dev_priv->map_mode = vmw_dma_map_populate; | ||
466 | goto out_fixup; | ||
467 | } | ||
468 | #endif | ||
469 | |||
470 | if (!(vmw_force_iommu || vmw_force_coherent)) { | ||
471 | dev_priv->map_mode = vmw_dma_phys; | ||
472 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | dev_priv->map_mode = vmw_dma_map_populate; | ||
477 | |||
478 | if (dma_ops->sync_single_for_cpu) | ||
479 | dev_priv->map_mode = vmw_dma_alloc_coherent; | ||
480 | #ifdef CONFIG_SWIOTLB | ||
481 | if (swiotlb_nr_tbl() == 0) | ||
482 | dev_priv->map_mode = vmw_dma_map_populate; | ||
483 | #endif | ||
484 | |||
485 | out_fixup: | ||
486 | if (dev_priv->map_mode == vmw_dma_map_populate && | ||
487 | vmw_restrict_iommu) | ||
488 | dev_priv->map_mode = vmw_dma_map_bind; | ||
489 | |||
490 | if (vmw_force_coherent) | ||
491 | dev_priv->map_mode = vmw_dma_alloc_coherent; | ||
492 | |||
493 | #if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU) | ||
494 | /* | ||
495 | * No coherent page pool | ||
496 | */ | ||
497 | if (dev_priv->map_mode == vmw_dma_alloc_coherent) | ||
498 | return -EINVAL; | ||
499 | #endif | ||
500 | |||
501 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
430 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | 506 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) |
431 | { | 507 | { |
432 | struct vmw_private *dev_priv; | 508 | struct vmw_private *dev_priv; |
433 | int ret; | 509 | int ret; |
434 | uint32_t svga_id; | 510 | uint32_t svga_id; |
435 | enum vmw_res_type i; | 511 | enum vmw_res_type i; |
512 | bool refuse_dma = false; | ||
436 | 513 | ||
437 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); | 514 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |
438 | if (unlikely(dev_priv == NULL)) { | 515 | if (unlikely(dev_priv == NULL)) { |
@@ -481,6 +558,11 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
481 | } | 558 | } |
482 | 559 | ||
483 | dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES); | 560 | dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES); |
561 | ret = vmw_dma_select_mode(dev_priv); | ||
562 | if (unlikely(ret != 0)) { | ||
563 | DRM_INFO("Restricting capabilities due to IOMMU setup.\n"); | ||
564 | refuse_dma = true; | ||
565 | } | ||
484 | 566 | ||
485 | dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE); | 567 | dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE); |
486 | dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE); | 568 | dev_priv->mmio_size = vmw_read(dev_priv, SVGA_REG_MEM_SIZE); |
@@ -558,8 +640,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
558 | } | 640 | } |
559 | 641 | ||
560 | dev_priv->has_gmr = true; | 642 | dev_priv->has_gmr = true; |
561 | if (ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, | 643 | if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) || |
562 | dev_priv->max_gmr_ids) != 0) { | 644 | refuse_dma || ttm_bo_init_mm(&dev_priv->bdev, VMW_PL_GMR, |
645 | dev_priv->max_gmr_ids) != 0) { | ||
563 | DRM_INFO("No GMR memory available. " | 646 | DRM_INFO("No GMR memory available. " |
564 | "Graphics memory resources are very limited.\n"); | 647 | "Graphics memory resources are very limited.\n"); |
565 | dev_priv->has_gmr = false; | 648 | dev_priv->has_gmr = false; |