Merge "msm: kgsl: Remove icc path from gmu device"

This commit is contained in:
qctecmdr 2020-01-25 03:42:50 -08:00 • committed by Gerrit - the friendly Code Review server
commit 0300f957f5
8 changed files with 234 additions and 43 deletions

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/
#ifndef _A6XX_REG_H
@ -394,6 +394,7 @@
#define A6XX_RBBM_ISDB_CNT 0x533
#define A6XX_RBBM_NC_MODE_CNTL 0X534
#define A6XX_RBBM_SNAPSHOT_STATUS 0x535
#define A6XX_RBBM_SECVID_TRUST_CNTL 0xF400
#define A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO 0xF800

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/
#include "adreno.h"
@ -805,6 +805,22 @@ static void a6xx_snapshot_shader(struct kgsl_device *device,
}
}
static void a650_snapshot_mempool(struct kgsl_device *device,
struct kgsl_snapshot *snapshot)
{
u32 val;
/* set CP_CHICKEN_DBG[StabilizeMVC] to stabilize it while dumping */
kgsl_regread(device, A6XX_CP_CHICKEN_DBG, &val);
kgsl_regwrite(device, A6XX_CP_CHICKEN_DBG, val | BIT(2));
kgsl_snapshot_indexed_registers(device, snapshot,
A6XX_CP_MEM_POOL_DBG_ADDR, A6XX_CP_MEM_POOL_DBG_DATA,
0, 0x2100);
kgsl_regwrite(device, A6XX_CP_CHICKEN_DBG, val);
}
static void a6xx_snapshot_mempool(struct kgsl_device *device,
struct kgsl_snapshot *snapshot)
{
@ -817,7 +833,7 @@ static void a6xx_snapshot_mempool(struct kgsl_device *device,
kgsl_snapshot_indexed_registers(device, snapshot,
A6XX_CP_MEM_POOL_DBG_ADDR, A6XX_CP_MEM_POOL_DBG_DATA,
0, 0x2060);
0, 0x2100);
/*
* Data at offset 0x2000 in the mempool section is the mempool size.
@ -1765,7 +1781,7 @@ void a6xx_snapshot(struct adreno_device *adreno_dev,
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct adreno_ringbuffer *rb;
bool sptprac_on;
unsigned int i, roq_size, ucode_dbg_size;
unsigned int i, roq_size;
/* GMU TCM data dumped through AHB */
gmu_core_dev_snapshot(device, snapshot);
@ -1814,6 +1830,10 @@ void a6xx_snapshot(struct adreno_device *adreno_dev,
if (!gmu_core_dev_gx_is_on(device))
return;
/* Assert the isStatic bit before triggering snapshot */
if (adreno_is_a660(adreno_dev))
kgsl_regwrite(device, A6XX_RBBM_SNAPSHOT_STATUS, 0x1);
/* Dump the registers which get affected by crash dumper trigger */
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
snapshot, a6xx_snapshot_pre_crashdump_regs, NULL);
@ -1846,13 +1866,10 @@ void a6xx_snapshot(struct adreno_device *adreno_dev,
A6XX_CP_DRAW_STATE_ADDR, A6XX_CP_DRAW_STATE_DATA,
0, 0x100);
ucode_dbg_size = adreno_is_a650_family(adreno_dev)
? 0x7000 : 0x6000;
/* SQE_UCODE Cache */
kgsl_snapshot_indexed_registers(device, snapshot,
A6XX_CP_SQE_UCODE_DBG_ADDR, A6XX_CP_SQE_UCODE_DBG_DATA,
0, ucode_dbg_size);
0, 0x8000);
/*
* CP ROQ dump units is 4dwords. The number of units is stored
@ -1869,7 +1886,10 @@ void a6xx_snapshot(struct adreno_device *adreno_dev,
snapshot, a6xx_snapshot_sqe, NULL);
/* Mempool debug data */
a6xx_snapshot_mempool(device, snapshot);
if (adreno_is_a650_family(adreno_dev))
a650_snapshot_mempool(device, snapshot);
else
a6xx_snapshot_mempool(device, snapshot);
if (sptprac_on) {
/* Shader memory */
@ -1882,6 +1902,18 @@ void a6xx_snapshot(struct adreno_device *adreno_dev,
a6xx_snapshot_dbgahb_regs(device, snapshot);
}
if (adreno_is_a660(adreno_dev)) {
u32 val;
kgsl_regread(device, A6XX_RBBM_SNAPSHOT_STATUS, &val);
if (!val)
dev_err(device->dev,
"Interface signals may have changed during snapshot\n");
kgsl_regwrite(device, A6XX_RBBM_SNAPSHOT_STATUS, 0x0);
}
/* Preemption record */
if (adreno_is_preemption_enabled(adreno_dev)) {
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/interconnect.h>
@ -147,15 +147,28 @@ u32 *kgsl_bus_get_table(struct platform_device *pdev,
int kgsl_bus_init(struct kgsl_device *device, struct platform_device *pdev)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int ret, count;
int count;
int ddr = of_fdt_get_ddrtype();
if (ddr >= 0) {
char str[32];
snprintf(str, sizeof(str), "qcom,bus-table-ddr%d", ddr);
pwr->ddr_table = kgsl_bus_get_table(pdev, str, &count);
if (!IS_ERR(pwr->ddr_table))
goto done;
}
/* Look if a generic table is present */
pwr->ddr_table = kgsl_bus_get_table(pdev, "qcom,bus-table-ddr", &count);
if (IS_ERR(pwr->ddr_table)) {
ret = PTR_ERR(pwr->ddr_table);
int ret = PTR_ERR(pwr->ddr_table);
pwr->ddr_table = NULL;
return ret;
}
done:
pwr->ddr_table_count = count;
validate_pwrlevels(device, pwr->ddr_table, pwr->ddr_table_count);

View file

@ -1390,8 +1390,6 @@ static int gmu_probe(struct kgsl_device *device, struct device_node *node)
gmu->num_gpupwrlevels = pwr->num_pwrlevels + 1;
gmu->icc_path = of_icc_get(&gmu->pdev->dev, NULL);
/* Populates RPMh configurations */
ret = gmu_rpmh_init(device, gmu);
if (ret)
@ -1572,7 +1570,7 @@ static int gmu_start(struct kgsl_device *device)
/* Vote for minimal DDR BW for GMU to init */
level = pwr->pwrlevels[pwr->default_pwrlevel].bus_min;
icc_set_bw(gmu->icc_path, 0,
icc_set_bw(pwr->icc_path, 0,
MBps_to_icc(pwr->ddr_table[level]));
ret = gmu_dev_ops->rpmh_gpu_pwrctrl(device, GMU_FW_START,
@ -1650,6 +1648,7 @@ static void gmu_stop(struct kgsl_device *device)
{
struct gmu_device *gmu = KGSL_GMU_DEVICE(device);
struct gmu_dev_ops *gmu_dev_ops = GMU_DEVICE_OPS(device);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int ret = 0;
if (!test_bit(GMU_CLK_ON, &device->gmu_core.flags))
@ -1676,7 +1675,7 @@ static void gmu_stop(struct kgsl_device *device)
gmu_disable_clks(device);
gmu_disable_gdsc(gmu);
icc_set_bw(gmu->icc_path, 0, 0);
icc_set_bw(pwr->icc_path, 0, 0);
return;
error:
@ -1710,8 +1709,6 @@ static void gmu_remove(struct kgsl_device *device)
clear_bit(ADRENO_ACD_CTRL, &adreno_dev->pwrctrl_flag);
icc_put(gmu->icc_path);
if (gmu->fw_image) {
release_firmware(gmu->fw_image);
gmu->fw_image = NULL;

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/
#ifndef __KGSL_GMU_H
#define __KGSL_GMU_H
@ -210,8 +210,6 @@ struct gmu_device {
unsigned long kmem_bitmap;
const struct gmu_vma_entry *vma;
unsigned int log_wptr_retention;
/** @icc_path: Interconnect path for the GMU */
struct icc_path *icc_path;
};
struct gmu_memdesc *gmu_get_memdesc(struct gmu_device *gmu,

View file

@ -567,6 +567,26 @@ iommu_context_by_name(struct kgsl_iommu *iommu, u32 name)
return &iommu->user_context;
}
static int kgsl_iommu_lpac_fault_handler(struct iommu_domain *domain,
struct device *dev, unsigned long addr, int flags, void *token)
{
struct kgsl_pagetable *pt = token;
struct kgsl_mmu *mmu = pt->mmu;
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
struct kgsl_iommu_context *ctx = &iommu->lpac_context;
u32 fsynr0, fsynr1;
fsynr0 = KGSL_IOMMU_GET_CTX_REG(ctx, FSYNR0);
fsynr1 = KGSL_IOMMU_GET_CTX_REG(ctx, FSYNR1);
dev_crit(device->dev,
"LPAC PAGE FAULT iova=0x%16lx, fsynr0=0x%x, fsynr1=0x%x\n",
addr, fsynr0, fsynr1);
return 0;
}
static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
struct device *dev, unsigned long addr, int flags, void *token)
{
@ -1011,11 +1031,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
int ret = 0;
struct kgsl_iommu_pt *iommu_pt = NULL;
unsigned int mmu_idr1;
unsigned int mmu_pagesize;
unsigned int mmu_npages;
unsigned int cb_num;
unsigned int cb0_offset;
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
struct kgsl_iommu_context *ctx = &iommu->user_context;
@ -1029,8 +1045,8 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
DOMAIN_ATTR_PROCID, &pt->name);
if (ret) {
dev_err(device->dev,
"set DOMAIN_ATTR_PROCID failed: %d\n",
ret);
"%s: set DOMAIN_ATTR_PROCID failed: %d\n",
ctx->name, ret);
goto done;
}
}
@ -1048,8 +1064,8 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
DOMAIN_ATTR_CONTEXT_BANK, &cb_num);
if (ret) {
dev_err(device->dev,
"get DOMAIN_ATTR_CONTEXT_BANK failed: %d\n",
ret);
"%s: get DOMAIN_ATTR_CONTEXT_BANK failed: %d\n",
ctx->name, ret);
goto done;
}
@ -1061,28 +1077,21 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
}
ctx->cb_num = cb_num;
mmu_idr1 = readl_relaxed(iommu->regbase + KGSL_IOMMU_IDR1_OFFSET);
mmu_pagesize = FIELD_GET(IDR1_PAGESIZE, mmu_idr1) ? SZ_64K : SZ_4K;
/*
* The number of pages in the global address space or translation
* bank address space is 2^(NUMPAGENDXB + 1).
*/
mmu_npages = 1 << (FIELD_GET(IDR1_NUMPAGENDXB, mmu_idr1) + 1);
cb0_offset = mmu_pagesize * mmu_npages;
ctx->regbase = iommu->regbase + cb0_offset + (cb_num * mmu_pagesize);
ctx->regbase = iommu->regbase + iommu->cb0_offset +
(cb_num * iommu->pagesize);
ret = iommu_domain_get_attr(iommu_pt->domain,
DOMAIN_ATTR_TTBR0, &iommu_pt->ttbr0);
if (ret) {
dev_err(device->dev, "get DOMAIN_ATTR_TTBR0 failed: %d\n", ret);
dev_err(device->dev, "%s: get DOMAIN_ATTR_TTBR0 failed: %d\n",
ctx->name, ret);
goto done;
}
ret = iommu_domain_get_attr(iommu_pt->domain,
DOMAIN_ATTR_CONTEXTIDR, &iommu_pt->contextidr);
if (ret) {
dev_err(device->dev, "get DOMAIN_ATTR_CONTEXTIDR failed: %d\n",
ret);
dev_err(device->dev, "%s: get DOMAIN_ATTR_CONTEXTIDR failed: %d\n",
ctx->name, ret);
goto done;
}
@ -1095,6 +1104,61 @@ done:
return ret;
}
static int _init_global_lpac_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
int ret = 0;
struct kgsl_iommu_pt *iommu_pt = NULL;
unsigned int cb_num;
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
struct kgsl_iommu_context *ctx = &iommu->lpac_context;
iommu_pt = _alloc_pt(&ctx->pdev->dev, mmu, pt);
if (IS_ERR(iommu_pt))
return PTR_ERR(iommu_pt);
_enable_gpuhtw_llc(mmu, iommu_pt);
ret = _attach_pt(iommu_pt, ctx);
if (ret)
goto done;
iommu_set_fault_handler(iommu_pt->domain,
kgsl_iommu_lpac_fault_handler, pt);
/* Try to get the ID of the context bank */
ret = iommu_domain_get_attr(iommu_pt->domain, DOMAIN_ATTR_CONTEXT_BANK,
&cb_num);
/*
* If this returns -ENODEV then we can't figure out what the current
* context bank is. This isn't fatal, but it does limit our ability to
* debug in a pagefault.
*/
if (ret) {
if (ret != -ENODEV) {
dev_err(device->dev,
"%s: Unable to get DOMAIN_ATTR_CONTEXT_BANK: %d\n",
ctx->name, ret);
goto done;
}
}
ctx->cb_num = cb_num;
ctx->regbase = iommu->regbase + iommu->cb0_offset +
(cb_num * iommu->pagesize);
kgsl_iommu_map_globals(mmu, pt);
done:
if (ret)
_free_pt(ctx, pt);
return ret;
}
#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER)
static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
@ -1231,6 +1295,9 @@ static int kgsl_iommu_init_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
case KGSL_MMU_SECURE_PT:
return _init_secure_pt(mmu, pt);
case KGSL_MMU_GLOBAL_LPAC_PT:
return _init_global_lpac_pt(mmu, pt);
default:
return _init_per_process_pt(mmu, pt);
}
@ -1422,6 +1489,43 @@ static int _setup_user_context(struct kgsl_mmu *mmu)
return 0;
}
static int _setup_lpac_context(struct kgsl_mmu *mmu)
{
int ret = 0;
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
struct kgsl_iommu_context *ctx = &iommu->lpac_context;
struct kgsl_iommu_pt *iommu_pt = NULL;
/* If there was no lpac device node, then we don't need to set it up */
if (!ctx->pdev)
return 0;
if (mmu->lpac_pagetable == NULL) {
mmu->lpac_pagetable = kgsl_mmu_getpagetable(mmu,
KGSL_MMU_GLOBAL_LPAC_PT);
/* if we don't have a default pagetable, nothing will work */
if (IS_ERR(mmu->lpac_pagetable)) {
ret = PTR_ERR(mmu->lpac_pagetable);
mmu->lpac_pagetable = NULL;
return ret;
} else if (mmu->lpac_pagetable == NULL) {
return -ENOMEM;
}
}
iommu_pt = mmu->lpac_pagetable->priv;
if (iommu_pt == NULL)
return -ENODEV;
ret = _attach_pt(iommu_pt, ctx);
if (ret)
return ret;
ctx->default_pt = mmu->lpac_pagetable;
return 0;
}
static int _setup_secure_context(struct kgsl_mmu *mmu)
{
int ret;
@ -1450,11 +1554,37 @@ static int _setup_secure_context(struct kgsl_mmu *mmu)
static int kgsl_iommu_set_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt);
static void get_cb0_offset(struct kgsl_mmu *mmu)
{
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
u32 mmu_idr1, mmu_npages;
if (iommu->cb0_offset)
return;
kgsl_mmu_enable_clk(mmu);
mmu_idr1 = readl_relaxed(iommu->regbase + KGSL_IOMMU_IDR1_OFFSET);
kgsl_mmu_disable_clk(mmu);
iommu->pagesize = FIELD_GET(IDR1_PAGESIZE, mmu_idr1) ? SZ_64K : SZ_4K;
/*
* The number of pages in the global address space or translation
* bank address space is 2^(NUMPAGENDXB + 1).
*/
mmu_npages = 1 << (FIELD_GET(IDR1_NUMPAGENDXB, mmu_idr1) + 1);
iommu->cb0_offset = iommu->pagesize * mmu_npages;
}
static int kgsl_iommu_start(struct kgsl_mmu *mmu)
{
int status;
struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);
get_cb0_offset(mmu);
/* Set the following registers only when the MMU type is QSMMU */
if (mmu->subtype != KGSL_IOMMU_SMMU_V500) {
/* Enable hazard check from GPU_SMMU_HUM_CFG */
@ -1471,9 +1601,16 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu)
if (status)
return status;
status = _setup_lpac_context(mmu);
if (status) {
_detach_context(&iommu->user_context);
return status;
}
status = _setup_secure_context(mmu);
if (status) {
_detach_context(&iommu->user_context);
_detach_context(&iommu->lpac_context);
return status;
}
@ -2430,6 +2567,10 @@ static int _kgsl_iommu_probe(struct kgsl_device *device,
platform_device_put(pdev);
}
/* Probe "lpac" context bank if the platform demands it */
if (!ret)
kgsl_iommu_probe_child(device, node,
&iommu->lpac_context, "gfx3d_lpac");
return ret;
}

