diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_drv.c')
| -rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 81 |
1 files changed, 32 insertions, 49 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 25afb1d594e3..7ef5dcb06104 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | **************************************************************************/ | 26 | **************************************************************************/ |
| 27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
| 29 | #include <linux/dma-mapping.h> | ||
| 29 | 30 | ||
| 30 | #include <drm/drmP.h> | 31 | #include <drm/drmP.h> |
| 31 | #include "vmwgfx_drv.h" | 32 | #include "vmwgfx_drv.h" |
| @@ -34,7 +35,6 @@ | |||
| 34 | #include <drm/ttm/ttm_placement.h> | 35 | #include <drm/ttm/ttm_placement.h> |
| 35 | #include <drm/ttm/ttm_bo_driver.h> | 36 | #include <drm/ttm/ttm_bo_driver.h> |
| 36 | #include <drm/ttm/ttm_module.h> | 37 | #include <drm/ttm/ttm_module.h> |
| 37 | #include <linux/intel-iommu.h> | ||
| 38 | 38 | ||
| 39 | #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices" | 39 | #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices" |
| 40 | #define VMWGFX_CHIP_SVGAII 0 | 40 | #define VMWGFX_CHIP_SVGAII 0 |
| @@ -546,6 +546,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv) | |||
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | /** | 548 | /** |
| 549 | * vmw_assume_iommu - Figure out whether coherent dma-remapping might be | ||
| 550 | * taking place. | ||
| 551 | * @dev: Pointer to the struct drm_device. | ||
| 552 | * | ||
| 553 | * Return: true if iommu present, false otherwise. | ||
| 554 | */ | ||
| 555 | static bool vmw_assume_iommu(struct drm_device *dev) | ||
| 556 | { | ||
| 557 | const struct dma_map_ops *ops = get_dma_ops(dev->dev); | ||
| 558 | |||
| 559 | return !dma_is_direct(ops) && ops && | ||
| 560 | ops->map_page != dma_direct_map_page; | ||
| 561 | } | ||
| 562 | |||
| 563 | /** | ||
| 549 | * vmw_dma_select_mode - Determine how DMA mappings should be set up for this | 564 | * vmw_dma_select_mode - Determine how DMA mappings should be set up for this |
| 550 | * system. | 565 | * system. |
| 551 | * | 566 | * |
| @@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv) | |||
| 565 | [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", | 580 | [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", |
| 566 | [vmw_dma_map_populate] = "Keeping DMA mappings.", | 581 | [vmw_dma_map_populate] = "Keeping DMA mappings.", |
| 567 | [vmw_dma_map_bind] = "Giving up DMA mappings early."}; | 582 | [vmw_dma_map_bind] = "Giving up DMA mappings early."}; |
| 568 | #ifdef CONFIG_X86 | ||
| 569 | const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); | ||
| 570 | 583 | ||
| 571 | #ifdef CONFIG_INTEL_IOMMU | 584 | if (vmw_force_coherent) |
| 572 | if (intel_iommu_enabled) { | 585 | dev_priv->map_mode = vmw_dma_alloc_coherent; |
| 586 | else if (vmw_assume_iommu(dev_priv->dev)) | ||
| 573 | dev_priv->map_mode = vmw_dma_map_populate; | 587 | dev_priv->map_mode = vmw_dma_map_populate; |
| 574 | goto out_fixup; | 588 | else if (!vmw_force_iommu) |
| 575 | } | ||
| 576 | #endif | ||
| 577 | |||
| 578 | if (!(vmw_force_iommu || vmw_force_coherent)) { | ||
| 579 | dev_priv->map_mode = vmw_dma_phys; | 589 | dev_priv->map_mode = vmw_dma_phys; |
| 580 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); | 590 | else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl()) |
| 581 | return 0; | ||
| 582 | } | ||
| 583 | |||
| 584 | dev_priv->map_mode = vmw_dma_map_populate; | ||
| 585 | |||
| 586 | if (dma_ops && dma_ops->sync_single_for_cpu) | ||
| 587 | dev_priv->map_mode = vmw_dma_alloc_coherent; | 591 | dev_priv->map_mode = vmw_dma_alloc_coherent; |
| 588 | #ifdef CONFIG_SWIOTLB | 592 | else |
| 589 | if (swiotlb_nr_tbl() == 0) | ||
| 590 | dev_priv->map_mode = vmw_dma_map_populate; | 593 | dev_priv->map_mode = vmw_dma_map_populate; |
| 591 | #endif | ||
| 592 | 594 | ||
| 593 | #ifdef CONFIG_INTEL_IOMMU | 595 | if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu) |
| 594 | out_fixup: | ||
| 595 | #endif | ||
| 596 | if (dev_priv->map_mode == vmw_dma_map_populate && | ||
| 597 | vmw_restrict_iommu) | ||
| 598 | dev_priv->map_mode = vmw_dma_map_bind; | 596 | dev_priv->map_mode = vmw_dma_map_bind; |
| 599 | 597 | ||
| 600 | if (vmw_force_coherent) | 598 | /* No TTM coherent page pool? FIXME: Ask TTM instead! */ |
| 601 | dev_priv->map_mode = vmw_dma_alloc_coherent; | 599 | if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) && |
| 602 | 600 | (dev_priv->map_mode == vmw_dma_alloc_coherent)) | |
| 603 | #if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU) | ||
| 604 | /* | ||
| 605 | * No coherent page pool | ||
| 606 | */ | ||
| 607 | if (dev_priv->map_mode == vmw_dma_alloc_coherent) | ||
| 608 | return -EINVAL; | 601 | return -EINVAL; |
| 609 | #endif | ||
| 610 | |||
| 611 | #else /* CONFIG_X86 */ | ||
| 612 | dev_priv->map_mode = vmw_dma_map_populate; | ||
| 613 | #endif /* CONFIG_X86 */ | ||
| 614 | 602 | ||
| 615 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); | 603 | DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); |
| 616 | |||
| 617 | return 0; | 604 | return 0; |
| 618 | } | 605 | } |
| 619 | 606 | ||
| @@ -625,24 +612,20 @@ out_fixup: | |||
| 625 | * With 32-bit we can only handle 32 bit PFNs. Optionally set that | 612 | * With 32-bit we can only handle 32 bit PFNs. Optionally set that |
| 626 | * restriction also for 64-bit systems. | 613 | * restriction also for 64-bit systems. |
| 627 | */ | 614 | */ |
| 628 | #ifdef CONFIG_INTEL_IOMMU | ||
| 629 | static int vmw_dma_masks(struct vmw_private *dev_priv) | 615 | static int vmw_dma_masks(struct vmw_private *dev_priv) |
| 630 | { | 616 | { |
| 631 | struct drm_device *dev = dev_priv->dev; | 617 | struct drm_device *dev = dev_priv->dev; |
| 618 | int ret = 0; | ||
| 632 | 619 | ||
| 633 | if (intel_iommu_enabled && | 620 | ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64)); |
| 621 | if (dev_priv->map_mode != vmw_dma_phys && | ||
| 634 | (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) { | 622 | (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) { |
| 635 | DRM_INFO("Restricting DMA addresses to 44 bits.\n"); | 623 | DRM_INFO("Restricting DMA addresses to 44 bits.\n"); |
| 636 | return dma_set_mask(dev->dev, DMA_BIT_MASK(44)); | 624 | return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44)); |
| 637 | } | 625 | } |
| 638 | return 0; | 626 | |
| 639 | } | 627 | return ret; |
| 640 | #else | ||
| 641 | static int vmw_dma_masks(struct vmw_private *dev_priv) | ||
| 642 | { | ||
| 643 | return 0; | ||
| 644 | } | 628 | } |
| 645 | #endif | ||
| 646 | 629 | ||
| 647 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | 630 | static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) |
| 648 | { | 631 | { |
