msm: kgsl: Mark the scratch buffer as privileged
Mark the scratch buffer as privileged so that it can only be accessed by GPU through the ringbuffer. To accomplish this, we need to: 1. Move the preemption data out of the scratch buffer. 2. Disable the shadow rptr feature. 3. Trigger RPTR update from GPU using a WHERE_AM_I packet. 4. Add support for the new ucode. Change-Id: I9b388f55f53b69028b9bbb2306cb43fd1297c52f Signed-off-by: Akhil P Oommen <akhilpo@codeaurora.org> Signed-off-by: Archana Sriram <apsrir@codeaurora.org> Signed-off-by: Harshitha Sai Neelati <hsaine@codeaurora.org>
This commit is contained in:
parent
dce3eda449
commit
76518d99f8
13 changed files with 110 additions and 56 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2002,2007-2018,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -3818,6 +3818,19 @@ static void adreno_gpu_model(struct kgsl_device *device, char *str,
|
||||||
ADRENO_CHIPID_PATCH(adreno_dev->chipid) + 1);
|
ADRENO_CHIPID_PATCH(adreno_dev->chipid) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 adreno_get_ucode_version(const u32 *data)
|
||||||
|
{
|
||||||
|
u32 version;
|
||||||
|
|
||||||
|
version = data[1];
|
||||||
|
|
||||||
|
if ((version & 0xf) != 0xa)
|
||||||
|
return version;
|
||||||
|
|
||||||
|
version &= ~0xfff;
|
||||||
|
return version | ((data[3] & 0xfff000) >> 12);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct kgsl_functable adreno_functable = {
|
static const struct kgsl_functable adreno_functable = {
|
||||||
/* Mandatory functions */
|
/* Mandatory functions */
|
||||||
.regread = adreno_regread,
|
.regread = adreno_regread,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2008-2018,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -277,8 +277,8 @@ enum adreno_preempt_states {
|
||||||
/**
|
/**
|
||||||
* struct adreno_preemption
|
* struct adreno_preemption
|
||||||
* @state: The current state of preemption
|
* @state: The current state of preemption
|
||||||
* @counters: Memory descriptor for the memory where the GPU writes the
|
* @scratch: Memory descriptor for the memory where the GPU writes the
|
||||||
* preemption counters on switch
|
* current ctxt record address and preemption counters on switch
|
||||||
* @timer: A timer to make sure preemption doesn't stall
|
* @timer: A timer to make sure preemption doesn't stall
|
||||||
* @work: A work struct for the preemption worker (for 5XX)
|
* @work: A work struct for the preemption worker (for 5XX)
|
||||||
* @token_submit: Indicates if a preempt token has been submitted in
|
* @token_submit: Indicates if a preempt token has been submitted in
|
||||||
|
|
@ -290,7 +290,7 @@ enum adreno_preempt_states {
|
||||||
*/
|
*/
|
||||||
struct adreno_preemption {
|
struct adreno_preemption {
|
||||||
atomic_t state;
|
atomic_t state;
|
||||||
struct kgsl_memdesc counters;
|
struct kgsl_memdesc scratch;
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
bool token_submit;
|
bool token_submit;
|
||||||
|
|
@ -1178,6 +1178,7 @@ void adreno_cx_misc_regrmw(struct adreno_device *adreno_dev,
|
||||||
unsigned int offsetwords,
|
unsigned int offsetwords,
|
||||||
unsigned int mask, unsigned int bits);
|
unsigned int mask, unsigned int bits);
|
||||||
|
|
||||||
|
u32 adreno_get_ucode_version(const u32 *data);
|
||||||
|
|
||||||
#define ADRENO_TARGET(_name, _id) \
|
#define ADRENO_TARGET(_name, _id) \
|
||||||
static inline int adreno_is_##_name(struct adreno_device *adreno_dev) \
|
static inline int adreno_is_##_name(struct adreno_device *adreno_dev) \
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2014-2018,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -2168,12 +2168,15 @@ static int a5xx_post_start(struct adreno_device *adreno_dev)
|
||||||
*cmds++ = 0xF;
|
*cmds++ = 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adreno_is_preemption_enabled(adreno_dev))
|
if (adreno_is_preemption_enabled(adreno_dev)) {
|
||||||
cmds += _preemption_init(adreno_dev, rb, cmds, NULL);
|
cmds += _preemption_init(adreno_dev, rb, cmds, NULL);
|
||||||
|
rb->_wptr = rb->_wptr - (42 - (cmds - start));
|
||||||
|
ret = adreno_ringbuffer_submit_spin_nosync(rb, NULL, 2000);
|
||||||
|
} else {
|
||||||
|
rb->_wptr = rb->_wptr - (42 - (cmds - start));
|
||||||
|
ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
rb->_wptr = rb->_wptr - (42 - (cmds - start));
|
|
||||||
|
|
||||||
ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
adreno_spin_idle_debug(adreno_dev,
|
adreno_spin_idle_debug(adreno_dev,
|
||||||
"hw initialization failed to idle\n");
|
"hw initialization failed to idle\n");
|
||||||
|
|
@ -2511,7 +2514,7 @@ static int _load_firmware(struct kgsl_device *device, const char *fwfile,
|
||||||
|
|
||||||
memcpy(firmware->memdesc.hostptr, &fw->data[4], fw->size - 4);
|
memcpy(firmware->memdesc.hostptr, &fw->data[4], fw->size - 4);
|
||||||
firmware->size = (fw->size - 4) / sizeof(uint32_t);
|
firmware->size = (fw->size - 4) / sizeof(uint32_t);
|
||||||
firmware->version = *(unsigned int *)&fw->data[4];
|
firmware->version = adreno_get_ucode_version((u32 *)fw->data);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2015-2017,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -112,7 +112,7 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev);
|
||||||
|
|
||||||
void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
|
void a5xx_hwcg_set(struct adreno_device *adreno_dev, bool on);
|
||||||
|
|
||||||
#define A5XX_CP_RB_CNTL_DEFAULT (((ilog2(4) << 8) & 0x1F00) | \
|
#define A5XX_CP_RB_CNTL_DEFAULT ((1 << 27) | ((ilog2(4) << 8) & 0x1F00) | \
|
||||||
(ilog2(KGSL_RB_DWORDS >> 1) & 0x3F))
|
(ilog2(KGSL_RB_DWORDS >> 1) & 0x3F))
|
||||||
/* GPMU interrupt multiplexor */
|
/* GPMU interrupt multiplexor */
|
||||||
#define FW_INTR_INFO (0)
|
#define FW_INTR_INFO (0)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2014-2017,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -575,7 +575,7 @@ static void a5xx_preemption_close(struct kgsl_device *device)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
del_timer(&preempt->timer);
|
del_timer(&preempt->timer);
|
||||||
kgsl_free_global(device, &preempt->counters);
|
kgsl_free_global(device, &preempt->scratch);
|
||||||
a5xx_preemption_iommu_close(adreno_dev);
|
a5xx_preemption_iommu_close(adreno_dev);
|
||||||
|
|
||||||
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
||||||
|
|
@ -602,14 +602,14 @@ int a5xx_preemption_init(struct adreno_device *adreno_dev)
|
||||||
(unsigned long) adreno_dev);
|
(unsigned long) adreno_dev);
|
||||||
|
|
||||||
/* Allocate mem for storing preemption counters */
|
/* Allocate mem for storing preemption counters */
|
||||||
ret = kgsl_allocate_global(device, &preempt->counters,
|
ret = kgsl_allocate_global(device, &preempt->scratch,
|
||||||
adreno_dev->num_ringbuffers *
|
adreno_dev->num_ringbuffers *
|
||||||
A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0,
|
A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0,
|
||||||
"preemption_counters");
|
"preemption_counters");
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
addr = preempt->counters.gpuaddr;
|
addr = preempt->scratch.gpuaddr;
|
||||||
|
|
||||||
/* Allocate mem for storing preemption switch record */
|
/* Allocate mem for storing preemption switch record */
|
||||||
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
||||||
|
|
|
||||||
|
|
@ -1066,7 +1066,7 @@ static int a6xx_post_start(struct adreno_device *adreno_dev)
|
||||||
|
|
||||||
rb->_wptr = rb->_wptr - (42 - (cmds - start));
|
rb->_wptr = rb->_wptr - (42 - (cmds - start));
|
||||||
|
|
||||||
ret = adreno_ringbuffer_submit_spin(rb, NULL, 2000);
|
ret = adreno_ringbuffer_submit_spin_nosync(rb, NULL, 2000);
|
||||||
if (ret)
|
if (ret)
|
||||||
adreno_spin_idle_debug(adreno_dev,
|
adreno_spin_idle_debug(adreno_dev,
|
||||||
"hw preemption initialization failed to idle\n");
|
"hw preemption initialization failed to idle\n");
|
||||||
|
|
@ -1173,7 +1173,7 @@ static int _load_firmware(struct kgsl_device *device, const char *fwfile,
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
memcpy(firmware->memdesc.hostptr, &fw->data[4], fw->size - 4);
|
memcpy(firmware->memdesc.hostptr, &fw->data[4], fw->size - 4);
|
||||||
firmware->size = (fw->size - 4) / sizeof(uint32_t);
|
firmware->size = (fw->size - 4) / sizeof(uint32_t);
|
||||||
firmware->version = *(unsigned int *)&fw->data[4];
|
firmware->version = adreno_get_ucode_version((u32 *)fw->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -103,7 +103,7 @@ struct cpu_gpu_lock {
|
||||||
/* Size of the performance counter save/restore block (in bytes) */
|
/* Size of the performance counter save/restore block (in bytes) */
|
||||||
#define A6XX_CP_PERFCOUNTER_SAVE_RESTORE_SIZE (4 * 1024)
|
#define A6XX_CP_PERFCOUNTER_SAVE_RESTORE_SIZE (4 * 1024)
|
||||||
|
|
||||||
#define A6XX_CP_RB_CNTL_DEFAULT (((ilog2(4) << 8) & 0x1F00) | \
|
#define A6XX_CP_RB_CNTL_DEFAULT ((1 << 27) | ((ilog2(4) << 8) & 0x1F00) | \
|
||||||
(ilog2(KGSL_RB_DWORDS >> 1) & 0x3F))
|
(ilog2(KGSL_RB_DWORDS >> 1) & 0x3F))
|
||||||
|
|
||||||
/* Preemption functions */
|
/* Preemption functions */
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2017-2018,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -341,8 +341,8 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
|
||||||
kgsl_sharedmem_writel(device, &iommu->smmu_info,
|
kgsl_sharedmem_writel(device, &iommu->smmu_info,
|
||||||
PREEMPT_SMMU_RECORD(context_idr), contextidr);
|
PREEMPT_SMMU_RECORD(context_idr), contextidr);
|
||||||
|
|
||||||
kgsl_sharedmem_readq(&device->scratch, &gpuaddr,
|
kgsl_sharedmem_readq(&preempt->scratch, &gpuaddr,
|
||||||
SCRATCH_PREEMPTION_CTXT_RESTORE_ADDR_OFFSET(next->id));
|
next->id * sizeof(u64));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set a keepalive bit before the first preemption register write.
|
* Set a keepalive bit before the first preemption register write.
|
||||||
|
|
@ -542,12 +542,10 @@ unsigned int a6xx_preemption_pre_ibsubmit(
|
||||||
rb->perfcounter_save_restore_desc.gpuaddr);
|
rb->perfcounter_save_restore_desc.gpuaddr);
|
||||||
|
|
||||||
if (context) {
|
if (context) {
|
||||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
|
||||||
struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
|
struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
|
||||||
struct adreno_ringbuffer *rb = drawctxt->rb;
|
struct adreno_ringbuffer *rb = drawctxt->rb;
|
||||||
uint64_t dest =
|
uint64_t dest = adreno_dev->preempt.scratch.gpuaddr +
|
||||||
SCRATCH_PREEMPTION_CTXT_RESTORE_GPU_ADDR(device,
|
sizeof(u64) * rb->id;
|
||||||
rb->id);
|
|
||||||
|
|
||||||
*cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2);
|
*cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2);
|
||||||
cmds += cp_gpuaddr(adreno_dev, cmds, dest);
|
cmds += cp_gpuaddr(adreno_dev, cmds, dest);
|
||||||
|
|
@ -565,9 +563,8 @@ unsigned int a6xx_preemption_post_ibsubmit(struct adreno_device *adreno_dev,
|
||||||
struct adreno_ringbuffer *rb = adreno_dev->cur_rb;
|
struct adreno_ringbuffer *rb = adreno_dev->cur_rb;
|
||||||
|
|
||||||
if (rb) {
|
if (rb) {
|
||||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
uint64_t dest = adreno_dev->preempt.scratch.gpuaddr +
|
||||||
uint64_t dest = SCRATCH_PREEMPTION_CTXT_RESTORE_GPU_ADDR(device,
|
sizeof(u64) * rb->id;
|
||||||
rb->id);
|
|
||||||
|
|
||||||
*cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2);
|
*cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 2, 2);
|
||||||
cmds += cp_gpuaddr(adreno_dev, cmds, dest);
|
cmds += cp_gpuaddr(adreno_dev, cmds, dest);
|
||||||
|
|
@ -719,7 +716,7 @@ static void a6xx_preemption_close(struct kgsl_device *device)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
del_timer(&preempt->timer);
|
del_timer(&preempt->timer);
|
||||||
kgsl_free_global(device, &preempt->counters);
|
kgsl_free_global(device, &preempt->scratch);
|
||||||
a6xx_preemption_iommu_close(adreno_dev);
|
a6xx_preemption_iommu_close(adreno_dev);
|
||||||
|
|
||||||
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
||||||
|
|
@ -749,15 +746,19 @@ int a6xx_preemption_init(struct adreno_device *adreno_dev)
|
||||||
setup_timer(&preempt->timer, _a6xx_preemption_timer,
|
setup_timer(&preempt->timer, _a6xx_preemption_timer,
|
||||||
(unsigned long) adreno_dev);
|
(unsigned long) adreno_dev);
|
||||||
|
|
||||||
/* Allocate mem for storing preemption counters */
|
/*
|
||||||
ret = kgsl_allocate_global(device, &preempt->counters,
|
* Allocate a scratch buffer to keep the below table:
|
||||||
adreno_dev->num_ringbuffers *
|
* Offset: What
|
||||||
A6XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0,
|
* 0x0: Context Record address
|
||||||
"preemption_counters");
|
* 0x10: Preemption Counters
|
||||||
|
*/
|
||||||
|
ret = kgsl_allocate_global(device, &preempt->scratch, PAGE_SIZE, 0, 0,
|
||||||
|
"preemption_scratch");
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
addr = preempt->counters.gpuaddr;
|
addr = preempt->scratch.gpuaddr +
|
||||||
|
KGSL_PRIORITY_MAX_RB_LEVELS * sizeof(u64);
|
||||||
|
|
||||||
/* Allocate mem for storing preemption switch record */
|
/* Allocate mem for storing preemption switch record */
|
||||||
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2002,2007-2018,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -168,7 +168,7 @@ static long adreno_ioctl_preemption_counters_query(
|
||||||
levels_to_copy = gpudev->num_prio_levels;
|
levels_to_copy = gpudev->num_prio_levels;
|
||||||
|
|
||||||
if (copy_to_user((void __user *) (uintptr_t) read->counters,
|
if (copy_to_user((void __user *) (uintptr_t) read->counters,
|
||||||
adreno_dev->preempt.counters.hostptr,
|
adreno_dev->preempt.scratch.hostptr,
|
||||||
levels_to_copy * size_level))
|
levels_to_copy * size_level))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2002,2007-2017,2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -103,6 +103,8 @@
|
||||||
/* A5XX Enable yield in RB only */
|
/* A5XX Enable yield in RB only */
|
||||||
#define CP_YIELD_ENABLE 0x1C
|
#define CP_YIELD_ENABLE 0x1C
|
||||||
|
|
||||||
|
#define CP_WHERE_AM_I 0x62
|
||||||
|
|
||||||
/* Enable/Disable/Defer A5x global preemption model */
|
/* Enable/Disable/Defer A5x global preemption model */
|
||||||
#define CP_PREEMPT_ENABLE_GLOBAL 0x69
|
#define CP_PREEMPT_ENABLE_GLOBAL 0x69
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -181,7 +181,7 @@ void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb,
|
||||||
adreno_ringbuffer_wptr(adreno_dev, rb);
|
adreno_ringbuffer_wptr(adreno_dev, rb);
|
||||||
}
|
}
|
||||||
|
|
||||||
int adreno_ringbuffer_submit_spin(struct adreno_ringbuffer *rb,
|
int adreno_ringbuffer_submit_spin_nosync(struct adreno_ringbuffer *rb,
|
||||||
struct adreno_submit_time *time, unsigned int timeout)
|
struct adreno_submit_time *time, unsigned int timeout)
|
||||||
{
|
{
|
||||||
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
|
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
|
||||||
|
|
@ -190,6 +190,38 @@ int adreno_ringbuffer_submit_spin(struct adreno_ringbuffer *rb,
|
||||||
return adreno_spin_idle(adreno_dev, timeout);
|
return adreno_spin_idle(adreno_dev, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adreno_ringbuffer_submit_spin() - Submit the cmds and wait until GPU is idle
|
||||||
|
* @rb: Pointer to ringbuffer
|
||||||
|
* @time: Pointer to adreno_submit_time
|
||||||
|
* @timeout: timeout value in ms
|
||||||
|
*
|
||||||
|
* Add commands to the ringbuffer and wait until GPU goes to idle. This routine
|
||||||
|
* inserts a WHERE_AM_I packet to trigger a shadow rptr update. So, use
|
||||||
|
* adreno_ringbuffer_submit_spin_nosync() if the previous cmd in the RB is a
|
||||||
|
* CSY packet because CSY followed by WHERE_AM_I is not legal.
|
||||||
|
*/
|
||||||
|
int adreno_ringbuffer_submit_spin(struct adreno_ringbuffer *rb,
|
||||||
|
struct adreno_submit_time *time, unsigned int timeout)
|
||||||
|
{
|
||||||
|
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
|
||||||
|
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||||
|
unsigned int *cmds;
|
||||||
|
|
||||||
|
if (adreno_is_a3xx(adreno_dev))
|
||||||
|
return adreno_ringbuffer_submit_spin_nosync(rb, time, timeout);
|
||||||
|
|
||||||
|
cmds = adreno_ringbuffer_allocspace(rb, 3);
|
||||||
|
if (IS_ERR(cmds))
|
||||||
|
return PTR_ERR(cmds);
|
||||||
|
|
||||||
|
*cmds++ = cp_packet(adreno_dev, CP_WHERE_AM_I, 2);
|
||||||
|
cmds += cp_gpuaddr(adreno_dev, cmds,
|
||||||
|
SCRATCH_RPTR_GPU_ADDR(device, rb->id));
|
||||||
|
|
||||||
|
return adreno_ringbuffer_submit_spin_nosync(rb, time, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
|
unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb,
|
||||||
unsigned int dwords)
|
unsigned int dwords)
|
||||||
{
|
{
|
||||||
|
|
@ -317,11 +349,12 @@ int adreno_ringbuffer_probe(struct adreno_device *adreno_dev, bool nopreempt)
|
||||||
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
|
||||||
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
|
||||||
int i;
|
int i;
|
||||||
|
unsigned int priv = KGSL_MEMDESC_RANDOM | KGSL_MEMDESC_PRIVILEGED;
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
|
|
||||||
if (!adreno_is_a3xx(adreno_dev)) {
|
if (!adreno_is_a3xx(adreno_dev)) {
|
||||||
status = kgsl_allocate_global(device, &device->scratch,
|
status = kgsl_allocate_global(device, &device->scratch,
|
||||||
PAGE_SIZE, 0, KGSL_MEMDESC_RANDOM, "scratch");
|
PAGE_SIZE, 0, priv, "scratch");
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -527,6 +560,8 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||||
if (gpudev->preemption_post_ibsubmit &&
|
if (gpudev->preemption_post_ibsubmit &&
|
||||||
adreno_is_preemption_enabled(adreno_dev))
|
adreno_is_preemption_enabled(adreno_dev))
|
||||||
total_sizedwords += 10;
|
total_sizedwords += 10;
|
||||||
|
else if (!adreno_is_a3xx(adreno_dev))
|
||||||
|
total_sizedwords += 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* a5xx uses 64 bit memory address. pm4 commands that involve read/write
|
* a5xx uses 64 bit memory address. pm4 commands that involve read/write
|
||||||
|
|
@ -738,6 +773,11 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||||
adreno_is_preemption_enabled(adreno_dev))
|
adreno_is_preemption_enabled(adreno_dev))
|
||||||
ringcmds += gpudev->preemption_post_ibsubmit(adreno_dev,
|
ringcmds += gpudev->preemption_post_ibsubmit(adreno_dev,
|
||||||
ringcmds);
|
ringcmds);
|
||||||
|
else if (!adreno_is_a3xx(adreno_dev)) {
|
||||||
|
*ringcmds++ = cp_packet(adreno_dev, CP_WHERE_AM_I, 2);
|
||||||
|
ringcmds += cp_gpuaddr(adreno_dev, ringcmds,
|
||||||
|
SCRATCH_RPTR_GPU_ADDR(device, rb->id));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have more ringbuffer commands than space reserved
|
* If we have more ringbuffer commands than space reserved
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -180,6 +180,9 @@ int adreno_ringbuffer_issue_internal_cmds(struct adreno_ringbuffer *rb,
|
||||||
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb,
|
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb,
|
||||||
struct adreno_submit_time *time);
|
struct adreno_submit_time *time);
|
||||||
|
|
||||||
|
int adreno_ringbuffer_submit_spin_nosync(struct adreno_ringbuffer *rb,
|
||||||
|
struct adreno_submit_time *time, unsigned int timeout);
|
||||||
|
|
||||||
int adreno_ringbuffer_submit_spin(struct adreno_ringbuffer *rb,
|
int adreno_ringbuffer_submit_spin(struct adreno_ringbuffer *rb,
|
||||||
struct adreno_submit_time *time, unsigned int timeout);
|
struct adreno_submit_time *time, unsigned int timeout);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2008-2019, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2008-2020, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 and
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
|
@ -71,13 +71,11 @@
|
||||||
/*
|
/*
|
||||||
* SCRATCH MEMORY: The scratch memory is one page worth of data that
|
* SCRATCH MEMORY: The scratch memory is one page worth of data that
|
||||||
* is mapped into the GPU. This allows for some 'shared' data between
|
* is mapped into the GPU. This allows for some 'shared' data between
|
||||||
* the GPU and CPU. For example, it will be used by the GPU to write
|
* the GPU and CPU.
|
||||||
* each updated RPTR for each RB.
|
|
||||||
*
|
*
|
||||||
* Used Data:
|
* Used Data:
|
||||||
* Offset: Length(bytes): What
|
* Offset: Length(bytes): What
|
||||||
* 0x0: 4 * KGSL_PRIORITY_MAX_RB_LEVELS: RB0 RPTR
|
* 0x0: 4 * KGSL_PRIORITY_MAX_RB_LEVELS: RB0 RPTR
|
||||||
* 0x10: 8 * KGSL_PRIORITY_MAX_RB_LEVELS: RB0 CTXT RESTORE ADDR
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Shadow global helpers */
|
/* Shadow global helpers */
|
||||||
|
|
@ -85,13 +83,6 @@
|
||||||
#define SCRATCH_RPTR_GPU_ADDR(dev, id) \
|
#define SCRATCH_RPTR_GPU_ADDR(dev, id) \
|
||||||
((dev)->scratch.gpuaddr + SCRATCH_RPTR_OFFSET(id))
|
((dev)->scratch.gpuaddr + SCRATCH_RPTR_OFFSET(id))
|
||||||
|
|
||||||
#define SCRATCH_PREEMPTION_CTXT_RESTORE_ADDR_OFFSET(id) \
|
|
||||||
(SCRATCH_RPTR_OFFSET(KGSL_PRIORITY_MAX_RB_LEVELS) + \
|
|
||||||
((id) * sizeof(uint64_t)))
|
|
||||||
#define SCRATCH_PREEMPTION_CTXT_RESTORE_GPU_ADDR(dev, id) \
|
|
||||||
((dev)->scratch.gpuaddr + \
|
|
||||||
SCRATCH_PREEMPTION_CTXT_RESTORE_ADDR_OFFSET(id))
|
|
||||||
|
|
||||||
/* Timestamp window used to detect rollovers (half of integer range) */
|
/* Timestamp window used to detect rollovers (half of integer range) */
|
||||||
#define KGSL_TIMESTAMP_WINDOW 0x80000000
|
#define KGSL_TIMESTAMP_WINDOW 0x80000000
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue