Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 12bf362f authored by Jordan Crouse's avatar Jordan Crouse Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm: Support different SMMU backends for address spaces



SDE and the GPU have different requirements for the SMMU backends - the
SDE generates its own iova addresses and needs special support for DMA
buffers and the GPU does its own IOMMU operations. Add a shim layer to
aspace to break out the address generation and call the appropriate
SMMU functions. There is probably consolidation that can be done,
but for now this is the best way to deal with the two use cases.

CRs-Fixed: 2050484
Change-Id: Ied6d0632c3420f8a5f61dbd80d6bc8330eb83010
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: default avatarAbhijit Kulkarni <kabhijit@codeaurora.org>
parent e22a2fb8
Loading
Loading
Loading
Loading
+25 −2
Original line number Diff line number Diff line
@@ -171,6 +171,9 @@ static void mdp4_preclose(struct msm_kms *kms, struct drm_file *file)

static void mdp4_destroy(struct msm_kms *kms)
{
	struct device *dev = mdp4_kms->dev->dev;
	struct msm_gem_address_space *aspace = mdp4_kms->aspace;

	struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
	struct device *dev = mdp4_kms->dev->dev;
	struct msm_mmu *mmu = mdp4_kms->mmu;
@@ -187,6 +190,12 @@ static void mdp4_destroy(struct msm_kms *kms)
	if (mdp4_kms->rpm_enabled)
		pm_runtime_disable(dev);

	if (aspace) {
		aspace->mmu->funcs->detach(aspace->mmu,
				iommu_ports, ARRAY_SIZE(iommu_ports));
		msm_gem_address_space_destroy(aspace);
	}

	kfree(mdp4_kms);
}

@@ -454,7 +463,6 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
	struct mdp4_platform_config *config = mdp4_get_config(pdev);
	struct mdp4_kms *mdp4_kms;
	struct msm_kms *kms = NULL;
	struct msm_mmu *mmu;
	int irq, ret;
	struct msm_gem_address_space *aspace;

@@ -546,8 +554,15 @@ struct msm_kms *mdp4_kms_init(struct drm_device *dev)
	mdelay(16);

	if (config->iommu) {
		struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, config->iommu);

		if (IS_ERR(mmu)) {
			ret = PTR_ERR(mmu);
			goto fail;
		}

		aspace = msm_gem_address_space_create(&pdev->dev,
				config->iommu, "mdp4");
				mmu, "mdp4", 0x1000, 0xffffffff);
		if (IS_ERR(aspace)) {
			ret = PTR_ERR(aspace);
			goto fail;
@@ -618,5 +633,13 @@ static struct mdp4_platform_config *mdp4_get_config(struct platform_device *dev)
	config.max_clk = 266667000;
	config.iommu = iommu_domain_alloc(&platform_bus_type);

#else
	if (cpu_is_apq8064())
		config.max_clk = 266667000;
	else
		config.max_clk = 200000000;

	config.iommu = msm_get_iommu_domain(DISPLAY_READ_DOMAIN);
#endif
	return &config;
}
+22 −11
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014, 2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
@@ -19,6 +19,7 @@
#include <linux/of_irq.h>

#include "msm_drv.h"
#include "msm_gem.h"
#include "msm_mmu.h"
#include "mdp5_kms.h"

@@ -117,11 +118,12 @@ static int mdp5_set_split_display(struct msm_kms *kms,
static void mdp5_kms_destroy(struct msm_kms *kms)
{
	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
	struct msm_mmu *mmu = mdp5_kms->mmu;
	struct msm_gem_address_space *aspace = mdp5_kms->aspace;

	if (mmu) {
		mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
		mmu->funcs->destroy(mmu);
	if (aspace) {
		aspace->mmu->funcs->detach(aspace->mmu,
				iommu_ports, ARRAY_SIZE(iommu_ports));
		msm_gem_address_space_destroy(aspace);
	}
}

@@ -564,8 +566,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
	struct mdp5_kms *mdp5_kms;
	struct mdp5_cfg *config;
	struct msm_kms *kms;
	struct msm_mmu *mmu;
	int irq, i, ret;
	struct msm_gem_address_space *aspace;

	/* priv->kms would have been populated by the MDP5 driver */
	kms = priv->kms;
@@ -606,7 +608,8 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
	mdelay(16);

	if (config->platform.iommu) {
		mmu = msm_iommu_new(&pdev->dev, config->platform.iommu);
		struct msm_mmu *mmu = msm_iommu_new(&pdev->dev,
				config->platform.iommu);
		if (IS_ERR(mmu)) {
			ret = PTR_ERR(mmu);
			dev_err(&pdev->dev, "failed to init iommu: %d\n", ret);
@@ -614,7 +617,16 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
			goto fail;
		}

		ret = mmu->funcs->attach(mmu, iommu_ports,
		aspace = msm_gem_smmu_address_space_create(&pdev->dev,
				mmu, "mdp5");
		if (IS_ERR(aspace)) {
			ret = PTR_ERR(aspace);
			goto fail;
		}

		mdp5_kms->aspace = aspace;

		ret = mmu->funcs->attach(aspace->mmu, iommu_ports,
				ARRAY_SIZE(iommu_ports));
		if (ret) {
			dev_err(&pdev->dev, "failed to attach iommu: %d\n",
@@ -625,11 +637,10 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
	} else {
		dev_info(&pdev->dev,
			 "no iommu, fallback to phys contig buffers for scanout\n");
		mmu = NULL;
		aspace = NULL;
	}
	mdp5_kms->mmu = mmu;

	mdp5_kms->id = msm_register_mmu(dev, mmu);
	mdp5_kms->id = msm_register_address_space(dev, aspace);
	if (mdp5_kms->id < 0) {
		ret = mdp5_kms->id;
		dev_err(&pdev->dev, "failed to register mdp5 iommu: %d\n", ret);
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ struct mdp5_kms {

	/* mapper-id used to request GEM buffer mapped for scanout: */
	int id;
	struct msm_mmu *mmu;
	struct msm_gem_address_space *aspace;

	struct mdp5_smp *smp;
	struct mdp5_ctl_manager *ctlm;
+11 −11
Original line number Diff line number Diff line
@@ -642,26 +642,26 @@ int msm_atomic_commit(struct drm_device *dev,
		struct drm_atomic_state *state, bool nonblock);

void msm_gem_submit_free(struct msm_gem_submit *submit);
static inline int msm_register_mmu(struct drm_device *dev,
		struct msm_mmu *mmu) {
	return -ENODEV;
}
static inline void msm_unregister_mmu(struct drm_device *dev,
		struct msm_mmu *mmu) {
}
int msm_register_address_space(struct drm_device *dev,
		struct msm_gem_address_space *aspace);

void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
		struct msm_gem_vma *vma, struct sg_table *sgt);
		struct msm_gem_vma *vma, struct sg_table *sgt,
		void *priv);
int msm_gem_map_vma(struct msm_gem_address_space *aspace,
		struct msm_gem_vma *vma, struct sg_table *sgt, int npages);

		struct msm_gem_vma *vma, struct sg_table *sgt,
		void *priv, unsigned int flags);
void msm_gem_address_space_destroy(struct msm_gem_address_space *aspace);

/* For GPU and legacy display */
struct msm_gem_address_space *
msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
		const char *name);

/* For SDE  display */
struct msm_gem_address_space *
msm_gem_smmu_address_space_create(struct device *dev, struct msm_mmu *mmu,
		const char *name);

int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
		struct drm_file *file);

+12 −6
Original line number Diff line number Diff line
@@ -26,6 +26,11 @@
#include "msm_gpu.h"
#include "msm_mmu.h"

static void *get_dmabuf_ptr(struct drm_gem_object *obj)
{
	return (obj && obj->import_attach) ? obj->import_attach->dmabuf : NULL;
}

static dma_addr_t physaddr(struct drm_gem_object *obj)
{
	struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -296,8 +301,8 @@ put_iova(struct drm_gem_object *obj)
	WARN_ON(!mutex_is_locked(&dev->struct_mutex));

	for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
		msm_gem_unmap_vma(priv->aspace[id],
				&msm_obj->domain[id], msm_obj->sgt);
		msm_gem_unmap_vma(priv->aspace[id], &msm_obj->domain[id],
			msm_obj->sgt, get_dmabuf_ptr(obj));
	}
}

@@ -323,10 +328,10 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,

		if (iommu_present(&platform_bus_type)) {
			ret = msm_gem_map_vma(priv->aspace[id],
					&msm_obj->domain[id],
					msm_obj->sgt, obj->size >> PAGE_SHIFT);
				&msm_obj->domain[id], msm_obj->sgt,
				get_dmabuf_ptr(obj),
				msm_obj->flags);
		} else {
			WARN_ONCE(1, "physical address being used\n");
			msm_obj->domain[id].iova = physaddr(obj);
		}
	}
@@ -697,7 +702,8 @@ void msm_gem_free_object(struct drm_gem_object *obj)

	if (obj->import_attach) {
		if (msm_obj->vaddr)
			dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr);
			dma_buf_vunmap(obj->import_attach->dmabuf,
				msm_obj->vaddr);

		/* Don't drop the pages for imported dmabuf, as they are not
		 * ours, just free the array we allocated:
Loading