Skip to content

Commit

Permalink
Merge tag 'drm/tegra/for-5.7-fixes' of git://anongit.freedesktop.org/…
Browse files Browse the repository at this point in the history
…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: Dave 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
  • Loading branch information
Dave Airlie committed May 14, 2020
2 parents 0c77ca2 + 4010e72 commit 6da9b04
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
3 changes: 2 additions & 1 deletion drivers/gpu/drm/tegra/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct host1x *host1x = dev_get_drvdata(dev->dev.parent);
struct iommu_domain *domain;

/*
Expand Down Expand Up @@ -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
* 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 domain != NULL;
Expand Down
59 changes: 55 additions & 4 deletions drivers/gpu/host1x/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev);
int err;

/*
* If the host1x firewall is enabled, there's no need to enable IOMMU
* support. Similarly, if host1x is already attached to an IOMMU (via
* the DMA API), don't try to attach again.
* We may not always want to enable IOMMU support (for example if the
* host1x firewall is already enabled and we don't support addressing
* 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;

host->group = iommu_group_get(host->dev);
Expand Down Expand Up @@ -502,6 +540,19 @@ static void __exit tegra_host1x_exit(void)
}
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("Terje Bergstrom <tbergstrom@nvidia.com>");
MODULE_DESCRIPTION("Host1x driver for Tegra products");
Expand Down
3 changes: 3 additions & 0 deletions include/linux/host1x.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ enum host1x_class {
HOST1X_CLASS_GR3D = 0x60,
};

struct host1x;
struct host1x_client;
struct iommu_group;

u64 host1x_get_dma_mask(struct host1x *host1x);

/**
* struct host1x_client_ops - host1x client operations
* @init: host1x client initialization code
Expand Down

0 comments on commit 6da9b04

Please sign in to comment.