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

Commit 36b7d237 authored by Hareesh Gundu's avatar Hareesh Gundu
Browse files

msm: kgsl: Add new kgsl_mmu_get_bus() API



There are multiple IOMMU drivers in the system,
each one will be sitting on different buses.
Add new kgsl_mmu_get_bus() API, which wraps the
msm_iommu_get_bus() API implementation for
choosing the right bus to declare their domain on.

Change-Id: I7fb8d56d7e68f05b16f9b2c37e1debe90809da3b
Signed-off-by: default avatarHareesh Gundu <hareeshg@codeaurora.org>
parent 0191ccd5
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ static int adreno_iommu_cb_probe(struct platform_device *pdev)
	struct kgsl_iommu_context *ctx = NULL;
	struct device_node *node = pdev->dev.of_node;
	struct kgsl_iommu *iommu = &device_3d0_iommu;
	int ret = 0;

	/* Map context names from dt to id's */
	if (!strcmp("gfx3d_user", node->name)) {
@@ -265,14 +266,28 @@ static int adreno_iommu_cb_probe(struct platform_device *pdev)
				&ctx->gpu_offset))
		ctx->gpu_offset = UINT_MAX;

	ctx->kgsldev = &device_3d0.dev;

	/* arm-smmu driver we'll have the right device pointer here. */
	if (of_find_property(node, "iommus", NULL)) {
		ctx->dev = &pdev->dev;
	} else {
		/*
	 * With the arm-smmu driver we'll have the right device pointer here.
	 * With the old msm_iommu driver we'll need to query it by name later.
		 * old iommu driver requires that we query the context bank
		 * device rather than getting it from dt.
		 */
	if (of_find_property(node, "iommus", NULL))
		ctx->dev = &pdev->dev;
		ctx->dev = kgsl_mmu_get_ctx(ctx->name);
		if (IS_ERR_OR_NULL(ctx->dev)) {
			ret = (ctx->dev == NULL) ? -ENODEV : PTR_ERR(ctx->dev);
			KGSL_CORE_ERR("ctx %s: kgsl_mmu_get_ctx err: %d\n",
					ctx->name, ret);
			return ret;
		}
	}

	return 0;
	kgsl_mmu_set_mmutype(KGSL_MMU_TYPE_IOMMU);

	return ret;
}

static struct of_device_id iommu_match_table[] = {
+1 −3
Original line number Diff line number Diff line
@@ -3908,7 +3908,7 @@ int kgsl_device_platform_probe(struct kgsl_device *device)

	setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device);

	status = kgsl_mmu_init(device);
	status = kgsl_mmu_init(device, ksgl_mmu_type);
	if (status != 0) {
		KGSL_DRV_ERR(device, "kgsl_mmu_init failed %d\n", status);
		goto error_pwrctrl_close;
@@ -4086,8 +4086,6 @@ static int __init kgsl_core_init(void)
	kgsl_driver.mem_workqueue =
		create_singlethread_workqueue("kgsl-mementry");

	kgsl_mmu_set_mmutype(ksgl_mmu_type);

	kgsl_events_init();

	result = kgsl_cmdbatch_init();
+20 −83
Original line number Diff line number Diff line
@@ -17,9 +17,6 @@
#include <linux/genalloc.h>
#include <linux/slab.h>
#include <linux/iommu.h>
#ifdef CONFIG_MSM_IOMMU
#include <linux/qcom_iommu.h>
#endif
#include <linux/msm_kgsl.h>
#include <linux/ratelimit.h>
#include <soc/qcom/scm.h>
@@ -508,21 +505,6 @@ static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
	kfree(iommu_pt);
}

/* currently only the MSM_IOMMU driver supports secure iommu */
#ifdef CONFIG_MSM_IOMMU
static inline struct bus_type *
get_secure_bus(void)
{
	return &msm_iommu_sec_bus_type;
}
#else
static inline struct bus_type *
get_secure_bus(void)
{
	return NULL;
}
#endif

static void setup_64bit_pagetable(struct kgsl_mmu *mmu,
		struct kgsl_pagetable *pagetable,
		struct kgsl_iommu_pt *pt)
