Commit 6da9b046 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm/tegra/for-5.7-fixes' of git://anongit.freedesktop.org/tegra/linux into drm-fixes

drm/tegra: Fixes for v5.7

This contains a pair of patches which fix SMMU support on Tegra124 and
Tegra210 for host1x and the Tegra DRM driver.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200508101355.3031268-1-thierry.reding@gmail.com
parents 0c77ca2f 4010e729
...@@ -1039,6 +1039,7 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt, ...@@ -1039,6 +1039,7 @@ void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt,
static bool host1x_drm_wants_iommu(struct host1x_device *dev) static bool host1x_drm_wants_iommu(struct host1x_device *dev)
{ {
struct host1x *host1x = dev_get_drvdata(dev->dev.parent);
struct iommu_domain *domain; struct iommu_domain *domain;
/* /*
...@@ -1076,7 +1077,7 @@ static bool host1x_drm_wants_iommu(struct host1x_device *dev) ...@@ -1076,7 +1077,7 @@ static bool host1x_drm_wants_iommu(struct host1x_device *dev)
* sufficient and whether or not the host1x is attached to an IOMMU * sufficient and whether or not the host1x is attached to an IOMMU
* doesn't matter. * doesn't matter.
*/ */
if (!domain && dma_get_mask(dev->dev.parent) <= DMA_BIT_MASK(32)) if (!domain && host1x_get_dma_mask(host1x) <= DMA_BIT_MASK(32))
return true; return true;
return domain != NULL; return domain != NULL;
......
...@@ -192,17 +192,55 @@ static void host1x_setup_sid_table(struct host1x *host) ...@@ -192,17 +192,55 @@ static void host1x_setup_sid_table(struct host1x *host)
} }
} }
static bool host1x_wants_iommu(struct host1x *host1x)
{
/*
* If we support addressing a maximum of 32 bits of physical memory
* and if the host1x firewall is enabled, there's no need to enable
* IOMMU support. This can happen for example on Tegra20, Tegra30
* and Tegra114.
*
* Tegra124 and later can address up to 34 bits of physical memory and
* many platforms come equipped with more than 2 GiB of system memory,
* which requires crossing the 4 GiB boundary. But there's a catch: on
* SoCs before Tegra186 (i.e. Tegra124 and Tegra210), the host1x can
* only address up to 32 bits of memory in GATHER opcodes, which means
* that command buffers need to either be in the first 2 GiB of system
* memory (which could quickly lead to memory exhaustion), or command
* buffers need to be treated differently from other buffers (which is
* not possible with the current ABI).
*
* A third option is to use the IOMMU in these cases to make sure all
* buffers will be mapped into a 32-bit IOVA space that host1x can
* address. This allows all of the system memory to be used and works
* within the limitations of the host1x on these SoCs.
*
* In summary, default to enable IOMMU on Tegra124 and later. For any
* of the earlier SoCs, only use the IOMMU for additional safety when
* the host1x firewall is disabled.
*/
if (host1x->info->dma_mask <= DMA_BIT_MASK(32)) {
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL))
return false;
}
return true;
}
static struct iommu_domain *host1x_iommu_attach(struct host1x *host) static struct iommu_domain *host1x_iommu_attach(struct host1x *host)
{ {
struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev); struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev);
int err; int err;
/* /*
* If the host1x firewall is enabled, there's no need to enable IOMMU * We may not always want to enable IOMMU support (for example if the
* support. Similarly, if host1x is already attached to an IOMMU (via * host1x firewall is already enabled and we don't support addressing
* the DMA API), don't try to attach again. * more than 32 bits of physical memory), so check for that first.
*
* Similarly, if host1x is already attached to an IOMMU (via the DMA
* API), don't try to attach again.
*/ */
if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) || domain) if (!host1x_wants_iommu(host) || domain)
return domain; return domain;
host->group = iommu_group_get(host->dev); host->group = iommu_group_get(host->dev);
...@@ -502,6 +540,19 @@ static void __exit tegra_host1x_exit(void) ...@@ -502,6 +540,19 @@ static void __exit tegra_host1x_exit(void)
} }
module_exit(tegra_host1x_exit); module_exit(tegra_host1x_exit);
/**
* host1x_get_dma_mask() - query the supported DMA mask for host1x
* @host1x: host1x instance
*
* Note that this returns the supported DMA mask for host1x, which can be
* different from the applicable DMA mask under certain circumstances.
*/
u64 host1x_get_dma_mask(struct host1x *host1x)
{
return host1x->info->dma_mask;
}
EXPORT_SYMBOL(host1x_get_dma_mask);
MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
MODULE_AUTHOR("Terje Bergstrom <tbergstrom@nvidia.com>"); MODULE_AUTHOR("Terje Bergstrom <tbergstrom@nvidia.com>");
MODULE_DESCRIPTION("Host1x driver for Tegra products"); MODULE_DESCRIPTION("Host1x driver for Tegra products");
......
...@@ -17,9 +17,12 @@ enum host1x_class { ...@@ -17,9 +17,12 @@ enum host1x_class {
HOST1X_CLASS_GR3D = 0x60, HOST1X_CLASS_GR3D = 0x60,
}; };
struct host1x;
struct host1x_client; struct host1x_client;
struct iommu_group; struct iommu_group;
u64 host1x_get_dma_mask(struct host1x *host1x);
/** /**
* struct host1x_client_ops - host1x client operations * struct host1x_client_ops - host1x client operations
* @init: host1x client initialization code * @init: host1x client initialization code
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment