mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "msm: kgsl: Refactor IOMMU contexts"
This commit is contained in:
commit
4495d8274f
3 changed files with 40 additions and 48 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue