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

Commit 4495d827 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Refactor IOMMU contexts"

parents db969894 b52fb8dc
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/slab.h>
@@ -235,7 +235,7 @@ unsigned int adreno_iommu_set_pt_generate_cmds(
	struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;
	u64 ttbr0;
	u32 contextidr;

+34 −37
Original line number Diff line number Diff line
@@ -558,13 +558,21 @@ static struct kgsl_process_private *kgsl_iommu_get_process(u64 ptbase)
	return NULL;
}

static struct kgsl_iommu_context *
iommu_context_by_name(struct kgsl_iommu *iommu, u32 name)
{
	if (name == KGSL_MMU_SECURE_PT)
		return &iommu->secure_context;

	return &iommu->user_context;
}

static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	struct device *dev, unsigned long addr, int flags, void *token)
{
	int ret = 0;
	struct kgsl_pagetable *pt = token;
	struct kgsl_mmu *mmu = pt->mmu;
	struct kgsl_iommu *iommu;
	struct kgsl_iommu_context *ctx;
	u64 ptbase;
	u32 contextidr;
@@ -587,8 +595,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	if (mmu == NULL)
		return ret;

	iommu = _IOMMU_PRIV(mmu);
	ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	device = KGSL_MMU_DEVICE(mmu);
	adreno_dev = ADRENO_DEVICE(device);
	gpudev = ADRENO_GPU_DEVICE(adreno_dev);
@@ -603,6 +609,8 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	else if (flags & IOMMU_FAULT_TRANSACTION_STALLED)
		fault_type = "transaction stalled";

	ctx = iommu_context_by_name(_IOMMU_PRIV(mmu), pt->name);

	ptbase = KGSL_IOMMU_GET_CTX_REG_Q(ctx, TTBR0);
	private = kgsl_iommu_get_process(ptbase);

@@ -611,9 +619,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
		comm = private->comm;
	}

	if (pt->name == KGSL_MMU_SECURE_PT)
		ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE];

	if (test_bit(KGSL_FT_PAGEFAULT_GPUHALT_ENABLE,
		&adreno_dev->ft_pf_policy) &&
		(flags & IOMMU_FAULT_TRANSACTION_STALLED)) {
@@ -819,7 +824,6 @@ static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
	struct kgsl_iommu_pt *iommu_pt = pt->priv;
	struct kgsl_mmu *mmu = pt->mmu;
	struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
	struct kgsl_iommu *iommu;
	struct kgsl_iommu_context  *ctx;

	/*
@@ -828,19 +832,17 @@ static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
	 */
	WARN_ON(!list_empty(&pt->list));

	iommu = _IOMMU_PRIV(mmu);
	ctx = iommu_context_by_name(_IOMMU_PRIV(mmu), pt->name);

	if (pt->name == KGSL_MMU_SECURE_PT) {
		struct kgsl_global_memdesc *md;

		ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE];
		/* Unmap any pending secure global buffers */
		list_for_each_entry(md, &device->globals, node) {
			if (md->memdesc.flags & KGSL_MEMFLAGS_SECURE)
				kgsl_mmu_unmap(pt, &md->memdesc);
		}
	} else {
		ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
		kgsl_iommu_unmap_globals(mmu, pt);
	}

@@ -1015,7 +1017,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	unsigned int cb_num;
	unsigned int cb0_offset;
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;

	iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt);

@@ -1100,7 +1102,7 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	int ret = 0;
	struct kgsl_iommu_pt *iommu_pt = NULL;
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE];
	struct kgsl_iommu_context *ctx = &iommu->secure_context;
	int secure_vmid = VMID_CP_PIXEL;
	struct kgsl_global_memdesc *md;

@@ -1151,7 +1153,7 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
	int ret = 0;
	struct kgsl_iommu_pt *iommu_pt = NULL;
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;
	int dynamic = 1;
	unsigned int cb_num = ctx->cb_num;