View file

@ -110,6 +110,8 @@ struct kgsl_iommu {
struct kgsl_iommu_context user_context;
/** @secure_context: Container for the secure iommu context */
struct kgsl_iommu_context secure_context;
/** @lpac_context: Container for the LPAC iommu context */
struct kgsl_iommu_context lpac_context;
void __iomem *regbase;
unsigned long regstart;
unsigned int regsize;
@ -125,6 +127,10 @@ struct kgsl_iommu {
* be mapped in all contexts
*/
bool ppt_active;
/** @cb0_offset: Offset of context bank 0 from iommu register base */
u32 cb0_offset;
/** @pagesize: Size of each context bank register space */
u32 pagesize;
};
/*

View file

@ -16,6 +16,7 @@
*/
#define KGSL_MMU_GLOBAL_PT 0
#define KGSL_MMU_SECURE_PT 1
#define KGSL_MMU_GLOBAL_LPAC_PT 2
#define MMU_DEFAULT_TTBR0(_d) \
(kgsl_mmu_pagetable_get_ttbr0((_d)->mmu.defaultpagetable))
@ -144,6 +145,8 @@ struct kgsl_mmu {
enum kgsl_mmutype type;
u32 subtype;
struct kgsl_pagetable *defaultpagetable;
/** @lpac_pagetable: Default lpac pagetable object for the MMU */
struct kgsl_pagetable *lpac_pagetable;
struct kgsl_pagetable *securepagetable;
const struct kgsl_mmu_ops *mmu_ops;
bool secured;