@@ -583,18 +565,22 @@ static void setup_32bit_pagetable(struct kgsl_mmu *mmu,


static struct kgsl_iommu_pt *
_alloc_pt(struct bus_type *bus, struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
_alloc_pt(struct device *dev, struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
	struct kgsl_iommu_pt *iommu_pt;
	struct bus_type *bus = kgsl_mmu_get_bus(dev);

	if (bus == NULL)
		return ERR_PTR(-ENODEV);

	iommu_pt = kzalloc(sizeof(struct kgsl_iommu_pt), GFP_KERNEL);
	if (iommu_pt == NULL)
		return NULL;
		return ERR_PTR(-ENOMEM);

	iommu_pt->domain = iommu_domain_alloc(bus);
	if (iommu_pt->domain == NULL) {
		kfree(iommu_pt);
		return NULL;
		return ERR_PTR(-ENODEV);
	}

	pt->pt_ops = &iommu_pt_ops;
@@ -637,9 +623,10 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	struct kgsl_iommu *iommu = mmu->priv;
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];

	iommu_pt = _alloc_pt(&platform_bus_type, mmu, pt);
	if (!iommu_pt)
		return -ENOMEM;
	iommu_pt = _alloc_pt(ctx->dev, mmu, pt);

	if (IS_ERR(iommu_pt))
		return PTR_ERR(iommu_pt);

	iommu_domain_set_attr(iommu_pt->domain,
				DOMAIN_ATTR_COHERENT_HTW_DISABLE, &disable_htw);
@@ -699,7 +686,6 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
	int ret = 0;
	struct kgsl_iommu_pt *iommu_pt = NULL;
	struct bus_type *bus = &platform_bus_type;
	struct kgsl_iommu *iommu = mmu->priv;
	int disable_htw = !MMU_FEATURE(mmu, KGSL_MMU_COHERENT_HTW);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE];
@@ -710,14 +696,14 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
		return -EPERM;

	if (!MMU_FEATURE(mmu, KGSL_MMU_HYP_SECURE_ALLOC)) {
		bus = get_secure_bus();
		if (bus == NULL)
		if (!kgsl_mmu_bus_secured(ctx->dev))
			return -EPERM;
	}

	iommu_pt = _alloc_pt(bus, mmu, pt);
	if (iommu_pt == NULL)
		return -ENOMEM;
	iommu_pt = _alloc_pt(ctx->dev, mmu, pt);

	if (IS_ERR(iommu_pt))
		return PTR_ERR(iommu_pt);

	iommu_domain_set_attr(iommu_pt->domain,
				DOMAIN_ATTR_COHERENT_HTW_DISABLE, &disable_htw);
@@ -763,9 +749,10 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	unsigned int cb_num = ctx->cb_num;
	int disable_htw = !MMU_FEATURE(mmu, KGSL_MMU_COHERENT_HTW);

	iommu_pt = _alloc_pt(&platform_bus_type, mmu, pt);
	if (!iommu_pt)
		return -ENOMEM;
	iommu_pt = _alloc_pt(ctx->dev, mmu, pt);

	if (IS_ERR(iommu_pt))
		return PTR_ERR(iommu_pt);

	ret = iommu_domain_set_attr(iommu_pt->domain,
				DOMAIN_ATTR_DYNAMIC, &dynamic);
@@ -834,52 +821,6 @@ static int kgsl_iommu_init_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	}
}

#ifndef CONFIG_MSM_IOMMU
static struct device *msm_iommu_get_ctx(const char *name)
{
	return ERR_PTR(-ENODEV);
}
#endif

/*
 * _get_iommu_ctxs - Get device pointer to IOMMU contexts
 * @mmu - Pointer to mmu device
 *
 * Return - 0 on success else error code
 */
static int _get_iommu_ctxs(struct kgsl_mmu *mmu)
{
	struct kgsl_iommu *iommu = mmu->priv;
	struct kgsl_iommu_context *ctx;
	int i;
	int ret = 0;

	for (i = 0; i < KGSL_IOMMU_CONTEXT_MAX; i++) {
		ctx = &iommu->ctx[i];
		/* skip contexts not found in dt */
		if (ctx->name == NULL)
			continue;
		ctx->kgsldev = mmu->device;

		if (ctx->dev != NULL)
			continue;
		/*
		 * The old iommu driver requires that we query the context bank
		 * device rather than getting it from dt.
		 */
		ctx->dev = msm_iommu_get_ctx(ctx->name);
		if (IS_ERR_OR_NULL(ctx->dev)) {
			ret = (!ctx->dev) ? -EINVAL : PTR_ERR(ctx->dev);
			memset(ctx, 0, sizeof(*ctx));
			KGSL_CORE_ERR("ctx %s: msm_iommu_get_ctx err: %d\n",
					ctx->name, ret);
			break;
		}
	}

	return ret;
}

