| From 2d9384ff91770a71bd1ff24c25952ef1187a0e9c Mon Sep 17 00:00:00 2001 |
| From: Thierry Reding <treding@nvidia.com> |
| Date: Tue, 4 Feb 2020 14:59:24 +0100 |
| Subject: drm/tegra: Relax IOMMU usage criteria on old Tegra |
| |
| From: Thierry Reding <treding@nvidia.com> |
| |
| commit 2d9384ff91770a71bd1ff24c25952ef1187a0e9c upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/gpu/drm/tegra/drm.c | 49 ++++++++++++++++++++++++++++---------------- |
| 1 file changed, 32 insertions(+), 17 deletions(-) |
| |
| --- a/drivers/gpu/drm/tegra/drm.c |
| +++ b/drivers/gpu/drm/tegra/drm.c |
| @@ -1037,23 +1037,9 @@ void tegra_drm_free(struct tegra_drm *te |
| 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 host1 |
| * 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; |