]> git.baikalelectronics.ru Git - kernel.git/commitdiff
drm/tegra: Relax IOMMU usage criteria on old Tegra
authorThierry Reding <treding@nvidia.com>
Tue, 4 Feb 2020 13:59:24 +0000 (14:59 +0100)
committerThierry Reding <treding@nvidia.com>
Thu, 6 Feb 2020 17:21:14 +0000 (18:21 +0100)
Older Tegra devices only allow addressing 32 bits of memory, so whether
or not the host1x is attached to an IOMMU doesn't matter. host1x IOMMU
attachment is only needed on devices that can address memory beyond the
32-bit boundary and where the host1x doesn't support the wide GATHER
opcode that allows it to access buffers at higher addresses.

Cc: <stable@vger.kernel.org> # v5.5
Signed-off-by: Thierry Reding <treding@nvidia.com>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
drivers/gpu/drm/tegra/drm.c

index aa9e49f04988724986cebfbc77166647888f286f..bd268028fb3d625c9c637b642a540d0e008dcfab 100644 (file)
@@ -1037,23 +1037,9 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
        free_pages((unsigned long)virt, get_order(size));
 }
 
-static int host1x_drm_probe(struct host1x_device *dev)
+static bool host1x_drm_wants_iommu(struct host1x_device *dev)
 {
-       struct drm_driver *driver = &tegra_drm_driver;
        struct iommu_domain *domain;
-       struct tegra_drm *tegra;
-       struct drm_device *drm;
-       int err;
-
-       drm = drm_dev_alloc(driver, &dev->dev);
-       if (IS_ERR(drm))
-               return PTR_ERR(drm);
-
-       tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
-       if (!tegra) {
-               err = -ENOMEM;
-               goto put;
-       }
 
        /*
         * If the Tegra DRM clients are backed by an IOMMU, push buffers are
@@ -1082,9 +1068,38 @@ static int host1x_drm_probe(struct host1x_device *dev)
         * up the device tree appropriately. This is considered an problem
         * of integration, so care must be taken for the DT to be consistent.
         */
-       domain = iommu_get_domain_for_dev(drm->dev->parent);
+       domain = iommu_get_domain_for_dev(dev->dev.parent);
+
+       /*
+        * Tegra20 and Tegra30 don't support addressing memory beyond the
+        * 32-bit boundary, so the regular GATHER opcodes will always be
+        * sufficient and whether or not the host1x is attached to an IOMMU
+        * doesn't matter.
+        */
+       if (!domain && dma_get_mask(dev->dev.parent) <= DMA_BIT_MASK(32))
+               return true;
+
+       return domain != NULL;
+}
+
+static int host1x_drm_probe(struct host1x_device *dev)
+{
+       struct drm_driver *driver = &tegra_drm_driver;
+       struct tegra_drm *tegra;
+       struct drm_device *drm;
+       int err;
+
+       drm = drm_dev_alloc(driver, &dev->dev);
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
+
+       tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
+       if (!tegra) {
+               err = -ENOMEM;
+               goto put;
+       }
 
-       if (domain && iommu_present(&platform_bus_type)) {
+       if (host1x_drm_wants_iommu(dev) && iommu_present(&platform_bus_type)) {
                tegra->domain = iommu_domain_alloc(&platform_bus_type);
                if (!tegra->domain) {
                        err = -ENOMEM;