Commit dd34bb96 authored by Lucas Stach's avatar Lucas Stach
Browse files

drm/etnaviv: move IOMMU domain allocation into etnaviv MMU



The GPU code doesn't need to deal with the IOMMU directly, instead
it can all be hidden behind the etnaviv mmu interface. Move the
last remaining part into etnaviv mmu.

Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
parent e095c8fe
Loading
Loading
Loading
Loading
+3 −30
Original line number Original line Diff line number Diff line
@@ -22,8 +22,6 @@
#include "etnaviv_gpu.h"
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
#include "etnaviv_mmu.h"
#include "etnaviv_iommu.h"
#include "etnaviv_iommu_v2.h"
#include "common.xml.h"
#include "common.xml.h"
#include "state.xml.h"
#include "state.xml.h"
#include "state_hi.xml.h"
#include "state_hi.xml.h"
@@ -585,9 +583,6 @@ static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
{
{
	int ret, i;
	int ret, i;
	struct iommu_domain *iommu;
	enum etnaviv_iommu_version version;
	bool mmuv2;


	ret = pm_runtime_get_sync(gpu->dev);
	ret = pm_runtime_get_sync(gpu->dev);
	if (ret < 0) {
	if (ret < 0) {
@@ -635,32 +630,10 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
		goto fail;
		goto fail;
	}
	}


	/* Setup IOMMU.. eventually we will (I think) do this once per context
	gpu->mmu = etnaviv_iommu_new(gpu);
	 * and have separate page tables per context.  For now, to keep things
	if (IS_ERR(gpu->mmu)) {
	 * simple and to get something working, just use a single address space:
	 */
	mmuv2 = gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION;
	dev_dbg(gpu->dev, "mmuv2: %d\n", mmuv2);

	if (!mmuv2) {
		iommu = etnaviv_iommu_domain_alloc(gpu);
		version = ETNAVIV_IOMMU_V1;
	} else {
		iommu = etnaviv_iommu_v2_domain_alloc(gpu);
		version = ETNAVIV_IOMMU_V2;
	}

	if (!iommu) {
		dev_err(gpu->dev, "Failed to allocate GPU IOMMU domain\n");
		ret = -ENOMEM;
		goto fail;
	}

	gpu->mmu = etnaviv_iommu_new(gpu, iommu, version);
	if (!gpu->mmu) {
		dev_err(gpu->dev, "Failed to instantiate GPU IOMMU\n");
		dev_err(gpu->dev, "Failed to instantiate GPU IOMMU\n");
		iommu_domain_free(iommu);
		ret = PTR_ERR(gpu->mmu);
		ret = -ENOMEM;
		goto fail;
		goto fail;
	}
	}


+1 −1
Original line number Original line Diff line number Diff line
@@ -219,7 +219,7 @@ void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu)
	gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, pgtable);
	gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, pgtable);
}
}


struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu)
struct iommu_domain *etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu)
{
{
	struct etnaviv_iommu_domain *etnaviv_domain;
	struct etnaviv_iommu_domain *etnaviv_domain;
	int ret;
	int ret;
+2 −2
Original line number Original line Diff line number Diff line
@@ -20,8 +20,8 @@
#include <linux/iommu.h>
#include <linux/iommu.h>
struct etnaviv_gpu;
struct etnaviv_gpu;


struct iommu_domain *etnaviv_iommu_domain_alloc(struct etnaviv_gpu *gpu);
struct iommu_domain *etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu);
void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu);
void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu);
struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu);
struct iommu_domain *etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu);


#endif /* __ETNAVIV_IOMMU_H__ */
#endif /* __ETNAVIV_IOMMU_H__ */
+1 −1
Original line number Original line Diff line number Diff line
@@ -26,7 +26,7 @@
#include "state_hi.xml.h"
#include "state_hi.xml.h"




struct iommu_domain *etnaviv_iommu_v2_domain_alloc(struct etnaviv_gpu *gpu)
struct iommu_domain *etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu)
{
{
	/* TODO */
	/* TODO */
	return NULL;
	return NULL;
+21 −7
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 */


#include "common.xml.h"
#include "etnaviv_drv.h"
#include "etnaviv_drv.h"
#include "etnaviv_gem.h"
#include "etnaviv_gem.h"
#include "etnaviv_gpu.h"
#include "etnaviv_gpu.h"
@@ -258,26 +259,39 @@ void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu)
	kfree(mmu);
	kfree(mmu);
}
}


struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu,
struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu)
	struct iommu_domain *domain, enum etnaviv_iommu_version version)
{
{
	enum etnaviv_iommu_version version;
	struct etnaviv_iommu *mmu;
	struct etnaviv_iommu *mmu;


	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
	mmu = kzalloc(sizeof(*mmu), GFP_KERNEL);
	if (!mmu)
	if (!mmu)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);


	mmu->domain = domain;
	if (!(gpu->identity.minor_features1 & chipMinorFeatures1_MMU_VERSION)) {
		mmu->domain = etnaviv_iommuv1_domain_alloc(gpu);
		version = ETNAVIV_IOMMU_V1;
	} else {
		mmu->domain = etnaviv_iommuv2_domain_alloc(gpu);
		version = ETNAVIV_IOMMU_V2;
	}

	if (!mmu->domain) {
		dev_err(gpu->dev, "Failed to allocate GPU IOMMU domain\n");
		kfree(mmu);
		return ERR_PTR(-ENOMEM);
	}

	mmu->gpu = gpu;
	mmu->gpu = gpu;
	mmu->version = version;
	mmu->version = version;
	mutex_init(&mmu->lock);
	mutex_init(&mmu->lock);
	INIT_LIST_HEAD(&mmu->mappings);
	INIT_LIST_HEAD(&mmu->mappings);


	drm_mm_init(&mmu->mm, domain->geometry.aperture_start,
	drm_mm_init(&mmu->mm, mmu->domain->geometry.aperture_start,
		    domain->geometry.aperture_end -
		    mmu->domain->geometry.aperture_end -
		      domain->geometry.aperture_start + 1);
		    mmu->domain->geometry.aperture_start + 1);


	iommu_set_fault_handler(domain, etnaviv_fault_handler, gpu->dev);
	iommu_set_fault_handler(mmu->domain, etnaviv_fault_handler, gpu->dev);


	return mmu;
	return mmu;
}
}
Loading