/*
 * kgsl_iommu_get_reg_ahbaddr - Returns the ahb address of the register
 * @mmu - Pointer to mmu structure
@@ -934,10 +875,6 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
		return -ENOMEM;
	}

	status = _get_iommu_ctxs(mmu);
	if (status)
		goto done;

	if (addr_entry_cache == NULL) {
		addr_entry_cache = KMEM_CACHE(kgsl_iommu_addr_entry, 0);
		if (addr_entry_cache == NULL) {
+7 −8
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"

static enum kgsl_mmutype kgsl_mmu_type;
static enum kgsl_mmutype kgsl_mmu_type = KGSL_MMU_TYPE_NONE;

static void pagetable_remove_sysfs_objects(struct kgsl_pagetable *pagetable);

@@ -520,12 +520,15 @@ kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, phys_addr_t pt_base,
}
EXPORT_SYMBOL(kgsl_mmu_log_fault_addr);

int kgsl_mmu_init(struct kgsl_device *device)
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype)
{
	int status = 0;
	struct kgsl_mmu *mmu = &device->mmu;
	mmu->device = device;

	if (mmutype && !strcmp(mmutype, "nommu"))
		kgsl_mmu_type = KGSL_MMU_TYPE_NONE;

	/*
	 * Don't use kgsl_allocate_global here because we need to get the MMU
	 * set up before we can add the global entry but the MMU init needs the
@@ -863,13 +866,9 @@ enum kgsl_mmutype kgsl_mmu_get_mmutype(void)
}
EXPORT_SYMBOL(kgsl_mmu_get_mmutype);

void kgsl_mmu_set_mmutype(char *mmutype)
void kgsl_mmu_set_mmutype(enum kgsl_mmutype type)
{
	kgsl_mmu_type = iommu_present(&platform_bus_type) ?
		KGSL_MMU_TYPE_IOMMU : KGSL_MMU_TYPE_NONE;

	if (mmutype && !strncmp(mmutype, "nommu", 5))
		kgsl_mmu_type = KGSL_MMU_TYPE_NONE;
	kgsl_mmu_type = type;
}
EXPORT_SYMBOL(kgsl_mmu_set_mmutype);

+32 −2
Original line number Diff line number Diff line
@@ -139,7 +139,7 @@ struct kgsl_pagetable *kgsl_mmu_getpagetable_ptbase(struct kgsl_mmu *,
						u64 ptbase);

void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable);
int kgsl_mmu_init(struct kgsl_device *device);
int kgsl_mmu_init(struct kgsl_device *device, char *mmutype);
int kgsl_mmu_start(struct kgsl_device *device);
int kgsl_mmu_close(struct kgsl_device *device);
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
@@ -157,7 +157,7 @@ int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, u64 pt_base);
unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu,
			phys_addr_t pt_base, unsigned int addr);
int kgsl_mmu_enabled(void);
void kgsl_mmu_set_mmutype(char *mmutype);
void kgsl_mmu_set_mmutype(enum kgsl_mmutype type);
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr);

@@ -329,6 +329,36 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable)
	return 0;
}

#ifdef CONFIG_MSM_IOMMU
#include <linux/qcom_iommu.h>
static inline bool kgsl_mmu_bus_secured(struct device *dev)
{
	struct bus_type *bus = msm_iommu_get_bus(dev);

	return (bus == &msm_iommu_sec_bus_type) ? true : false;
}
static inline struct bus_type *kgsl_mmu_get_bus(struct device *dev)
{
	return msm_iommu_get_bus(dev);
}
static inline struct device *kgsl_mmu_get_ctx(const char *name)
{
	return msm_iommu_get_ctx(name);
}
#else
static inline bool kgsl_mmu_bus_secured(struct device *dev)
{
	return false;
}

static inline struct bus_type *kgsl_mmu_get_bus(struct device *dev)
{
	return &platform_bus_type;
}
static inline struct device *kgsl_mmu_get_ctx(const char *name)
{
	return ERR_PTR(-ENODEV);
}
#endif

#endif /* __KGSL_MMU_H */