@@ -1272,10 +1274,9 @@ static void _detach_context(struct kgsl_iommu_context *ctx)
static void kgsl_iommu_close(struct kgsl_mmu *mmu)
{
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	int i;

	for (i = 0; i < KGSL_IOMMU_CONTEXT_MAX; i++)
		_detach_context(&iommu->ctx[i]);
	_detach_context(&iommu->user_context);
	_detach_context(&iommu->secure_context);

	kgsl_mmu_putpagetable(mmu->defaultpagetable);
	mmu->defaultpagetable = NULL;
@@ -1307,12 +1308,11 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
{
	struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	int status = 0;

	mmu->features |= KGSL_MMU_PAGED;

	if (ctx->name == NULL) {
	if (!iommu->user_context.name) {
		dev_err(device->dev,
			"dt: gfx3d0_user context bank not found\n");
		return -EINVAL;
@@ -1364,7 +1364,7 @@ static int _setup_user_context(struct kgsl_mmu *mmu)
{
	int ret = 0;
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;
	struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct kgsl_iommu_pt *iommu_pt = NULL;
@@ -1426,7 +1426,7 @@ static int _setup_secure_context(struct kgsl_mmu *mmu)
{
	int ret;
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE];
	struct kgsl_iommu_context *ctx = &iommu->secure_context;

	struct kgsl_iommu_pt *iommu_pt;

@@ -1473,7 +1473,7 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)

	status = _setup_secure_context(mmu);
	if (status) {
		_detach_context(&iommu->ctx[KGSL_IOMMU_CONTEXT_USER]);
		_detach_context(&iommu->user_context);
		return status;
	}

@@ -1787,7 +1787,7 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu)
{
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context  *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context  *ctx = &iommu->user_context;
	unsigned int sctlr_val;

	if (ctx->default_pt != NULL && ctx->stalled_on_fault) {
@@ -1814,7 +1814,7 @@ static void kgsl_iommu_clear_fsr(struct kgsl_mmu *mmu)
static void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu)
{
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;

	if (ctx->default_pt != NULL && ctx->stalled_on_fault) {
		/*
@@ -1847,7 +1847,7 @@ kgsl_iommu_get_current_ttbr0(struct kgsl_mmu *mmu)
{
	u64 val;
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;

	/*
	 * We cannot enable or disable the clocks in interrupt context, this
@@ -1878,7 +1878,7 @@ kgsl_iommu_get_current_ttbr0(struct kgsl_mmu *mmu)
static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;
	uint64_t ttbr0, temp;
	unsigned int contextidr;
	unsigned long wait_for_flush;
@@ -1936,7 +1936,7 @@ static int kgsl_iommu_set_pf_policy(struct kgsl_mmu *mmu,
				unsigned long pf_policy)
{
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
	struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
	struct kgsl_iommu_context *ctx = &iommu->user_context;
	struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

@@ -2321,9 +2321,9 @@ static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable,
}

static int kgsl_iommu_probe_child(struct kgsl_device *device,
		struct device_node *parent, int id, const char *name)
		struct device_node *parent, struct kgsl_iommu_context *context,
		const char *name)
{
	struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
	struct device_node *node = of_find_node_by_name(parent, name);
	struct platform_device *pdev;
	struct device_node *phandle;
@@ -2333,13 +2333,10 @@ static int kgsl_iommu_probe_child(struct kgsl_device *device,

	pdev = of_find_device_by_node(node);

	iommu->ctx[id].id = id;
	iommu->ctx[id].cb_num = -1;
	iommu->ctx[id].name = name;

	iommu->ctx[id].kgsldev = device;

	iommu->ctx[id].pdev = pdev;
	context->cb_num = -1;
	context->name = name;
	context->kgsldev = device;
	context->pdev = pdev;

	phandle = of_parse_phandle(node, "iommus", 0);

@@ -2413,7 +2410,7 @@ static int _kgsl_iommu_probe(struct kgsl_device *device,
	of_platform_populate(node, NULL, NULL, &pdev->dev);

	/* The "user" device always needs to be present */
	ret = kgsl_iommu_probe_child(device, node, KGSL_IOMMU_CONTEXT_USER,
	ret = kgsl_iommu_probe_child(device, node, &iommu->user_context,
		"gfx3d_user");

	if (!ret && device->mmu.secured) {
@@ -2424,7 +2421,7 @@ static int _kgsl_iommu_probe(struct kgsl_device *device,

		/* Secure context bank devices are optional */
		if (kgsl_iommu_probe_child(device, node,
			KGSL_IOMMU_CONTEXT_SECURE, name))
			&iommu->secure_context, name))
			device->mmu.secured = false;
	}

+4 −9
Original line number Diff line number Diff line
@@ -68,12 +68,6 @@ enum kgsl_iommu_reg_map {
/* Max number of iommu clks per IOMMU unit */
#define KGSL_IOMMU_MAX_CLKS 5

enum kgsl_iommu_context_id {
	KGSL_IOMMU_CONTEXT_USER = 0,
	KGSL_IOMMU_CONTEXT_SECURE = 1,
	KGSL_IOMMU_CONTEXT_MAX,
};

/* offset at which a nop command is placed in setstate */
#define KGSL_IOMMU_SETSTATE_NOP_OFFSET	1024

@@ -94,7 +88,6 @@ enum kgsl_iommu_context_id {
struct kgsl_iommu_context {
	struct platform_device *pdev;
	const char *name;
	enum kgsl_iommu_context_id id;
	unsigned int cb_num;
	struct kgsl_device *kgsldev;
	bool stalled_on_fault;
@@ -104,7 +97,6 @@ struct kgsl_iommu_context {

/*
 * struct kgsl_iommu - Structure holding iommu data for kgsl driver
 * @ctx: Array of kgsl_iommu_context structs
 * @regbase: Virtual address of the IOMMU register base
 * @regstart: Physical address of the iommu registers
 * @regsize: Length of the iommu register region.
@@ -114,7 +106,10 @@ struct kgsl_iommu_context {
 * @smmu_info: smmu info used in a5xx preemption
 */
struct kgsl_iommu {
	struct kgsl_iommu_context ctx[KGSL_IOMMU_CONTEXT_MAX];
	/** @user_context: Container for the user iommu context */
	struct kgsl_iommu_context user_context;
	/** @secure_context: Container for the secure iommu context */
	struct kgsl_iommu_context secure_context;
	void __iomem *regbase;
	unsigned long regstart;
	unsigned int regsize;