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

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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;

	/*
@@ -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;
+55 −4
Original line number Diff line number Diff line
@@ -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);
@@ -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");
+3 −0
Original line number Diff line number Diff line
@@ -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