Merge "msm: kgsl: Refactor IOMMU contexts"

This commit is contained in:
qctecmdr 2020-01-07 16:32:23 -08:00 • committed by Gerrit - the friendly Code Review server
commit 4495d8274f
3 changed files with 40 additions and 48 deletions

View file

@ -1,6 +1,6 @@
// 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;

View file

@ -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;
}

View file

@ -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;