msm: kgsl: Move globals to the KGSL device handle

Move the list of globals out of iommu and move them to a linked list in
the device instead. But that's not the clever part. The clever part is
we painstakingly dynamically allocate all of the global objects and
track them so we can automatically clean them up when the device is
removed, thereby saving quite a bit of pain. Also, by dynamically
allocating the memdescs we can skip creating lots of static memory
descriptors that may or may not be used for any given target.

Change-Id: Ic0dedbadb9963bb7395a9845aebc1d828ba6dd8e
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
This commit is contained in:
Jordan Crouse 2019-10-14 10:41:02 -06:00
commit 2f23b00d46
31 changed files with 671 additions and 818 deletions

View file

@ -3,6 +3,7 @@
* Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/of.h>
@ -90,6 +91,39 @@ int adreno_wake_nice = -7;
/* Number of milliseconds to stay active active after a wake on touch */
unsigned int adreno_wake_timeout = 100;
int adreno_get_firmware(struct adreno_device *adreno_dev,
const char *fwfile, struct adreno_firmware *firmware)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
const struct firmware *fw = NULL;
int ret;
if (!IS_ERR_OR_NULL(firmware->memdesc))
return 0;
ret = request_firmware(&fw, fwfile, &device->pdev->dev);
if (ret) {
dev_err(device->dev, "request_firmware(%s) failed: %d\n",
fwfile, ret);
return ret;
}
firmware->memdesc = kgsl_allocate_global(device, fw->size - 4,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_UCODE,
"ucode");
ret = PTR_ERR_OR_ZERO(firmware->memdesc);
if (!ret) {
memcpy(firmware->memdesc->hostptr, &fw->data[4], fw->size - 4);
firmware->size = (fw->size - 4) / sizeof(u32);
firmware->version = *((u32 *)&fw->data[4]);
}
release_firmware(fw);
return ret;
}
void adreno_reglist_write(struct adreno_device *adreno_dev,
const struct adreno_reglist *list, u32 count)
{
@ -161,7 +195,7 @@ unsigned int adreno_get_rptr(struct adreno_ringbuffer *rb)
else {
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
kgsl_sharedmem_readl(&device->scratch, &rptr,
kgsl_sharedmem_readl(device->scratch, &rptr,
SCRATCH_RPTR_OFFSET(rb->id));
}
@ -1404,9 +1438,10 @@ static int adreno_probe(struct platform_device *pdev)
if (ADRENO_FEATURE(adreno_dev, ADRENO_APRIV))
priv |= KGSL_MEMDESC_PRIVILEGED;
status = kgsl_allocate_global(device, &device->memstore,
device->memstore = kgsl_allocate_global(device,
KGSL_MEMSTORE_SIZE, 0, priv, "memstore");
status = PTR_ERR_OR_ZERO(device->memstore);
if (status)
goto out;
@ -1474,7 +1509,6 @@ static int adreno_probe(struct platform_device *pdev)
out:
if (status) {
adreno_ringbuffer_close(adreno_dev);
kgsl_free_global(device, &device->memstore);
kgsl_device_platform_remove(device);
device->pdev = NULL;
}
@ -1484,13 +1518,9 @@ out:
static void _adreno_free_memories(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_firmware *pfp_fw = ADRENO_FW(adreno_dev, ADRENO_FW_PFP);
struct adreno_firmware *pm4_fw = ADRENO_FW(adreno_dev, ADRENO_FW_PM4);
if (test_bit(ADRENO_DEVICE_DRAWOBJ_PROFILE, &adreno_dev->priv))
kgsl_free_global(device, &adreno_dev->profile_buffer);
/* Free local copies of firmware and other command streams */
kfree(pfp_fw->fwvirt);
pfp_fw->fwvirt = NULL;
@ -1500,9 +1530,6 @@ static void _adreno_free_memories(struct adreno_device *adreno_dev)
kfree(adreno_dev->gpmu_cmds);
adreno_dev->gpmu_cmds = NULL;
kgsl_free_global(device, &pfp_fw->memdesc);
kgsl_free_global(device, &pm4_fw->memdesc);
}
static int adreno_remove(struct platform_device *pdev)
@ -1558,16 +1585,11 @@ static int adreno_remove(struct platform_device *pdev)
if (efuse_base != NULL)
iounmap(efuse_base);
kgsl_free_global(device, &device->memstore);
kgsl_device_platform_remove(device);
gmu_core_remove(device);
if (test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv)) {
kgsl_free_global(device, &adreno_dev->pwron_fixup);
clear_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv);
}
clear_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv);
clear_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv);
return 0;
@ -1676,10 +1698,6 @@ static int adreno_init(struct kgsl_device *device)
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
int ret;
if (!adreno_is_a3xx(adreno_dev))
kgsl_sharedmem_set(device, &device->scratch, 0, 0,
device->scratch.size);
ret = kgsl_pwrctrl_change_state(device, KGSL_STATE_INIT);
if (ret)
return ret;
@ -1736,25 +1754,19 @@ static int adreno_init(struct kgsl_device *device)
if (!adreno_is_a3xx(adreno_dev)) {
unsigned int priv = 0;
int r;
if (ADRENO_FEATURE(adreno_dev, ADRENO_APRIV))
priv |= KGSL_MEMDESC_PRIVILEGED;
r = kgsl_allocate_global(device,
&adreno_dev->profile_buffer, PAGE_SIZE,
0, priv, "alwayson");
adreno_dev->profile_buffer =
kgsl_allocate_global(device, PAGE_SIZE, 0, priv,
"alwayson");
adreno_dev->profile_index = 0;
if (r == 0) {
if (!IS_ERR(adreno_dev->profile_buffer))
set_bit(ADRENO_DEVICE_DRAWOBJ_PROFILE,
&adreno_dev->priv);
kgsl_sharedmem_set(device,
&adreno_dev->profile_buffer, 0, 0,
PAGE_SIZE);
}
}
return 0;
@ -1857,7 +1869,7 @@ static void adreno_set_active_ctxs_null(struct adreno_device *adreno_dev)
rb->drawctxt_active = NULL;
kgsl_sharedmem_writel(KGSL_DEVICE(adreno_dev),
&rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname),
rb->pagetable_desc, PT_INFO_OFFSET(current_rb_ptname),
0);
}
}
@ -2314,14 +2326,14 @@ static int adreno_prop_device_shadow(struct kgsl_device *device,
{
struct kgsl_shadowprop shadowprop = { 0 };
if (device->memstore.hostptr) {
if (device->memstore->hostptr) {
/*
* NOTE: with mmu enabled, gpuaddr doesn't mean
* anything to mmap().
*/
shadowprop.gpuaddr = (unsigned long)device->memstore.gpuaddr;
shadowprop.size = device->memstore.size;
shadowprop.gpuaddr = (unsigned long)device->memstore->gpuaddr;
shadowprop.size = device->memstore->size;
shadowprop.flags = KGSL_FLAGS_INITIALIZED |
KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS;
@ -2334,11 +2346,10 @@ static int adreno_prop_device_qdss_stm(struct kgsl_device *device,
struct kgsl_device_getproperty *param)
{
struct kgsl_qdss_stm_prop qdssprop = {0};
struct kgsl_memdesc *qdss_desc = kgsl_mmu_get_qdss_global_entry(device);
if (qdss_desc) {
qdssprop.gpuaddr = qdss_desc->gpuaddr;
qdssprop.size = qdss_desc->size;
if (!IS_ERR_OR_NULL(device->qdss_desc)) {
qdssprop.gpuaddr = device->qdss_desc->gpuaddr;
qdssprop.size = device->qdss_desc->size;
}
return copy_prop(param, &qdssprop, sizeof(qdssprop));
@ -2348,12 +2359,10 @@ static int adreno_prop_device_qtimer(struct kgsl_device *device,
struct kgsl_device_getproperty *param)
{
struct kgsl_qtimer_prop qtimerprop = {0};
struct kgsl_memdesc *qtimer_desc =
kgsl_mmu_get_qtimer_global_entry(device);
if (qtimer_desc) {
qtimerprop.gpuaddr = qtimer_desc->gpuaddr;
qtimerprop.size = qtimer_desc->size;
if (!IS_ERR_OR_NULL(device->qtimer_desc)) {
qtimerprop.gpuaddr = device->qtimer_desc->gpuaddr;
qtimerprop.size = device->qtimer_desc->size;
}
return copy_prop(param, &qtimerprop, sizeof(qtimerprop));
@ -3361,11 +3370,11 @@ static int __adreno_readtimestamp(struct adreno_device *adreno_dev, int index,
switch (type) {
case KGSL_TIMESTAMP_CONSUMED:
kgsl_sharedmem_readl(&device->memstore, timestamp,
kgsl_sharedmem_readl(device->memstore, timestamp,
KGSL_MEMSTORE_OFFSET(index, soptimestamp));
break;
case KGSL_TIMESTAMP_RETIRED:
kgsl_sharedmem_readl(&device->memstore, timestamp,
kgsl_sharedmem_readl(device->memstore, timestamp,
KGSL_MEMSTORE_OFFSET(index, eoptimestamp));
break;
default:

View file

@ -270,7 +270,7 @@ enum adreno_preempt_states {
*/
struct adreno_preemption {
atomic_t state;
struct kgsl_memdesc counters;
struct kgsl_memdesc *counters;
struct timer_list timer;
struct work_struct work;
unsigned int preempt_level;
@ -303,7 +303,7 @@ struct adreno_firmware {
unsigned int *fwvirt;
size_t size;
unsigned int version;
struct kgsl_memdesc memdesc;
struct kgsl_memdesc *memdesc;
};
/**
@ -481,7 +481,7 @@ struct adreno_device {
bool cooperative_reset;
struct adreno_profile profile;
struct adreno_dispatcher dispatcher;
struct kgsl_memdesc pwron_fixup;
struct kgsl_memdesc *pwron_fixup;
unsigned int pwron_fixup_dwords;
struct work_struct input_work;
struct adreno_busy_data busy_data;
@ -498,9 +498,9 @@ struct adreno_device {
struct dentry *ctx_d_debugfs;
unsigned long pwrctrl_flag;
struct kgsl_memdesc profile_buffer;
struct kgsl_memdesc *profile_buffer;
unsigned int profile_index;
struct kgsl_memdesc pwrup_reglist;
struct kgsl_memdesc *pwrup_reglist;
uint32_t *lm_sequence;
uint32_t lm_size;
struct adreno_preemption preempt;
@ -529,6 +529,10 @@ struct adreno_device {
bool gpuhtw_llc_slice_enable;
unsigned int zap_loaded;
unsigned int soc_hw_rev;
/**
* @critpkts: Memory descriptor for 5xx critical packets if applicable
*/
struct kgsl_memdesc *critpkts;
};
/**
@ -1506,7 +1510,7 @@ static inline void adreno_ringbuffer_set_global(
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
kgsl_sharedmem_writel(device,
&adreno_dev->ringbuffers[0].pagetable_desc,
adreno_dev->ringbuffers[0].pagetable_desc,
PT_INFO_OFFSET(current_global_ptname), name);
}
@ -1519,13 +1523,13 @@ static inline void adreno_ringbuffer_set_pagetable(struct adreno_ringbuffer *rb,
spin_lock_irqsave(&rb->preempt_lock, flags);
kgsl_sharedmem_writel(device, &rb->pagetable_desc,
kgsl_sharedmem_writel(device, rb->pagetable_desc,
PT_INFO_OFFSET(current_rb_ptname), pt->name);
kgsl_sharedmem_writeq(device, &rb->pagetable_desc,
kgsl_sharedmem_writeq(device, rb->pagetable_desc,
PT_INFO_OFFSET(ttbr0), kgsl_mmu_pagetable_get_ttbr0(pt));
kgsl_sharedmem_writel(device, &rb->pagetable_desc,
kgsl_sharedmem_writel(device, rb->pagetable_desc,
PT_INFO_OFFSET(contextidr),
kgsl_mmu_pagetable_get_contextidr(pt));
@ -1686,4 +1690,19 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev,
unsigned int fence_mask);
int adreno_clear_pending_transactions(struct kgsl_device *device);
void adreno_gmu_send_nmi(struct adreno_device *adreno_dev);
/**
* adreno_get_firwmare - Load firmware into a adreno_firmware struct
* @adreno_dev: An Adreno GPU device handle
* @fwfile: Firmware file to load
* @firmware: A &struct adreno_firmware container for the firmware.
*
* Load the specified firmware file into the memdesc in &struct adreno_firmware
* and get the size and version from the data.
*
* Return: 0 on success or negative on failure
*/
int adreno_get_firmware(struct adreno_device *adreno_dev,
const char *fwfile, struct adreno_firmware *firmware);
#endif /*__ADRENO_H */

View file

@ -177,20 +177,18 @@ static int _a3xx_pwron_fixup(struct adreno_device *adreno_dev)
{
unsigned int *cmds;
int count = ARRAY_SIZE(_a3xx_pwron_fixup_fs_instructions);
int ret;
/* Return if the fixup is already in place */
if (test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv))
return 0;
ret = kgsl_allocate_global(KGSL_DEVICE(adreno_dev),
&adreno_dev->pwron_fixup, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, 0, "pwron_fixup");
adreno_dev->pwron_fixup = kgsl_allocate_global(KGSL_DEVICE(adreno_dev),
PAGE_SIZE, KGSL_MEMFLAGS_GPUREADONLY, 0, "pwron_fixup");
if (ret)
return ret;
if (IS_ERR(adreno_dev->pwron_fixup))
return PTR_ERR(adreno_dev->pwron_fixup);
cmds = adreno_dev->pwron_fixup.hostptr;
cmds = adreno_dev->pwron_fixup->hostptr;
*cmds++ = cp_type0_packet(A3XX_UCHE_CACHE_INVALIDATE0_REG, 2);
*cmds++ = 0x00000000;
@ -598,7 +596,7 @@ static int _a3xx_pwron_fixup(struct adreno_device *adreno_dev)
* program the indirect buffer call in the ringbuffer
*/
adreno_dev->pwron_fixup_dwords =
(cmds - (unsigned int *) adreno_dev->pwron_fixup.hostptr);
(cmds - (unsigned int *) adreno_dev->pwron_fixup->hostptr);
/* Mark the flag in ->priv to show that we have the fix */
set_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv);
@ -678,7 +676,7 @@ static int a3xx_rb_start(struct adreno_device *adreno_dev)
(1 << 27));
adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_BASE,
rb->buffer_desc.gpuaddr);
rb->buffer_desc->gpuaddr);
a3xx_microcode_load(adreno_dev);

View file

@ -19,8 +19,6 @@
#include "kgsl_trace.h"
static int critical_packet_constructed;
static struct kgsl_memdesc crit_pkts;
static unsigned int crit_pkts_dwords;
static struct kgsl_memdesc crit_pkts_refbuf0;
@ -129,8 +127,6 @@ static void a5xx_platform_setup(struct adreno_device *adreno_dev)
static void a5xx_critical_packet_destroy(struct adreno_device *adreno_dev)
{
kgsl_free_global(&adreno_dev->dev, &crit_pkts);
kgsl_iommu_unmap_global_secure_pt_entry(KGSL_DEVICE(adreno_dev),
&crit_pkts_refbuf0);
kgsl_sharedmem_free(&crit_pkts_refbuf0);
@ -159,10 +155,10 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev)
uint64_t gpuaddrs[4];
int ret;
ret = kgsl_allocate_global(&adreno_dev->dev,
&crit_pkts, PAGE_SIZE * 4, 0, 0, "crit_pkts");
if (ret)
return ret;
adreno_dev->critpkts = kgsl_allocate_global(KGSL_DEVICE(adreno_dev),
PAGE_SIZE * 4, 0, 0, "crit_pkts");
if (IS_ERR(adreno_dev->critpkts))
return PTR_ERR(adreno_dev->critpkts);
ret = kgsl_allocate_user(&adreno_dev->dev, &crit_pkts_refbuf0,
PAGE_SIZE, KGSL_MEMFLAGS_SECURE, 0);
@ -174,12 +170,12 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev)
if (ret)
return ret;
cmds = crit_pkts.hostptr;
cmds = adreno_dev->critpkts->hostptr;
gpuaddrs[0] = crit_pkts_refbuf0.gpuaddr;
gpuaddrs[1] = crit_pkts.gpuaddr + PAGE_SIZE;
gpuaddrs[2] = crit_pkts.gpuaddr + (PAGE_SIZE * 2);
gpuaddrs[3] = crit_pkts.gpuaddr + (PAGE_SIZE * 3);
gpuaddrs[1] = adreno_dev->critpkts->gpuaddr + PAGE_SIZE;
gpuaddrs[2] = adreno_dev->critpkts->gpuaddr + (PAGE_SIZE * 2);
gpuaddrs[3] = adreno_dev->critpkts->gpuaddr + (PAGE_SIZE * 3);
crit_pkts_dwords = ARRAY_SIZE(_a5xx_critical_pkts);
@ -188,15 +184,15 @@ static int a5xx_critical_packet_construct(struct adreno_device *adreno_dev)
_do_fixup(critical_pkt_fixups, ARRAY_SIZE(critical_pkt_fixups),
gpuaddrs, cmds);
cmds = crit_pkts.hostptr + PAGE_SIZE;
cmds = adreno_dev->critpkts->hostptr + PAGE_SIZE;
memcpy(cmds, _a5xx_critical_pkts_mem01,
ARRAY_SIZE(_a5xx_critical_pkts_mem01) << 2);
cmds = crit_pkts.hostptr + (PAGE_SIZE * 2);
cmds = adreno_dev->critpkts->hostptr + (PAGE_SIZE * 2);
memcpy(cmds, _a5xx_critical_pkts_mem02,
ARRAY_SIZE(_a5xx_critical_pkts_mem02) << 2);
cmds = crit_pkts.hostptr + (PAGE_SIZE * 3);
cmds = adreno_dev->critpkts->hostptr + (PAGE_SIZE * 3);
memcpy(cmds, _a5xx_critical_pkts_mem03,
ARRAY_SIZE(_a5xx_critical_pkts_mem03) << 2);
@ -1589,7 +1585,7 @@ static int _preemption_init(
struct kgsl_context *context)
{
unsigned int *cmds_orig = cmds;
uint64_t gpuaddr = rb->preemption_desc.gpuaddr;
uint64_t gpuaddr = rb->preemption_desc->gpuaddr;
/* Turn CP protection OFF */
cmds += cp_protected_mode(adreno_dev, cmds, 0);
@ -1698,13 +1694,13 @@ static int a5xx_microcode_load(struct adreno_device *adreno_dev)
const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev);
uint64_t gpuaddr;
gpuaddr = pm4_fw->memdesc.gpuaddr;
gpuaddr = pm4_fw->memdesc->gpuaddr;
kgsl_regwrite(device, A5XX_CP_PM4_INSTR_BASE_LO,
lower_32_bits(gpuaddr));
kgsl_regwrite(device, A5XX_CP_PM4_INSTR_BASE_HI,
upper_32_bits(gpuaddr));
gpuaddr = pfp_fw->memdesc.gpuaddr;
gpuaddr = pfp_fw->memdesc->gpuaddr;
kgsl_regwrite(device, A5XX_CP_PFP_INSTR_BASE_LO,
lower_32_bits(gpuaddr));
kgsl_regwrite(device, A5XX_CP_PFP_INSTR_BASE_HI,
@ -1841,7 +1837,7 @@ int a5xx_critical_packet_submit(struct adreno_device *adreno_dev,
return PTR_ERR(cmds);
*cmds++ = cp_mem_packet(adreno_dev, CP_INDIRECT_BUFFER_PFE, 2, 1);
cmds += cp_gpuaddr(adreno_dev, cmds, crit_pkts.gpuaddr);
cmds += cp_gpuaddr(adreno_dev, cmds, adreno_dev->critpkts->gpuaddr);
*cmds++ = crit_pkts_dwords;
ret = adreno_ringbuffer_submit_spin(rb, NULL, 20);
@ -1910,7 +1906,7 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev)
A5XX_CP_RB_CNTL_DEFAULT);
adreno_writereg64(adreno_dev, ADRENO_REG_CP_RB_BASE,
ADRENO_REG_CP_RB_BASE_HI, rb->buffer_desc.gpuaddr);
ADRENO_REG_CP_RB_BASE_HI, rb->buffer_desc->gpuaddr);
ret = a5xx_microcode_load(adreno_dev);
if (ret)
@ -1937,36 +1933,6 @@ static int a5xx_rb_start(struct adreno_device *adreno_dev)
return 0;
}
static int _load_firmware(struct kgsl_device *device, const char *fwfile,
struct adreno_firmware *firmware)
{
const struct firmware *fw = NULL;
int ret;
ret = request_firmware(&fw, fwfile, device->dev);
if (ret) {
dev_err(device->dev, "request_firmware(%s) failed: %d\n",
fwfile, ret);
return ret;
}
ret = kgsl_allocate_global(device, &firmware->memdesc, fw->size - 4,
KGSL_MEMFLAGS_GPUREADONLY, 0, "ucode");
if (ret)
goto done;
memcpy(firmware->memdesc.hostptr, &fw->data[4], fw->size - 4);
firmware->size = (fw->size - 4) / sizeof(uint32_t);
firmware->version = *(unsigned int *)&fw->data[4];
done:
release_firmware(fw);
return ret;
}
/*
* a5xx_microcode_read() - Read microcode
* @adreno_dev: Pointer to adreno device
@ -1978,19 +1944,13 @@ static int a5xx_microcode_read(struct adreno_device *adreno_dev)
struct adreno_firmware *pfp_fw = ADRENO_FW(adreno_dev, ADRENO_FW_PFP);
const struct adreno_a5xx_core *a5xx_core = to_a5xx_core(adreno_dev);
if (pm4_fw->memdesc.hostptr == NULL) {
ret = _load_firmware(KGSL_DEVICE(adreno_dev),
a5xx_core->pm4fw_name, pm4_fw);
if (ret)
return ret;
}
ret = adreno_get_firmware(adreno_dev, a5xx_core->pm4fw_name, pm4_fw);
if (ret)
return ret;
if (pfp_fw->memdesc.hostptr == NULL) {
ret = _load_firmware(KGSL_DEVICE(adreno_dev),
a5xx_core->pfpfw_name, pfp_fw);
if (ret)
return ret;
}
ret = adreno_get_firmware(adreno_dev, a5xx_core->pfpfw_name, pfp_fw);
if (ret)
return ret;
ret = _load_gpmu_firmware(adreno_dev);
if (ret)
@ -2665,7 +2625,7 @@ static void a5xx_cp_callback(struct adreno_device *adreno_dev, int bit)
if (test_bit(ADRENO_DEVICE_CACHE_FLUSH_TS_SUSPENDED, &adreno_dev->priv))
return;
kgsl_sharedmem_readl(&device->memstore, &cur,
kgsl_sharedmem_readl(device->memstore, &cur,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
ref_wait_ts));

View file

@ -241,26 +241,26 @@ void a5xx_preemption_trigger(struct adreno_device *adreno_dev)
* preemption_desc at init time, so no need to check if
* sharedmem accesses to these memdescs succeed.
*/
kgsl_sharedmem_readq(&next->pagetable_desc, &ttbr0,
kgsl_sharedmem_readq(next->pagetable_desc, &ttbr0,
PT_INFO_OFFSET(ttbr0));
kgsl_sharedmem_readl(&next->pagetable_desc, &contextidr,
kgsl_sharedmem_readl(next->pagetable_desc, &contextidr,
PT_INFO_OFFSET(contextidr));
kgsl_sharedmem_writel(device, &next->preemption_desc,
kgsl_sharedmem_writel(device, next->preemption_desc,
PREEMPT_RECORD(wptr), next->wptr);
spin_unlock_irqrestore(&next->preempt_lock, flags);
/* And write it to the smmu info */
kgsl_sharedmem_writeq(device, &iommu->smmu_info,
kgsl_sharedmem_writeq(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(ttbr0), ttbr0);
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(context_idr), contextidr);
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO,
lower_32_bits(next->preemption_desc.gpuaddr));
lower_32_bits(next->preemption_desc->gpuaddr));
kgsl_regwrite(device, A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_HI,
upper_32_bits(next->preemption_desc.gpuaddr));
upper_32_bits(next->preemption_desc->gpuaddr));
adreno_dev->next_rb = next;
@ -346,7 +346,7 @@ unsigned int a5xx_preemption_pre_ibsubmit(
unsigned int *cmds, struct kgsl_context *context)
{
unsigned int *cmds_orig = cmds;
uint64_t gpuaddr = rb->preemption_desc.gpuaddr;
uint64_t gpuaddr = rb->preemption_desc->gpuaddr;
unsigned int preempt_style = 0;
if (context) {
@ -463,31 +463,31 @@ void a5xx_preemption_start(struct adreno_device *adreno_dev)
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
/* smmu_info is allocated and mapped in a5xx_preemption_iommu_init */
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(magic), A5XX_CP_SMMU_INFO_MAGIC_REF);
kgsl_sharedmem_writeq(device, &iommu->smmu_info,
kgsl_sharedmem_writeq(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(ttbr0), MMU_DEFAULT_TTBR0(device));
/* The CP doesn't use the asid record, so poison it */
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(asid), 0xDECAFBAD);
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(context_idr),
MMU_DEFAULT_CONTEXTIDR(device));
adreno_writereg64(adreno_dev,
ADRENO_REG_CP_CONTEXT_SWITCH_SMMU_INFO_LO,
ADRENO_REG_CP_CONTEXT_SWITCH_SMMU_INFO_HI,
iommu->smmu_info.gpuaddr);
iommu->smmu_info->gpuaddr);
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
/*
* preemption_desc is allocated and mapped at init time,
* so no need to check sharedmem_writel return value
*/
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(rptr), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(wptr), 0);
adreno_ringbuffer_set_pagetable(rb,
@ -500,32 +500,33 @@ static int a5xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev,
struct adreno_ringbuffer *rb, uint64_t counteraddr)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
int ret;
ret = kgsl_allocate_global(device, &rb->preemption_desc,
A5XX_CP_CTXRECORD_SIZE_IN_BYTES, 0, KGSL_MEMDESC_PRIVILEGED,
"preemption_desc");
if (ret)
return ret;
if (IS_ERR_OR_NULL(rb->preemption_desc))
rb->preemption_desc = kgsl_allocate_global(device,
A5XX_CP_CTXRECORD_SIZE_IN_BYTES, 0,
KGSL_MEMDESC_PRIVILEGED, "preemption_desc");
kgsl_sharedmem_writel(device, &rb->preemption_desc,
if (IS_ERR(rb->preemption_desc))
return PTR_ERR(rb->preemption_desc);
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(magic), A5XX_CP_CTXRECORD_MAGIC_REF);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(info), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(data), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(cntl), A5XX_CP_RB_CNTL_DEFAULT);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(rptr), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(wptr), 0);
kgsl_sharedmem_writeq(device, &rb->preemption_desc,
kgsl_sharedmem_writeq(device, rb->preemption_desc,
PREEMPT_RECORD(rptr_addr), SCRATCH_RPTR_GPU_ADDR(device,
rb->id));
kgsl_sharedmem_writeq(device, &rb->preemption_desc,
PREEMPT_RECORD(rbase), rb->buffer_desc.gpuaddr);
kgsl_sharedmem_writeq(device, &rb->preemption_desc,
kgsl_sharedmem_writeq(device, rb->preemption_desc,
PREEMPT_RECORD(rbase), rb->buffer_desc->gpuaddr);
kgsl_sharedmem_writeq(device, rb->preemption_desc,
PREEMPT_RECORD(counter), counteraddr);
return 0;
@ -538,44 +539,25 @@ static int a5xx_preemption_iommu_init(struct adreno_device *adreno_dev)
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
/* Allocate mem for storing preemption smmu record */
return kgsl_allocate_global(device, &iommu->smmu_info, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED,
"smmu_info");
if (IS_ERR_OR_NULL(iommu->smmu_info))
iommu->smmu_info = kgsl_allocate_global(device, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED,
"smmu_info");
return PTR_ERR_OR_ZERO(iommu->smmu_info);
}
static void a5xx_preemption_iommu_close(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
kgsl_free_global(device, &iommu->smmu_info);
}
#else
static int a5xx_preemption_iommu_init(struct adreno_device *adreno_dev)
{
return -ENODEV;
}
static void a5xx_preemption_iommu_close(struct adreno_device *adreno_dev)
{
}
#endif
static void _preemption_close(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_preemption *preempt = &adreno_dev->preempt;
struct adreno_ringbuffer *rb;
unsigned int i;
del_timer(&preempt->timer);
kgsl_free_global(device, &preempt->counters);
a5xx_preemption_iommu_close(adreno_dev);
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
kgsl_free_global(device, &rb->preemption_desc);
}
}
void a5xx_preemption_close(struct adreno_device *adreno_dev)
@ -604,14 +586,17 @@ int a5xx_preemption_init(struct adreno_device *adreno_dev)
timer_setup(&preempt->timer, _a5xx_preemption_timer, 0);
/* Allocate mem for storing preemption counters */
ret = kgsl_allocate_global(device, &preempt->counters,
adreno_dev->num_ringbuffers *
A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0,
"preemption_counters");
if (IS_ERR_OR_NULL(preempt->counters))
preempt->counters = kgsl_allocate_global(device,
adreno_dev->num_ringbuffers *
A5XX_CP_CTXRECORD_PREEMPTION_COUNTER_SIZE, 0, 0,
"preemption_counters");
ret = PTR_ERR_OR_ZERO(preempt->counters);
if (ret)
goto err;
addr = preempt->counters.gpuaddr;
addr = preempt->counters->gpuaddr;
/* Allocate mem for storing preemption switch record */
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {

View file

@ -137,7 +137,7 @@ static size_t a5xx_snapshot_cp_pm4(struct kgsl_device *device, u8 *buf,
header->type = SNAPSHOT_DEBUG_CP_PM4_RAM;
header->size = size;
memcpy(data, fw->memdesc.hostptr, size * sizeof(uint32_t));
memcpy(data, fw->memdesc->hostptr, size * sizeof(uint32_t));
return DEBUG_SECTION_SZ(size);
}
@ -160,7 +160,7 @@ static size_t a5xx_snapshot_cp_pfp(struct kgsl_device *device, u8 *buf,
header->type = SNAPSHOT_DEBUG_CP_PFP_RAM;
header->size = size;
memcpy(data, fw->memdesc.hostptr, size * sizeof(uint32_t));
memcpy(data, fw->memdesc->hostptr, size * sizeof(uint32_t));
return DEBUG_SECTION_SZ(size);
}
@ -595,8 +595,8 @@ static struct a5xx_shader_block a5xx_shader_blocks[] = {
{A5XX_TP_POWER_RESTORE_RAM, 0x40},
};
static struct kgsl_memdesc capturescript;
static struct kgsl_memdesc registers;
static struct kgsl_memdesc *capturescript;
static struct kgsl_memdesc *registers;
static bool crash_dump_valid;
static size_t a5xx_snapshot_shader_memory(struct kgsl_device *device,
@ -618,7 +618,7 @@ static size_t a5xx_snapshot_shader_memory(struct kgsl_device *device,
header->index = info->bank;
header->size = block->sz;
memcpy(data, registers.hostptr + info->offset,
memcpy(data, registers->hostptr + info->offset,
block->sz * sizeof(unsigned int));
return SHADER_SECTION_SZ(block->sz);
@ -686,7 +686,7 @@ static size_t a5xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
{
struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf;
unsigned int *data = (unsigned int *)(buf + sizeof(*header));
unsigned int *src = (unsigned int *) registers.hostptr;
unsigned int *src = (unsigned int *) registers->hostptr;
struct registers *regs = (struct registers *)priv;
unsigned int j, k;
unsigned int count = 0;
@ -764,7 +764,8 @@ static void _a5xx_do_crashdump(struct kgsl_device *device)
if (!device->snapshot_crashdumper)
return;
if (capturescript.gpuaddr == 0 || registers.gpuaddr == 0)
if (IS_ERR_OR_NULL(capturescript) || IS_ERR_OR_NULL(registers))
return;
/* IF the SMMU is stalled we cannot do a crash dump */
@ -776,9 +777,9 @@ static void _a5xx_do_crashdump(struct kgsl_device *device)
kgsl_regwrite(device, A5XX_CP_CNTL, 1);
kgsl_regwrite(device, A5XX_CP_CRASH_SCRIPT_BASE_LO,
lower_32_bits(capturescript.gpuaddr));
lower_32_bits(capturescript->gpuaddr));
kgsl_regwrite(device, A5XX_CP_CRASH_SCRIPT_BASE_HI,
upper_32_bits(capturescript.gpuaddr));
upper_32_bits(capturescript->gpuaddr));
kgsl_regwrite(device, A5XX_CP_CRASH_DUMP_CNTL, 1);
wait_time = jiffies + msecs_to_jiffies(CP_CRASH_DUMPER_TIMEOUT);
@ -803,7 +804,7 @@ static int get_hlsq_registers(struct kgsl_device *device,
const struct a5xx_hlsq_sp_tp_regs *regs, unsigned int *data)
{
unsigned int i;
unsigned int *src = registers.hostptr + regs->offset;
unsigned int *src = registers->hostptr + regs->offset;
for (i = 0; i < regs->size; i++) {
*data++ = regs->ahbaddr + i;
@ -1016,7 +1017,7 @@ static int _a5xx_crashdump_init_shader(struct a5xx_shader_block *block,
(1 << 21) | 1;
/* Read all the data in one chunk */
ptr[qwords++] = registers.gpuaddr + *offset;
ptr[qwords++] = registers->gpuaddr + *offset;
ptr[qwords++] =
(((uint64_t) A5XX_HLSQ_DBG_AHB_READ_APERTURE << 44)) |
block->sz;
@ -1043,7 +1044,7 @@ static int _a5xx_crashdump_init_hlsq(struct a5xx_hlsq_sp_tp_regs *regs,
(1 << 21) | 1;
/* Read all the data in one chunk */
ptr[qwords++] = registers.gpuaddr + *offset;
ptr[qwords++] = registers->gpuaddr + *offset;
ptr[qwords++] =
(((uint64_t) A5XX_HLSQ_DBG_AHB_READ_APERTURE << 44)) |
regs->size;
@ -1065,7 +1066,7 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev)
uint64_t *ptr;
uint64_t offset = 0;
if (capturescript.gpuaddr != 0 && registers.gpuaddr != 0)
if (!IS_ERR_OR_NULL(capturescript) && !IS_ERR_OR_NULL(registers))
return;
/*
@ -1117,25 +1118,30 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev)
/* Now allocate the script and data buffers */
/* The script buffers needs 2 extra qwords on the end */
if (kgsl_allocate_global(device, &capturescript,
script_size + 16, KGSL_MEMFLAGS_GPUREADONLY,
KGSL_MEMDESC_PRIVILEGED, "capturescript"))
if (!IS_ERR_OR_NULL(capturescript))
capturescript = kgsl_allocate_global(device,
script_size + 16, KGSL_MEMFLAGS_GPUREADONLY,
KGSL_MEMDESC_PRIVILEGED, "capturescript");
if (IS_ERR(capturescript))
return;
if (kgsl_allocate_global(device, &registers, data_size, 0,
KGSL_MEMDESC_PRIVILEGED, "capturescript_regs")) {
kgsl_free_global(KGSL_DEVICE(adreno_dev), &capturescript);
if (!IS_ERR_OR_NULL(registers))
registers = kgsl_allocate_global(device, data_size, 0,
KGSL_MEMDESC_PRIVILEGED, "capturescript_regs");
if (IS_ERR(registers))
return;
}
/* Build the crash script */
ptr = (uint64_t *) capturescript.hostptr;
ptr = (uint64_t *) capturescript->hostptr;
/* For the registers, program a read command for each pair */
for (j = 0; j < ARRAY_SIZE(a5xx_registers) / 2; j++) {
unsigned int r = REG_PAIR_COUNT(a5xx_registers, j);
*ptr++ = registers.gpuaddr + offset;
*ptr++ = registers->gpuaddr + offset;
*ptr++ = (((uint64_t) a5xx_registers[2 * j]) << 44)
| r;
offset += r * sizeof(unsigned int);
@ -1144,7 +1150,7 @@ void a5xx_crashdump_init(struct adreno_device *adreno_dev)
if (ADRENO_FEATURE(adreno_dev, ADRENO_GPMU)) {
for (j = 0; j < ARRAY_SIZE(a5xx_gpmu_registers) / 2; j++) {
unsigned int r = REG_PAIR_COUNT(a5xx_gpmu_registers, j);
*ptr++ = registers.gpuaddr + offset;
*ptr++ = registers->gpuaddr + offset;
*ptr++ = (((uint64_t) a5xx_gpmu_registers[2 * j]) << 44)
| r;
offset += r * sizeof(unsigned int);

View file

@ -3,7 +3,6 @@
* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*/
#include <linux/firmware.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/soc/qcom/llcc-qcom.h>
@ -114,7 +113,7 @@ static void a6xx_init(struct adreno_device *adreno_dev)
a6xx_crashdump_init(adreno_dev);
kgsl_allocate_global(device, &adreno_dev->pwrup_reglist,
adreno_dev->pwrup_reglist = kgsl_allocate_global(device,
PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED, "powerup_register_list");
}
@ -272,7 +271,7 @@ struct a6xx_reglist_list {
static void a6xx_patch_pwrup_reglist(struct adreno_device *adreno_dev)
{
struct a6xx_reglist_list reglist[3];
void *ptr = adreno_dev->pwrup_reglist.hostptr;
void *ptr = adreno_dev->pwrup_reglist->hostptr;
struct cpu_gpu_lock *lock = ptr;
int items = 0, i, j;
u32 *dest = ptr + sizeof(*lock);
@ -535,7 +534,7 @@ static void a6xx_start(struct adreno_device *adreno_dev)
a6xx_protect_init(adreno_dev);
if (!patch_reglist && (adreno_dev->pwrup_reglist.gpuaddr != 0)) {
if (!patch_reglist && (adreno_dev->pwrup_reglist->gpuaddr != 0)) {
a6xx_patch_pwrup_reglist(adreno_dev);
patch_reglist = true;
}
@ -571,7 +570,7 @@ static int a6xx_microcode_load(struct adreno_device *adreno_dev)
void *zap;
int ret = 0;
gpuaddr = fw->memdesc.gpuaddr;
gpuaddr = fw->memdesc->gpuaddr;
kgsl_regwrite(device, A6XX_CP_SQE_INSTR_BASE_LO,
lower_32_bits(gpuaddr));
kgsl_regwrite(device, A6XX_CP_SQE_INSTR_BASE_HI,
@ -664,7 +663,7 @@ static void _set_ordinals(struct adreno_device *adreno_dev,
*cmds++ = 0x00000002;
if (CP_INIT_MASK & CP_INIT_REGISTER_INIT_LIST_WITH_SPINLOCK) {
uint64_t gpuaddr = adreno_dev->pwrup_reglist.gpuaddr;
uint64_t gpuaddr = adreno_dev->pwrup_reglist->gpuaddr;
*cmds++ = lower_32_bits(gpuaddr);
*cmds++ = upper_32_bits(gpuaddr);
@ -703,7 +702,7 @@ static int a6xx_send_cp_init(struct adreno_device *adreno_dev,
adreno_spin_idle_debug(adreno_dev,
"CP initialization failed to idle\n");
kgsl_sharedmem_writel(device, &device->scratch,
kgsl_sharedmem_writel(device, device->scratch,
SCRATCH_RPTR_OFFSET(rb->id), 0);
rb->wptr = 0;
rb->_wptr = 0;
@ -729,7 +728,7 @@ static int _preemption_init(struct adreno_device *adreno_dev,
*cmds++ = cp_type7_packet(CP_SET_PSEUDO_REGISTER, 6);
*cmds++ = 1;
cmds += cp_gpuaddr(adreno_dev, cmds,
rb->preemption_desc.gpuaddr);
rb->preemption_desc->gpuaddr);
*cmds++ = 2;
cmds += cp_gpuaddr(adreno_dev, cmds,
@ -816,7 +815,7 @@ static int a6xx_rb_start(struct adreno_device *adreno_dev)
A6XX_CP_RB_CNTL_DEFAULT);
adreno_writereg64(adreno_dev, ADRENO_REG_CP_RB_BASE,
ADRENO_REG_CP_RB_BASE_HI, rb->buffer_desc.gpuaddr);
ADRENO_REG_CP_RB_BASE_HI, rb->buffer_desc->gpuaddr);
ret = a6xx_microcode_load(adreno_dev);
if (ret)
@ -904,34 +903,6 @@ unsigned int a6xx_set_marker(
return 2;
}
static int _load_firmware(struct kgsl_device *device, const char *fwfile,
struct adreno_firmware *firmware)
{
const struct firmware *fw = NULL;
int ret;
ret = request_firmware(&fw, fwfile, device->dev);
if (ret) {
dev_err(device->dev, "request_firmware(%s) failed: %d\n",
fwfile, ret);
return ret;
}
ret = kgsl_allocate_global(device, &firmware->memdesc, fw->size - 4,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_UCODE,
"ucode");
if (!ret) {
memcpy(firmware->memdesc.hostptr, &fw->data[4], fw->size - 4);
firmware->size = (fw->size - 4) / sizeof(uint32_t);
firmware->version = *(unsigned int *)&fw->data[4];
}
release_firmware(fw);
return ret;
}
/*
* a6xx_gpu_keepalive() - GMU reg write to request GPU stays on
* @adreno_dev: Pointer to the adreno device that has the GMU
@ -966,18 +937,10 @@ static bool a6xx_hw_isidle(struct adreno_device *adreno_dev)
*/
static int a6xx_microcode_read(struct adreno_device *adreno_dev)
{
int ret;
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_firmware *sqe_fw = ADRENO_FW(adreno_dev, ADRENO_FW_SQE);
const struct adreno_a6xx_core *a6xx_core = to_a6xx_core(adreno_dev);
if (sqe_fw->memdesc.hostptr == NULL) {
ret = _load_firmware(device, a6xx_core->sqefw_name, sqe_fw);
if (ret)
return ret;
}
return 0;
return adreno_get_firmware(adreno_dev, a6xx_core->sqefw_name, sqe_fw);
}
static int a6xx_soft_reset(struct adreno_device *adreno_dev)
@ -2480,7 +2443,7 @@ static void cpu_gpu_unlock(struct cpu_gpu_lock *lock)
static int a6xx_perfcounter_update(struct adreno_device *adreno_dev,
struct adreno_perfcount_register *reg, bool update_reg)
{
void *ptr = adreno_dev->pwrup_reglist.hostptr;
void *ptr = adreno_dev->pwrup_reglist->hostptr;
struct cpu_gpu_lock *lock = ptr;
u32 *data = ptr + sizeof(*lock);
int i, offset = 0;

View file

@ -280,23 +280,23 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
* preemption_desc at init time, so no need to check if
* sharedmem accesses to these memdescs succeed.
*/
kgsl_sharedmem_readq(&next->pagetable_desc, &ttbr0,
kgsl_sharedmem_readq(next->pagetable_desc, &ttbr0,
PT_INFO_OFFSET(ttbr0));
kgsl_sharedmem_readl(&next->pagetable_desc, &contextidr,
kgsl_sharedmem_readl(next->pagetable_desc, &contextidr,
PT_INFO_OFFSET(contextidr));
kgsl_sharedmem_writel(device, &next->preemption_desc,
kgsl_sharedmem_writel(device, next->preemption_desc,
PREEMPT_RECORD(wptr), next->wptr);
spin_unlock_irqrestore(&next->preempt_lock, flags);
/* And write it to the smmu info */
kgsl_sharedmem_writeq(device, &iommu->smmu_info,
kgsl_sharedmem_writeq(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(ttbr0), ttbr0);
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(context_idr), contextidr);
kgsl_sharedmem_readq(&device->scratch, &gpuaddr,
kgsl_sharedmem_readq(device->scratch, &gpuaddr,
SCRATCH_PREEMPTION_CTXT_RESTORE_ADDR_OFFSET(next->id));
/*
@ -321,7 +321,7 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
*/
if (adreno_gmu_fenced_write(adreno_dev,
ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR_LO,
lower_32_bits(next->preemption_desc.gpuaddr),
lower_32_bits(next->preemption_desc->gpuaddr),
FENCE_STATUS_WRITEDROPPED1_MASK))
goto err;
@ -339,7 +339,7 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
if (adreno_gmu_fenced_write(adreno_dev,
ADRENO_REG_CP_CONTEXT_SWITCH_PRIV_NON_SECURE_RESTORE_ADDR_HI,
upper_32_bits(next->preemption_desc.gpuaddr),
upper_32_bits(next->preemption_desc->gpuaddr),
FENCE_STATUS_WRITEDROPPED1_MASK))
goto err;
@ -494,7 +494,7 @@ unsigned int a6xx_preemption_pre_ibsubmit(
cmds += cp_gpuaddr(adreno_dev, cmds, 0x0);
*cmds++ = SET_PSEUDO_REGISTER_SAVE_REGISTER_PRIV_NON_SECURE_SAVE_ADDR;
cmds += cp_gpuaddr(adreno_dev, cmds, rb->preemption_desc.gpuaddr);
cmds += cp_gpuaddr(adreno_dev, cmds, rb->preemption_desc->gpuaddr);
*cmds++ = SET_PSEUDO_REGISTER_SAVE_REGISTER_PRIV_SECURE_SAVE_ADDR;
cmds += cp_gpuaddr(adreno_dev, cmds,
@ -515,7 +515,7 @@ unsigned int a6xx_preemption_pre_ibsubmit(
*/
*cmds++ = SET_PSEUDO_REGISTER_SAVE_REGISTER_COUNTER;
cmds += cp_gpuaddr(adreno_dev, cmds,
rb->perfcounter_save_restore_desc.gpuaddr);
rb->perfcounter_save_restore_desc->gpuaddr);
if (context) {
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@ -573,31 +573,31 @@ void a6xx_preemption_start(struct adreno_device *adreno_dev)
adreno_set_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE);
/* smmu_info is allocated and mapped in a6xx_preemption_iommu_init */
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(magic), A6XX_CP_SMMU_INFO_MAGIC_REF);
kgsl_sharedmem_writeq(device, &iommu->smmu_info,
kgsl_sharedmem_writeq(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(ttbr0), MMU_DEFAULT_TTBR0(device));
/* The CP doesn't use the asid record, so poison it */
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(asid), 0xDECAFBAD);
kgsl_sharedmem_writel(device, &iommu->smmu_info,
kgsl_sharedmem_writel(device, iommu->smmu_info,
PREEMPT_SMMU_RECORD(context_idr),
MMU_DEFAULT_CONTEXTIDR(device));
adreno_writereg64(adreno_dev,
ADRENO_REG_CP_CONTEXT_SWITCH_SMMU_INFO_LO,
ADRENO_REG_CP_CONTEXT_SWITCH_SMMU_INFO_HI,
iommu->smmu_info.gpuaddr);
iommu->smmu_info->gpuaddr);
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
/*
* preemption_desc is allocated and mapped at init time,
* so no need to check sharedmem_writel return value
*/
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(rptr), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(wptr), 0);
adreno_ringbuffer_set_pagetable(rb,
@ -611,11 +611,12 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev,
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
int ret;
ret = kgsl_allocate_global(device, &rb->preemption_desc,
A6XX_CP_CTXRECORD_SIZE_IN_BYTES, 0, KGSL_MEMDESC_PRIVILEGED,
"preemption_desc");
if (ret)
return ret;
if (IS_ERR_OR_NULL(rb->preemption_desc))
rb->preemption_desc = kgsl_allocate_global(device,
A6XX_CP_CTXRECORD_SIZE_IN_BYTES, 0,
KGSL_MEMDESC_PRIVILEGED, "preemption_desc");
if (IS_ERR(rb->preemption_desc))
return PTR_ERR(rb->preemption_desc);
ret = kgsl_allocate_user(device, &rb->secure_preemption_desc,
A6XX_CP_CTXRECORD_SIZE_IN_BYTES,
@ -628,30 +629,33 @@ static int a6xx_preemption_ringbuffer_init(struct adreno_device *adreno_dev,
if (ret)
return ret;
ret = kgsl_allocate_global(device, &rb->perfcounter_save_restore_desc,
A6XX_CP_PERFCOUNTER_SAVE_RESTORE_SIZE, 0,
KGSL_MEMDESC_PRIVILEGED, "perfcounter_save_restore_desc");
if (ret)
return ret;
if (IS_ERR_OR_NULL(rb->perfcounter_save_restore_desc))
rb->perfcounter_save_restore_desc = kgsl_allocate_global(device,
A6XX_CP_PERFCOUNTER_SAVE_RESTORE_SIZE, 0,
KGSL_MEMDESC_PRIVILEGED,
"perfcounter_save_restore_desc");
kgsl_sharedmem_writel(device, &rb->preemption_desc,
if (IS_ERR(rb->perfcounter_save_restore_desc))
return PTR_ERR(rb->perfcounter_save_restore_desc);
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(magic), A6XX_CP_CTXRECORD_MAGIC_REF);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(info), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(data), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(cntl), A6XX_CP_RB_CNTL_DEFAULT);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(rptr), 0);
kgsl_sharedmem_writel(device, &rb->preemption_desc,
kgsl_sharedmem_writel(device, rb->preemption_desc,
PREEMPT_RECORD(wptr), 0);
kgsl_sharedmem_writeq(device, &rb->preemption_desc,
kgsl_sharedmem_writeq(device, rb->preemption_desc,
PREEMPT_RECORD(rptr_addr), SCRATCH_RPTR_GPU_ADDR(device,
rb->id));
kgsl_sharedmem_writeq(device, &rb->preemption_desc,
PREEMPT_RECORD(rbase), rb->buffer_desc.gpuaddr);
kgsl_sharedmem_writeq(device, &rb->preemption_desc,
kgsl_sharedmem_writeq(device, rb->preemption_desc,
PREEMPT_RECORD(rbase), rb->buffer_desc->gpuaddr);
kgsl_sharedmem_writeq(device, rb->preemption_desc,
PREEMPT_RECORD(counter), 0);
return 0;
@ -664,27 +668,18 @@ static int a6xx_preemption_iommu_init(struct adreno_device *adreno_dev)
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
/* Allocate mem for storing preemption smmu record */
return kgsl_allocate_global(device, &iommu->smmu_info, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED,
"smmu_info");
}
if (IS_ERR_OR_NULL(iommu->smmu_info))
iommu->smmu_info = kgsl_allocate_global(device, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, KGSL_MEMDESC_PRIVILEGED,
"smmu_info");
static void a6xx_preemption_iommu_close(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
kgsl_free_global(device, &iommu->smmu_info);
return PTR_ERR_OR_ZERO(iommu->smmu_info);
}
#else
static int a6xx_preemption_iommu_init(struct adreno_device *adreno_dev)
{
return -ENODEV;
}
static void a6xx_preemption_iommu_close(struct adreno_device *adreno_dev)
{
}
#endif
static void _preemption_close(struct adreno_device *adreno_dev)
@ -695,11 +690,8 @@ static void _preemption_close(struct adreno_device *adreno_dev)
unsigned int i;
del_timer(&preempt->timer);
a6xx_preemption_iommu_close(adreno_dev);
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
kgsl_free_global(device, &rb->preemption_desc);
kgsl_free_global(device, &rb->perfcounter_save_restore_desc);
kgsl_iommu_unmap_global_secure_pt_entry(device,
&rb->secure_preemption_desc);
kgsl_sharedmem_free(&rb->secure_preemption_desc);

View file

@ -621,8 +621,8 @@ static struct a6xx_shader_block a6xx_shader_blocks[] = {
{A6XX_HLSQ_INDIRECT_META, 0x40,}
};
static struct kgsl_memdesc a6xx_capturescript;
static struct kgsl_memdesc a6xx_crashdump_registers;
static struct kgsl_memdesc *a6xx_capturescript;
static struct kgsl_memdesc *a6xx_crashdump_registers;
static bool crash_dump_valid;
static struct reg_list {
@ -675,7 +675,7 @@ static size_t a6xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
return 0;
}
src = (unsigned int *)(a6xx_crashdump_registers.hostptr + regs->offset);
src = a6xx_crashdump_registers->hostptr + regs->offset;
remain -= sizeof(*header);
for (j = 0; j < regs->count; j++) {
@ -778,7 +778,7 @@ static size_t a6xx_snapshot_shader_memory(struct kgsl_device *device,
header->index = info->bank;
header->size = block->sz;
memcpy(data, a6xx_crashdump_registers.hostptr + info->offset,
memcpy(data, a6xx_crashdump_registers->hostptr + info->offset,
block->sz * sizeof(unsigned int));
return SHADER_SECTION_SZ(block->sz);
@ -935,8 +935,8 @@ static size_t a6xx_snapshot_cluster_dbgahb(struct kgsl_device *device, u8 *buf,
header->ctxt_id = info->ctxt_id;
header->cluster_id = cluster->id;
src = (unsigned int *)(a6xx_crashdump_registers.hostptr +
(header->ctxt_id ? cluster->offset1 : cluster->offset0));
src = a6xx_crashdump_registers->hostptr +
(header->ctxt_id ? cluster->offset1 : cluster->offset0);
for (i = 0; i < cluster->num_sets; i++) {
unsigned int start;
@ -1034,7 +1034,7 @@ static size_t a6xx_snapshot_non_ctx_dbgahb(struct kgsl_device *device, u8 *buf,
remain -= sizeof(*header);
src = (unsigned int *)(a6xx_crashdump_registers.hostptr + regs->offset);
src = a6xx_crashdump_registers->hostptr + regs->offset;
for (i = 0; i < regs->num_sets; i++) {
unsigned int start;
@ -1175,8 +1175,8 @@ static size_t a6xx_snapshot_mvc(struct kgsl_device *device, u8 *buf,
header->ctxt_id = info->ctxt_id;
header->cluster_id = cluster->id;
src = (unsigned int *)(a6xx_crashdump_registers.hostptr +
(header->ctxt_id ? cluster->offset1 : cluster->offset0));
src = a6xx_crashdump_registers->hostptr +
(header->ctxt_id ? cluster->offset1 : cluster->offset0);
for (i = 0; i < cluster->num_sets; i++) {
start = cluster->regs[2 * i];
@ -1600,8 +1600,9 @@ static void _a6xx_do_crashdump(struct kgsl_device *device)
if (!device->snapshot_crashdumper)
return;
if (a6xx_capturescript.gpuaddr == 0 ||
a6xx_crashdump_registers.gpuaddr == 0)
if (IS_ERR_OR_NULL(a6xx_capturescript) ||
IS_ERR_OR_NULL(a6xx_crashdump_registers))
return;
/* IF the SMMU is stalled we cannot do a crash dump */
@ -1614,9 +1615,9 @@ static void _a6xx_do_crashdump(struct kgsl_device *device)
kgsl_regwrite(device, A6XX_CP_MISC_CNTL, 1);
kgsl_regwrite(device, A6XX_CP_CRASH_SCRIPT_BASE_LO,
lower_32_bits(a6xx_capturescript.gpuaddr));
lower_32_bits(a6xx_capturescript->gpuaddr));
kgsl_regwrite(device, A6XX_CP_CRASH_SCRIPT_BASE_HI,
upper_32_bits(a6xx_capturescript.gpuaddr));
upper_32_bits(a6xx_capturescript->gpuaddr));
kgsl_regwrite(device, A6XX_CP_CRASH_DUMP_CNTL, 1);
wait_time = jiffies + msecs_to_jiffies(CP_CRASH_DUMPER_TIMEOUT);
@ -1927,7 +1928,7 @@ static int _a6xx_crashdump_init_mvc(struct adreno_device *adreno_dev,
for (k = 0; k < cluster->num_sets; k++) {
count = REG_PAIR_COUNT(cluster->regs, k);
ptr[qwords++] =
a6xx_crashdump_registers.gpuaddr + *offset;
a6xx_crashdump_registers->gpuaddr + *offset;
ptr[qwords++] =
(((uint64_t)cluster->regs[2 * k]) << 44) |
count;
@ -1955,7 +1956,7 @@ static int _a6xx_crashdump_init_shader(struct a6xx_shader_block *block,
(1 << 21) | 1;
/* Read all the data in one chunk */
ptr[qwords++] = a6xx_crashdump_registers.gpuaddr + *offset;
ptr[qwords++] = a6xx_crashdump_registers->gpuaddr + *offset;
ptr[qwords++] =
(((uint64_t) A6XX_HLSQ_DBG_AHB_READ_APERTURE << 44)) |
block->sz;
@ -1998,7 +1999,7 @@ static int _a6xx_crashdump_init_ctx_dbgahb(uint64_t *ptr, uint64_t *offset)
count = REG_PAIR_COUNT(cluster->regs, k);
ptr[qwords++] =
a6xx_crashdump_registers.gpuaddr + *offset;
a6xx_crashdump_registers->gpuaddr + *offset;
ptr[qwords++] =
(((uint64_t)(A6XX_HLSQ_DBG_AHB_READ_APERTURE +
start - cluster->regbase / 4) << 44)) |
@ -2033,7 +2034,7 @@ static int _a6xx_crashdump_init_non_ctx_dbgahb(uint64_t *ptr, uint64_t *offset)
count = REG_PAIR_COUNT(regs->regs, k);
ptr[qwords++] =
a6xx_crashdump_registers.gpuaddr + *offset;
a6xx_crashdump_registers->gpuaddr + *offset;
ptr[qwords++] =
(((uint64_t)(A6XX_HLSQ_DBG_AHB_READ_APERTURE +
start - regs->regbase / 4) << 44)) |
@ -2054,8 +2055,8 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev)
uint64_t *ptr;
uint64_t offset = 0;
if (a6xx_capturescript.gpuaddr != 0 &&
a6xx_crashdump_registers.gpuaddr != 0)
if (!IS_ERR_OR_NULL(a6xx_capturescript) &&
!IS_ERR_OR_NULL(a6xx_crashdump_registers))
return;
/*
@ -2163,20 +2164,25 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev)
/* Now allocate the script and data buffers */
/* The script buffers needs 2 extra qwords on the end */
if (kgsl_allocate_global(device, &a6xx_capturescript,
script_size + 16, KGSL_MEMFLAGS_GPUREADONLY,
KGSL_MEMDESC_PRIVILEGED, "capturescript"))
if (IS_ERR_OR_NULL(a6xx_capturescript))
a6xx_capturescript = kgsl_allocate_global(device,
script_size + 16, KGSL_MEMFLAGS_GPUREADONLY,
KGSL_MEMDESC_PRIVILEGED, "capturescript");
if (IS_ERR(a6xx_capturescript))
return;
if (kgsl_allocate_global(device, &a6xx_crashdump_registers, data_size,
0, KGSL_MEMDESC_PRIVILEGED, "capturescript_regs")) {
kgsl_free_global(KGSL_DEVICE(adreno_dev), &a6xx_capturescript);
if (IS_ERR_OR_NULL(a6xx_crashdump_registers))
a6xx_crashdump_registers = kgsl_allocate_global(device,
data_size, 0, KGSL_MEMDESC_PRIVILEGED,
"capturescript_regs");
if (IS_ERR(a6xx_crashdump_registers))
return;
}
/* Build the crash script */
ptr = (uint64_t *)a6xx_capturescript.hostptr;
ptr = (uint64_t *)a6xx_capturescript->hostptr;
/* For the registers, program a read command for each pair */
for (i = 0; i < ARRAY_SIZE(a6xx_reg_list); i++) {
@ -2193,7 +2199,7 @@ void a6xx_crashdump_init(struct adreno_device *adreno_dev)
for (j = 0; j < regs->count; j++) {
unsigned int r = REG_PAIR_COUNT(regs->regs, j);
*ptr++ = a6xx_crashdump_registers.gpuaddr + offset;
*ptr++ = a6xx_crashdump_registers->gpuaddr + offset;
*ptr++ = (((uint64_t) regs->regs[2 * j]) << 44) | r;
offset += r * sizeof(unsigned int);
}

View file

@ -50,7 +50,7 @@ int adreno_getproperty_compat(struct kgsl_device *device,
break;
}
memset(&shadowprop, 0, sizeof(shadowprop));
if (device->memstore.hostptr) {
if (device->memstore->hostptr) {
/*
* NOTE: with mmu enabled, gpuaddr doesn't mean
* anything to mmap().
@ -58,10 +58,10 @@ int adreno_getproperty_compat(struct kgsl_device *device,
* (because legacy) and the memstore gpuaddr is
* 64 bit. Cast the memstore gpuaddr to uint32.
*/
shadowprop.gpuaddr =
(unsigned int) device->memstore.gpuaddr;
shadowprop.gpuaddr = (unsigned int)
device->memstore->gpuaddr;
shadowprop.size =
(unsigned int) device->memstore.size;
(unsigned int) device->memstore->size;
/*
* GSL needs this to be set, even if it
* appears to be meaningless

View file

@ -268,11 +268,11 @@ static void _retire_timestamp(struct kgsl_drawobj *drawobj)
* Write the start and end timestamp to the memstore to keep the
* accounting sane
*/
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, soptimestamp),
drawobj->timestamp);
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp),
drawobj->timestamp);
@ -2176,7 +2176,7 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
adreno_dispatch_retire_drawqueue(adreno_dev,
&(rb->dispatch_q));
/* Select the active dispatch_q */
if (base == rb->buffer_desc.gpuaddr) {
if (base == rb->buffer_desc->gpuaddr) {
dispatch_q = &(rb->dispatch_q);
hung_rb = rb;
if (adreno_dev->cur_rb != hung_rb) {
@ -2224,11 +2224,11 @@ static int dispatcher_do_fault(struct adreno_device *adreno_dev)
*/
if (hung_rb != NULL) {
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
MEMSTORE_RB_OFFSET(hung_rb, soptimestamp),
hung_rb->timestamp);
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
MEMSTORE_RB_OFFSET(hung_rb, eoptimestamp),
hung_rb->timestamp);
@ -2306,7 +2306,7 @@ static void _print_recovery(struct kgsl_device *device,
static void cmdobj_profile_ticks(struct adreno_device *adreno_dev,
struct kgsl_drawobj_cmd *cmdobj, uint64_t *start, uint64_t *retire)
{
void *ptr = adreno_dev->profile_buffer.hostptr;
void *ptr = adreno_dev->profile_buffer->hostptr;
struct adreno_drawobj_profile_entry *entry;
entry = (struct adreno_drawobj_profile_entry *)

View file

@ -268,11 +268,11 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device,
* set the timestamp to the last value since the context is invalidated
* and we want the pending events for this context to go away
*/
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, soptimestamp),
drawctxt->timestamp);
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp),
drawctxt->timestamp);
@ -402,10 +402,10 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
return ERR_PTR(ret);
}
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
0);
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
0);
@ -530,11 +530,11 @@ void adreno_drawctxt_detach(struct kgsl_context *context)
return;
}
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, soptimestamp),
drawctxt->timestamp);
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp),
drawctxt->timestamp);

View file

@ -160,7 +160,7 @@ static long adreno_ioctl_preemption_counters_query(
levels_to_copy = gpudev->num_prio_levels;
if (copy_to_user(u64_to_user_ptr(read->counters),
adreno_dev->preempt.counters.hostptr,
adreno_dev->preempt.counters->hostptr,
levels_to_copy * size_level))
return -EFAULT;

View file

@ -216,7 +216,7 @@ static unsigned int _adreno_iommu_set_pt_v2_a5xx(struct kgsl_device *device,
*cmds++ = contextidr;
*cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 4, 1);
cmds += cp_gpuaddr(adreno_dev, cmds, (rb->pagetable_desc.gpuaddr +
cmds += cp_gpuaddr(adreno_dev, cmds, (rb->pagetable_desc->gpuaddr +
PT_INFO_OFFSET(ttbr0)));
*cmds++ = lower_32_bits(ttbr0);
*cmds++ = upper_32_bits(ttbr0);
@ -250,7 +250,7 @@ static unsigned int _adreno_iommu_set_pt_v2_a6xx(struct kgsl_device *device,
*cmds++ = cb_num;
*cmds++ = cp_mem_packet(adreno_dev, CP_MEM_WRITE, 4, 1);
cmds += cp_gpuaddr(adreno_dev, cmds, (rb->pagetable_desc.gpuaddr +
cmds += cp_gpuaddr(adreno_dev, cmds, (rb->pagetable_desc->gpuaddr +
PT_INFO_OFFSET(ttbr0)));
*cmds++ = lower_32_bits(ttbr0);
*cmds++ = upper_32_bits(ttbr0);
@ -296,7 +296,7 @@ unsigned int adreno_iommu_set_pt_generate_cmds(
cmds += cp_wait_for_me(adreno_dev, cmds);
*cmds++ = cp_mem_packet(adreno_dev, CP_INDIRECT_BUFFER_PFE, 2, 1);
cmds += cp_gpuaddr(adreno_dev, cmds,
iommu->setstate.gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET);
iommu->setstate->gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET);
*cmds++ = 2;
cmds += cp_wait_for_idle(adreno_dev, cmds);
@ -445,7 +445,7 @@ void adreno_iommu_init(struct adreno_device *adreno_dev)
* pagetables in-stream
*/
kgsl_sharedmem_writel(device, &iommu->setstate,
kgsl_sharedmem_writel(device, iommu->setstate,
KGSL_IOMMU_SETSTATE_NOP_OFFSET,
cp_packet(adreno_dev, CP_NOP, 1));

View file

@ -111,11 +111,11 @@ static int _build_pre_ib_cmds(struct adreno_device *adreno_dev,
struct adreno_profile_assigns_list *entry;
unsigned int *start, *ibcmds;
unsigned int count = profile->assignment_count;
uint64_t gpuaddr = profile->shared_buffer.gpuaddr;
uint64_t gpuaddr = profile->shared_buffer->gpuaddr;
unsigned int ib_offset = head + SIZE_DATA(count);
unsigned int data_offset = head * sizeof(unsigned int);
ibcmds = ib_offset + ((unsigned int *) profile->shared_buffer.hostptr);
ibcmds = ib_offset + ((unsigned int *) profile->shared_buffer->hostptr);
start = ibcmds;
ibcmds += cp_identifier(adreno_dev, ibcmds, START_PROFILE_IDENTIFIER);
@ -156,7 +156,7 @@ static int _build_pre_ib_cmds(struct adreno_device *adreno_dev,
ibcmds += cp_identifier(adreno_dev, ibcmds, END_PROFILE_IDENTIFIER);
return _create_ib_ref(adreno_dev, &profile->shared_buffer, rbcmds,
return _create_ib_ref(adreno_dev, profile->shared_buffer, rbcmds,
ibcmds - start, ib_offset * sizeof(unsigned int));
}
@ -167,11 +167,11 @@ static int _build_post_ib_cmds(struct adreno_device *adreno_dev,
struct adreno_profile_assigns_list *entry;
unsigned int *start, *ibcmds;
unsigned int count = profile->assignment_count;
uint64_t gpuaddr = profile->shared_buffer.gpuaddr;
uint64_t gpuaddr = profile->shared_buffer->gpuaddr;
unsigned int ib_offset = head + SIZE_DATA(count) + SIZE_PREIB(count);
unsigned int data_offset = head * sizeof(unsigned int);
ibcmds = ib_offset + ((unsigned int *) profile->shared_buffer.hostptr);
ibcmds = ib_offset + ((unsigned int *) profile->shared_buffer->hostptr);
start = ibcmds;
/* start of profile identifier */
@ -195,14 +195,14 @@ static int _build_post_ib_cmds(struct adreno_device *adreno_dev,
/* end of profile identifier */
ibcmds += cp_identifier(adreno_dev, ibcmds, END_PROFILE_IDENTIFIER);
return _create_ib_ref(adreno_dev, &profile->shared_buffer, rbcmds,
return _create_ib_ref(adreno_dev, profile->shared_buffer, rbcmds,
ibcmds - start, ib_offset * sizeof(unsigned int));
}
static bool shared_buf_empty(struct adreno_profile *profile)
{
if (profile->shared_buffer.hostptr == NULL ||
profile->shared_buffer.size == 0)
if (profile->shared_buffer->hostptr == NULL ||
profile->shared_buffer->size == 0)
return true;
if (profile->shared_head == profile->shared_tail)
@ -319,7 +319,7 @@ static bool results_available(struct adreno_device *adreno_dev,
unsigned int global_eop;
unsigned int off = profile->shared_tail;
unsigned int *shared_ptr = (unsigned int *)
profile->shared_buffer.hostptr;
profile->shared_buffer->hostptr;
unsigned int ts, cnt;
int ts_cmp;
@ -362,7 +362,7 @@ static void transfer_results(struct adreno_profile *profile,
{
unsigned int buf_off;
unsigned int ts, cnt, ctxt_id, pid, tid, client_type;
unsigned int *ptr = (unsigned int *) profile->shared_buffer.hostptr;
unsigned int *ptr = (unsigned int *) profile->shared_buffer->hostptr;
unsigned int *log_ptr, *log_base;
struct adreno_profile_assigns_list *assigns_list;
int i, tmp_tail;
@ -1017,17 +1017,15 @@ void adreno_profile_init(struct adreno_device *adreno_dev)
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_profile *profile = &adreno_dev->profile;
struct dentry *profile_dir;
int ret;
profile->enabled = false;
/* allocate shared_buffer, which includes pre_ib and post_ib */
profile->shared_size = ADRENO_PROFILE_SHARED_BUF_SIZE_DWORDS;
ret = kgsl_allocate_global(device, &profile->shared_buffer,
profile->shared_buffer = kgsl_allocate_global(device,
profile->shared_size * sizeof(unsigned int),
0, 0, "profile");
if (ret) {
if (IS_ERR(profile->shared_buffer)) {
profile->shared_size = 0;
return;
}
@ -1061,7 +1059,6 @@ void adreno_profile_close(struct adreno_device *adreno_dev)
profile->log_tail = NULL;
profile->shared_head = 0;
profile->shared_tail = 0;
kgsl_free_global(KGSL_DEVICE(adreno_dev), &profile->shared_buffer);
profile->shared_size = 0;
profile->assignment_count = 0;
@ -1128,7 +1125,7 @@ void adreno_profile_preib_processing(struct adreno_device *adreno_dev,
/* zero out the counter area of shared_buffer entry_head */
shared_ptr = entry_head + ((unsigned int *)
profile->shared_buffer.hostptr);
profile->shared_buffer->hostptr);
memset(shared_ptr, 0, SIZE_SHARED_ENTRY(count) * sizeof(unsigned int));
/* reserve space for the pre ib shared buffer */

View file

@ -39,7 +39,7 @@ struct adreno_profile {
* pre_ib entry N
* post_ib entry N
*/
struct kgsl_memdesc shared_buffer;
struct kgsl_memdesc *shared_buffer;
unsigned int shared_head;
unsigned int shared_tail;
unsigned int shared_size;

View file

@ -17,11 +17,11 @@
#define RB_HOSTPTR(_rb, _pos) \
((unsigned int *) ((_rb)->buffer_desc.hostptr + \
((unsigned int *) ((_rb)->buffer_desc->hostptr + \
((_pos) * sizeof(unsigned int))))
#define RB_GPUADDR(_rb, _pos) \
((_rb)->buffer_desc.gpuaddr + ((_pos) * sizeof(unsigned int)))
((_rb)->buffer_desc->gpuaddr + ((_pos) * sizeof(unsigned int)))
static inline bool is_internal_cmds(unsigned int flags)
{
@ -224,10 +224,10 @@ int adreno_ringbuffer_start(struct adreno_device *adreno_dev)
/* Setup the ringbuffers state before we start */
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
kgsl_sharedmem_set(device, &(rb->buffer_desc),
kgsl_sharedmem_set(device, rb->buffer_desc,
0, 0xAA, KGSL_RB_SIZE);
if (!adreno_is_a3xx(adreno_dev))
kgsl_sharedmem_writel(device, &device->scratch,
kgsl_sharedmem_writel(device, device->scratch,
SCRATCH_RPTR_OFFSET(rb->id), 0);
rb->wptr = 0;
rb->_wptr = 0;
@ -258,8 +258,8 @@ static int _rb_readtimestamp(struct kgsl_device *device,
static int _adreno_ringbuffer_probe(struct adreno_device *adreno_dev,
int id)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffers[id];
int ret;
unsigned int priv = 0;
rb->id = id;
@ -275,21 +275,22 @@ static int _adreno_ringbuffer_probe(struct adreno_device *adreno_dev,
* Allocate mem for storing RB pagetables and commands to
* switch pagetable
*/
ret = kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->pagetable_desc,
PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED, "pagetable_desc");
if (ret)
return ret;
rb->pagetable_desc = kgsl_allocate_global(device, PAGE_SIZE,
0, KGSL_MEMDESC_PRIVILEGED, "pagetable_desc");
if (IS_ERR(rb->pagetable_desc))
return PTR_ERR(rb->pagetable_desc);
/* allocate a chunk of memory to create user profiling IB1s */
kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->profile_desc,
PAGE_SIZE, KGSL_MEMFLAGS_GPUREADONLY, 0, "profile_desc");
rb->profile_desc = kgsl_allocate_global(device, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, 0, "profile_desc");
/* For targets that support it, make the ringbuffer privileged */
if (ADRENO_FEATURE(adreno_dev, ADRENO_APRIV))
priv |= KGSL_MEMDESC_PRIVILEGED;
return kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->buffer_desc,
KGSL_RB_SIZE, KGSL_MEMFLAGS_GPUREADONLY, priv, "ringbuffer");
rb->buffer_desc = kgsl_allocate_global(device, KGSL_RB_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, priv, "ringbuffer");
return PTR_ERR_OR_ZERO(rb->buffer_desc);
}
int adreno_ringbuffer_probe(struct adreno_device *adreno_dev)
@ -306,10 +307,11 @@ int adreno_ringbuffer_probe(struct adreno_device *adreno_dev)
if (ADRENO_FEATURE(adreno_dev, ADRENO_APRIV))
priv |= KGSL_MEMDESC_PRIVILEGED;
status = kgsl_allocate_global(device, &device->scratch,
PAGE_SIZE, 0, priv, "scratch");
if (status != 0)
return status;
device->scratch = kgsl_allocate_global(device,
PAGE_SIZE, 0, KGSL_MEMDESC_RANDOM, "scratch");
if (IS_ERR(device->scratch))
return PTR_ERR(device->scratch);
}
if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
@ -341,30 +343,16 @@ int adreno_ringbuffer_probe(struct adreno_device *adreno_dev)
return status;
}
static void _adreno_ringbuffer_close(struct adreno_device *adreno_dev,
struct adreno_ringbuffer *rb)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
kgsl_free_global(device, &rb->pagetable_desc);
kgsl_free_global(device, &rb->profile_desc);
kgsl_free_global(device, &rb->buffer_desc);
kgsl_del_event_group(&rb->events);
memset(rb, 0, sizeof(struct adreno_ringbuffer));
}
void adreno_ringbuffer_close(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
struct adreno_ringbuffer *rb;
int i;
if (!adreno_is_a3xx(adreno_dev))
kgsl_free_global(device, &device->scratch);
FOR_EACH_RINGBUFFER(adreno_dev, rb, i)
_adreno_ringbuffer_close(adreno_dev, rb);
FOR_EACH_RINGBUFFER(adreno_dev, rb, i) {
kgsl_del_event_group(&rb->events);
memset(rb, 0, sizeof(*rb));
}
if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
if (gpudev->preemption_close)
@ -577,7 +565,7 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
*ringcmds++ = cp_mem_packet(adreno_dev,
CP_INDIRECT_BUFFER_PFE, 2, 1);
ringcmds += cp_gpuaddr(adreno_dev, ringcmds,
adreno_dev->pwron_fixup.gpuaddr);
adreno_dev->pwron_fixup->gpuaddr);
*ringcmds++ = adreno_dev->pwron_fixup_dwords;
/* Re-enable protected mode */
@ -842,12 +830,12 @@ static int set_user_profiling(struct adreno_device *adreno_dev,
u64 ib_gpuaddr;
u32 *ib;
if (!rb->profile_desc.hostptr)
if (!rb->profile_desc->hostptr)
return 0;
ib = ((u32 *) rb->profile_desc.hostptr) +
ib = ((u32 *) rb->profile_desc->hostptr) +
(rb->profile_index * PROFILE_IB_DWORDS);
ib_gpuaddr = rb->profile_desc.gpuaddr +
ib_gpuaddr = rb->profile_desc->gpuaddr +
(rb->profile_index * (PROFILE_IB_DWORDS << 2));
dwords = _get_alwayson_counter(adreno_dev, ib, gpuaddr);
@ -1012,7 +1000,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
if (kernel_profiling) {
cmds += _get_alwayson_counter(adreno_dev, cmds,
adreno_dev->profile_buffer.gpuaddr +
adreno_dev->profile_buffer->gpuaddr +
ADRENO_DRAWOBJ_PROFILE_OFFSET(cmdobj->profile_index,
started));
}
@ -1068,7 +1056,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
if (kernel_profiling) {
cmds += _get_alwayson_counter(adreno_dev, cmds,
adreno_dev->profile_buffer.gpuaddr +
adreno_dev->profile_buffer->gpuaddr +
ADRENO_DRAWOBJ_PROFILE_OFFSET(cmdobj->profile_index,
retired));
}

View file

@ -101,7 +101,7 @@ struct adreno_ringbuffer_pagetable_info {
*/
struct adreno_ringbuffer {
uint32_t flags;
struct kgsl_memdesc buffer_desc;
struct kgsl_memdesc *buffer_desc;
unsigned int _wptr;
unsigned int wptr;
unsigned int last_wptr;
@ -110,10 +110,10 @@ struct adreno_ringbuffer {
unsigned int timestamp;
struct kgsl_event_group events;
struct adreno_context *drawctxt_active;
struct kgsl_memdesc preemption_desc;
struct kgsl_memdesc *preemption_desc;
struct kgsl_memdesc secure_preemption_desc;
struct kgsl_memdesc perfcounter_save_restore_desc;
struct kgsl_memdesc pagetable_desc;
struct kgsl_memdesc *perfcounter_save_restore_desc;
struct kgsl_memdesc *pagetable_desc;
struct adreno_dispatcher_drawqueue dispatch_q;
wait_queue_head_t ts_expire_waitq;
unsigned int wptr_preempt_end;
@ -125,7 +125,7 @@ struct adreno_ringbuffer {
* @profile_desc: global memory to construct IB1s to do user side
* profiling
*/
struct kgsl_memdesc profile_desc;
struct kgsl_memdesc *profile_desc;
/**
* @profile_index: Pointer to the next "slot" in profile_desc for a user
* profiling IB1. This allows for PAGE_SIZE / 16 = 256 simultaneous

View file

@ -216,7 +216,7 @@ static inline bool iommu_is_setstate_addr(struct kgsl_device *device,
if (kgsl_mmu_get_mmutype(device) != KGSL_MMU_TYPE_IOMMU)
return false;
return kgsl_gpuaddr_in_memdesc(&iommu->setstate, gpuaddr,
return kgsl_gpuaddr_in_memdesc(iommu->setstate, gpuaddr,
size);
}
@ -228,7 +228,7 @@ static void dump_all_ibs(struct kgsl_device *device,
unsigned int *rbptr;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
rbptr = rb->buffer_desc.hostptr;
rbptr = rb->buffer_desc->hostptr;
for (index = 0; index < KGSL_RB_DWORDS;) {
@ -251,7 +251,7 @@ static void dump_all_ibs(struct kgsl_device *device,
if (iommu_is_setstate_addr(device, ibaddr, ibsize))
continue;
if (kgsl_gpuaddr_in_memdesc(&adreno_dev->pwron_fixup,
if (kgsl_gpuaddr_in_memdesc(adreno_dev->pwron_fixup,
ibaddr, ibsize))
continue;
@ -284,7 +284,7 @@ static void snapshot_rb_ibs(struct kgsl_device *device,
* from the rptr
*/
index = rptr;
rbptr = rb->buffer_desc.hostptr;
rbptr = rb->buffer_desc->hostptr;
do {
index--;
@ -402,7 +402,7 @@ static void snapshot_rb_ibs(struct kgsl_device *device,
if (iommu_is_setstate_addr(device, ibaddr, ibsize))
continue;
if (kgsl_gpuaddr_in_memdesc(&adreno_dev->pwron_fixup,
if (kgsl_gpuaddr_in_memdesc(adreno_dev->pwron_fixup,
ibaddr, ibsize))
continue;
@ -447,14 +447,14 @@ static size_t snapshot_rb(struct kgsl_device *device, u8 *buf,
&header->timestamp_queued);
adreno_rb_readtimestamp(adreno_dev, rb, KGSL_TIMESTAMP_RETIRED,
&header->timestamp_retired);
header->gpuaddr = rb->buffer_desc.gpuaddr;
header->gpuaddr = rb->buffer_desc->gpuaddr;
header->id = rb->id;
if (rb == adreno_dev->cur_rb)
snapshot_rb_ibs(device, rb, snapshot);
/* Just copy the ringbuffer, there are no active IBs */
memcpy(data, rb->buffer_desc.hostptr, KGSL_RB_SIZE);
memcpy(data, rb->buffer_desc->hostptr, KGSL_RB_SIZE);
/* Return the size of the section */
return KGSL_RB_SIZE + sizeof(*header);
@ -760,7 +760,7 @@ static size_t snapshot_global(struct kgsl_device *device, u8 *buf,
u8 *ptr = buf + sizeof(*header);
if (memdesc->size == 0)
if (!memdesc || memdesc->size == 0)
return 0;
if (remain < (memdesc->size + sizeof(*header))) {
@ -794,12 +794,12 @@ static void adreno_snapshot_iommu(struct kgsl_device *device,
struct kgsl_iommu *iommu = KGSL_IOMMU_PRIV(device);
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
snapshot, snapshot_global, &iommu->setstate);
snapshot, snapshot_global, iommu->setstate);
if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
kgsl_snapshot_add_section(device,
KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
snapshot, snapshot_global, &iommu->smmu_info);
snapshot, snapshot_global, iommu->smmu_info);
}
static void adreno_snapshot_ringbuffer(struct kgsl_device *device,
@ -873,11 +873,11 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
/* Dump selected global buffers */
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
snapshot, snapshot_global, &device->memstore);
snapshot, snapshot_global, device->memstore);
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_GPU_OBJECT_V2,
snapshot, snapshot_global,
&adreno_dev->pwron_fixup);
adreno_dev->pwron_fixup);
if (kgsl_mmu_get_mmutype(device) == KGSL_MMU_TYPE_IOMMU)
adreno_snapshot_iommu(device, snapshot);

View file

@ -518,8 +518,8 @@ DECLARE_EVENT_CLASS(adreno_hw_preempt_template,
__entry->new_rptr = new_rptr;
__entry->cur_wptr = cur_rb->wptr;
__entry->new_wptr = new_rb->wptr;
__entry->cur_rbbase = cur_rb->buffer_desc.gpuaddr;
__entry->new_rbbase = new_rb->buffer_desc.gpuaddr;
__entry->cur_rbbase = cur_rb->buffer_desc->gpuaddr;
__entry->new_rbbase = new_rb->buffer_desc->gpuaddr;
),
TP_printk(
"cur_rb_lvl=%d rptr=%x wptr=%x rbbase=%x new_rb_lvl=%d rptr=%x wptr=%x rbbase=%x",
@ -573,8 +573,8 @@ TRACE_EVENT(adreno_hw_preempt_comp_to_clear,
__entry->cur_wptr = cur_rb->wptr;
__entry->new_wptr_end = new_rb->wptr_preempt_end;
__entry->new_wptr = new_rb->wptr;
__entry->cur_rbbase = cur_rb->buffer_desc.gpuaddr;
__entry->new_rbbase = new_rb->buffer_desc.gpuaddr;
__entry->cur_rbbase = cur_rb->buffer_desc->gpuaddr;
__entry->new_rbbase = new_rb->buffer_desc->gpuaddr;
),
TP_printk(
"cur_rb_lvl=%d rptr=%x wptr=%x rbbase=%x prev_rb_lvl=%d rptr=%x wptr_preempt_end=%x wptr=%x rbbase=%x",
@ -607,8 +607,8 @@ TRACE_EVENT(adreno_hw_preempt_token_submit,
__entry->cur_wptr = cur_rb->wptr;
__entry->cur_wptr_end = cur_rb->wptr_preempt_end;
__entry->new_wptr = new_rb->wptr;
__entry->cur_rbbase = cur_rb->buffer_desc.gpuaddr;
__entry->new_rbbase = new_rb->buffer_desc.gpuaddr;
__entry->cur_rbbase = cur_rb->buffer_desc->gpuaddr;
__entry->new_rbbase = new_rb->buffer_desc->gpuaddr;
),
TP_printk(
"cur_rb_lvl=%d rptr=%x wptr_preempt_end=%x wptr=%x rbbase=%x new_rb_lvl=%d rptr=%x wptr=%x rbbase=%x",

View file

@ -716,9 +716,9 @@ kgsl_context_destroy(struct kref *kref)
if (context->id != KGSL_CONTEXT_INVALID) {
/* Clear the timestamps in the memstore during destroy */
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), 0);
kgsl_sharedmem_writel(device, &device->memstore,
kgsl_sharedmem_writel(device, device->memstore,
KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), 0);
/* clear device power constraint */
@ -1181,8 +1181,8 @@ static int kgsl_open_device(struct kgsl_device *device)
* which will be called by kgsl_active_count_get().
*/
atomic_inc(&device->active_cnt);
kgsl_sharedmem_set(device, &device->memstore, 0, 0,
device->memstore.size);
kgsl_sharedmem_set(device, device->memstore, 0, 0,
device->memstore->size);
result = device->ftbl->init(device);
if (result)
@ -4397,7 +4397,7 @@ static int
kgsl_mmap_memstore(struct file *file, struct kgsl_device *device,
struct vm_area_struct *vma)
{
struct kgsl_memdesc *memdesc = &device->memstore;
struct kgsl_memdesc *memdesc = device->memstore;
unsigned int vma_size = vma->vm_end - vma->vm_start;
/* The memstore can only be mapped as read only */
@ -4728,7 +4728,7 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr,
struct kgsl_device *device = dev_priv->device;
struct kgsl_mem_entry *entry = NULL;
if (vma_offset == (unsigned long) device->memstore.gpuaddr)
if (vma_offset == (unsigned long) device->memstore->gpuaddr)
return get_unmapped_area(NULL, addr, len, pgoff, flags);
val = get_mmap_entry(private, &entry, pgoff, len);
@ -4774,7 +4774,7 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma)
/* Handle leagacy behavior for memstore */
if (vma_offset == (unsigned long) device->memstore.gpuaddr)
if (vma_offset == (unsigned long) device->memstore->gpuaddr)
return kgsl_mmap_memstore(file, device, vma);
/*
@ -5061,6 +5061,7 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
error_close_mmu:
kgsl_mmu_close(device);
kgsl_free_globals(device);
error_pwrctrl_close:
kgsl_pwrctrl_close(device);
error:
@ -5083,6 +5084,12 @@ void kgsl_device_platform_remove(struct kgsl_device *device)
kgsl_mmu_close(device);
/*
* This needs to come after the MMU close so we can be sure all the
* pagetables have been freed
*/
kgsl_free_globals(device);
kgsl_pwrctrl_close(device);
kgsl_device_debugfs_close(device);

View file

@ -50,10 +50,10 @@
KGSL_MEMSTORE_OFFSET(((rb)->id + KGSL_MEMSTORE_MAX), field)
#define MEMSTORE_ID_GPU_ADDR(dev, iter, field) \
((dev)->memstore.gpuaddr + KGSL_MEMSTORE_OFFSET(iter, field))
((dev)->memstore->gpuaddr + KGSL_MEMSTORE_OFFSET(iter, field))
#define MEMSTORE_RB_GPU_ADDR(dev, rb, field) \
((dev)->memstore.gpuaddr + \
((dev)->memstore->gpuaddr + \
KGSL_MEMSTORE_OFFSET(((rb)->id + KGSL_MEMSTORE_MAX), field))
/*
@ -71,13 +71,13 @@
/* Shadow global helpers */
#define SCRATCH_RPTR_OFFSET(id) ((id) * sizeof(unsigned int))
#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 + \
((dev)->scratch->gpuaddr + \
SCRATCH_PREEMPTION_CTXT_RESTORE_ADDR_OFFSET(id))
/* Timestamp window used to detect rollovers (half of integer range) */
@ -227,6 +227,18 @@ struct kgsl_memdesc {
unsigned int cur_bindings;
};
/**
* struct kgsl_global_memdesc - wrapper for global memory objects
*/
struct kgsl_global_memdesc {
/** @memdesc: Container for the GPU memory descriptor for the object */
struct kgsl_memdesc memdesc;
/** @name: Name of the object for the debugfs list */
const char *name;
/** @node: List node for the list of global objects */
struct list_head node;
};
/*
* List of different memory entry types. The usermem enum
* starts at 0, which we use for allocated memory, so 1 is
@ -449,22 +461,22 @@ int kgsl_request_irq(struct platform_device *pdev, const char *name,
int __init kgsl_core_init(void);
void kgsl_core_exit(void);
static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
static inline bool kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
uint64_t gpuaddr, uint64_t size)
{
if (!memdesc)
return false;
/* set a minimum size to search for */
if (!size)
size = 1;
/* don't overflow */
if (size > U64_MAX - gpuaddr)
return 0;
return false;
if (gpuaddr >= memdesc->gpuaddr &&
((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size))) {
return 1;
}
return 0;
return (gpuaddr >= memdesc->gpuaddr &&
((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size)));
}
static inline void *kgsl_memdesc_map(struct kgsl_memdesc *memdesc)

View file

@ -67,13 +67,25 @@ DEFINE_DEBUGFS_ATTRIBUTE(_isdb_fops, _isdb_get, _isdb_set, "%llu\n");
static int globals_print(struct seq_file *s, void *unused)
{
kgsl_print_global_pt_entries(s);
struct kgsl_device *device = s->private;
struct kgsl_global_memdesc *md;
list_for_each_entry(md, &device->globals, node) {
struct kgsl_memdesc *memdesc = &md->memdesc;
seq_printf(s, "0x%pK-0x%pK %16llu %s\n",
(u64 *)(uintptr_t) memdesc->gpuaddr,
(u64 *)(uintptr_t) (memdesc->gpuaddr +
memdesc->size - 1), memdesc->size,
md->name);
}
return 0;
}
static int globals_open(struct inode *inode, struct file *file)
{
return single_open(file, globals_print, NULL);
return single_open(file, globals_print, inode->i_private);
}
static int globals_release(struct inode *inode, struct file *file)

View file

@ -238,8 +238,8 @@ struct kgsl_device {
/* Starting kernel virtual address for QDSS GFX DBG register block */
void __iomem *qdss_gfx_virt;
struct kgsl_memdesc memstore;
struct kgsl_memdesc scratch;
struct kgsl_memdesc *memstore;
struct kgsl_memdesc *scratch;
const char *iomemname;
struct kgsl_mmu mmu;
@ -307,6 +307,16 @@ struct kgsl_device {
unsigned int num_l3_pwrlevels;
/* store current L3 vote to determine if we should change our vote */
unsigned int cur_l3_pwrlevel;
/** @globals: List of global memory objects */
struct list_head globals;
/** @globlal_map: bitmap for global memory allocations */
unsigned long *global_map;
/** @global_pages: Number of pages available in the global_map */
unsigned int global_pages;
/* @qdss_desc: Memory descriptor for the QDSS region if applicable */
struct kgsl_memdesc *qdss_desc;
/* @qtimer_desc: Memory descriptor for the QDSS region if applicable */
struct kgsl_memdesc *qtimer_desc;
};
#define KGSL_MMU_DEVICE(_mmu) \
@ -321,7 +331,8 @@ struct kgsl_device {
.wait_queue = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).wait_queue),\
.active_cnt_wq = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).active_cnt_wq),\
.mutex = __MUTEX_INITIALIZER((_dev).mutex),\
.state = KGSL_STATE_NONE
.state = KGSL_STATE_NONE, \
.globals = LIST_HEAD_INIT((_dev).globals)
/**

View file

@ -66,80 +66,31 @@ struct kgsl_iommu_addr_entry {
static struct kmem_cache *addr_entry_cache;
/*
* There are certain memory allocations (ringbuffer, memstore, etc) that need to
* be present at the same address in every pagetable. We call these "global"
* pagetable entries. There are relatively few of these and they are mostly
* stable (defined at init time) but the actual number of globals can differ
* slight depending on the target and implementation.
*
* Here we define an array and a simple allocator to keep track of the currently
* active global entries. Each entry is assigned a unique address inside of a
* MMU implementation specific "global" region. We use a simple bitmap based
* allocator for the region to allow for both fixed and dynamic addressing.
*/
#define GLOBAL_PT_ENTRIES 32
struct global_pt_entry {
struct kgsl_memdesc *memdesc;
char name[32];
};
#define GLOBAL_MAP_PAGES (KGSL_IOMMU_GLOBAL_MEM_SIZE >> PAGE_SHIFT)
static struct global_pt_entry global_pt_entries[GLOBAL_PT_ENTRIES];
static DECLARE_BITMAP(global_map, GLOBAL_MAP_PAGES);
static int secure_global_size;
static int global_pt_count;
static struct kgsl_memdesc gpu_qdss_desc;
static struct kgsl_memdesc gpu_qtimer_desc;
void kgsl_print_global_pt_entries(struct seq_file *s)
static void kgsl_iommu_unmap_globals(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable)
{
int i;
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
struct kgsl_global_memdesc *md;
for (i = 0; i < global_pt_count; i++) {
struct kgsl_memdesc *memdesc = global_pt_entries[i].memdesc;
if (memdesc == NULL)
continue;
seq_printf(s, "0x%pK-0x%pK %16llu %s\n",
(uint64_t *)(uintptr_t) memdesc->gpuaddr,
(uint64_t *)(uintptr_t) (memdesc->gpuaddr +
memdesc->size - 1), memdesc->size,
global_pt_entries[i].name);
}
list_for_each_entry(md, &device->globals, node)
kgsl_mmu_unmap(pagetable, &md->memdesc);
}
static void kgsl_iommu_unmap_globals(struct kgsl_pagetable *pagetable)
static void kgsl_iommu_map_globals(struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable)
{
unsigned int i;
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
struct kgsl_global_memdesc *md;
for (i = 0; i < global_pt_count; i++) {
if (global_pt_entries[i].memdesc != NULL)
kgsl_mmu_unmap(pagetable,
global_pt_entries[i].memdesc);
}
list_for_each_entry(md, &device->globals, node)
kgsl_mmu_map(pagetable, &md->memdesc);
}
static int kgsl_iommu_map_globals(struct kgsl_pagetable *pagetable)
static u64 kgsl_iommu_get_global_base(struct kgsl_mmu *mmu)
{
unsigned int i;
for (i = 0; i < global_pt_count; i++) {
if (global_pt_entries[i].memdesc != NULL) {
int ret = kgsl_mmu_map(pagetable,
global_pt_entries[i].memdesc);
if (ret)
return ret;
}
}
return 0;
return KGSL_IOMMU_GLOBAL_MEM_BASE(mmu);
}
void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_device *device,
@ -180,165 +131,6 @@ int kgsl_iommu_map_global_secure_pt_entry(struct kgsl_device *device,
return ret;
}
static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc)
{
int i;
if (memdesc->gpuaddr == 0 || !(memdesc->priv & KGSL_MEMDESC_GLOBAL))
return;
for (i = 0; i < global_pt_count; i++) {
if (global_pt_entries[i].memdesc == memdesc) {
u64 offset = memdesc->gpuaddr -
KGSL_IOMMU_GLOBAL_MEM_BASE(mmu);
bitmap_clear(global_map, offset >> PAGE_SHIFT,
kgsl_memdesc_footprint(memdesc) >> PAGE_SHIFT);
memdesc->gpuaddr = 0;
memdesc->priv &= ~KGSL_MEMDESC_GLOBAL;
global_pt_entries[i].memdesc = NULL;
return;
}
}
}
static void kgsl_iommu_add_global(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc, const char *name)
{
u32 bit, start = 0;
u64 size = kgsl_memdesc_footprint(memdesc);
if (memdesc->gpuaddr != 0)
return;
if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES))
return;
if (WARN_ON(size > KGSL_IOMMU_GLOBAL_MEM_SIZE))
return;
if (memdesc->priv & KGSL_MEMDESC_RANDOM) {
u32 range = GLOBAL_MAP_PAGES - (size >> PAGE_SHIFT);
start = get_random_int() % range;
}
for (;;) {
bit = bitmap_find_next_zero_area(global_map, GLOBAL_MAP_PAGES,
start, size >> PAGE_SHIFT, 0);
if (bit < GLOBAL_MAP_PAGES)
break;
if (WARN_ON(start == 0))
return;
start--;
}
memdesc->gpuaddr =
KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + (bit << PAGE_SHIFT);
bitmap_set(global_map, bit, size >> PAGE_SHIFT);
memdesc->priv |= KGSL_MEMDESC_GLOBAL;
global_pt_entries[global_pt_count].memdesc = memdesc;
strlcpy(global_pt_entries[global_pt_count].name, name,
sizeof(global_pt_entries[global_pt_count].name));
global_pt_count++;
}
struct kgsl_memdesc *kgsl_iommu_get_qdss_global_entry(void)
{
return &gpu_qdss_desc;
}
static void kgsl_setup_qdss_desc(struct kgsl_device *device)
{
int result = 0;
uint32_t gpu_qdss_entry[2];
if (!of_find_property(device->pdev->dev.of_node,
"qcom,gpu-qdss-stm", NULL))
return;
if (of_property_read_u32_array(device->pdev->dev.of_node,
"qcom,gpu-qdss-stm", gpu_qdss_entry, 2)) {
dev_err(device->dev, "Failed to read gpu qdss dts entry\n");
return;
}
kgsl_memdesc_init(device, &gpu_qdss_desc, 0);
gpu_qdss_desc.priv = 0;
gpu_qdss_desc.physaddr = gpu_qdss_entry[0];
gpu_qdss_desc.size = gpu_qdss_entry[1];
gpu_qdss_desc.pagetable = NULL;
gpu_qdss_desc.ops = NULL;
gpu_qdss_desc.hostptr = NULL;
result = kgsl_memdesc_sg_dma(&gpu_qdss_desc, gpu_qdss_desc.physaddr,
gpu_qdss_desc.size);
if (result) {
dev_err(device->dev, "memdesc_sg_dma failed: %d\n", result);
return;
}
kgsl_mmu_add_global(device, &gpu_qdss_desc, "gpu-qdss");
}
static inline void kgsl_cleanup_qdss_desc(struct kgsl_mmu *mmu)
{
kgsl_iommu_remove_global(mmu, &gpu_qdss_desc);
kgsl_sharedmem_free(&gpu_qdss_desc);
}
struct kgsl_memdesc *kgsl_iommu_get_qtimer_global_entry(void)
{
return &gpu_qtimer_desc;
}
static void kgsl_setup_qtimer_desc(struct kgsl_device *device)
{
int result = 0;
uint32_t gpu_qtimer_entry[2];
if (!of_find_property(device->pdev->dev.of_node,
"qcom,gpu-qtimer", NULL))
return;
if (of_property_read_u32_array(device->pdev->dev.of_node,
"qcom,gpu-qtimer", gpu_qtimer_entry, 2)) {
dev_err(device->dev, "Failed to read gpu qtimer dts entry\n");
return;
}
kgsl_memdesc_init(device, &gpu_qtimer_desc, 0);
gpu_qtimer_desc.priv = 0;
gpu_qtimer_desc.physaddr = gpu_qtimer_entry[0];
gpu_qtimer_desc.size = gpu_qtimer_entry[1];
gpu_qtimer_desc.pagetable = NULL;
gpu_qtimer_desc.ops = NULL;
gpu_qtimer_desc.hostptr = NULL;
result = kgsl_memdesc_sg_dma(&gpu_qtimer_desc, gpu_qtimer_desc.physaddr,
gpu_qtimer_desc.size);
if (result) {
dev_err(device->dev, "memdesc_sg_dma failed: %d\n", result);
return;
}
kgsl_mmu_add_global(device, &gpu_qtimer_desc, "gpu-qtimer");
}
static inline void kgsl_cleanup_qtimer_desc(struct kgsl_mmu *mmu)
{
kgsl_iommu_remove_global(mmu, &gpu_qtimer_desc);
kgsl_sharedmem_free(&gpu_qtimer_desc);
}
static void _detach_pt(struct kgsl_iommu_pt *iommu_pt,
struct kgsl_iommu_context *ctx)
{
@ -528,49 +320,45 @@ struct _mem_entry {
char name[32];
};
static void _get_global_entries(uint64_t faultaddr,
static void _get_global_entries(struct kgsl_mmu *mmu, uint64_t faultaddr,
struct _mem_entry *prev,
struct _mem_entry *next)
{
int i;
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
struct kgsl_global_memdesc *p = NULL, *n = NULL, *md;
uint64_t prevaddr = 0;
struct global_pt_entry *p = NULL;
uint64_t nextaddr = (uint64_t) -1;
struct global_pt_entry *n = NULL;
for (i = 0; i < global_pt_count; i++) {
uint64_t addr;
list_for_each_entry(md, &device->globals, node) {
struct kgsl_memdesc *memdesc = &md->memdesc;
u64 addr;
if (global_pt_entries[i].memdesc == NULL)
continue;
addr = global_pt_entries[i].memdesc->gpuaddr;
addr = memdesc->gpuaddr;
if ((addr < faultaddr) && (addr > prevaddr)) {
prevaddr = addr;
p = &global_pt_entries[i];
p = md;
}
if ((addr > faultaddr) && (addr < nextaddr)) {
nextaddr = addr;
n = &global_pt_entries[i];
n = md;
}
}
if (p != NULL) {
prev->gpuaddr = p->memdesc->gpuaddr;
prev->size = p->memdesc->size;
prev->flags = p->memdesc->flags;
prev->priv = p->memdesc->priv;
prev->gpuaddr = p->memdesc.gpuaddr;
prev->size = p->memdesc.size;
prev->flags = p->memdesc.flags;
prev->priv = p->memdesc.priv;
prev->pid = 0;
strlcpy(prev->name, p->name, sizeof(prev->name));
}
if (n != NULL) {
next->gpuaddr = n->memdesc->gpuaddr;
next->size = n->memdesc->size;
next->flags = n->memdesc->flags;
next->priv = n->memdesc->priv;
next->gpuaddr = n->memdesc.gpuaddr;
next->size = n->memdesc.size;
next->flags = n->memdesc.flags;
next->priv = n->memdesc.priv;
next->pid = 0;
strlcpy(next->name, n->name, sizeof(next->name));
}
@ -637,7 +425,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, uint64_t faultaddr,
nextentry->gpuaddr = (uint64_t) -1;
if (ADDR_IN_GLOBAL(mmu, faultaddr)) {
_get_global_entries(faultaddr, preventry, nextentry);
_get_global_entries(mmu, faultaddr, preventry, nextentry);
} else if (private) {
spin_lock(&private->mem_lock);
_get_entries(private, faultaddr, preventry, nextentry);
@ -975,7 +763,7 @@ static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt)
ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE];
} else {
ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_USER];
kgsl_iommu_unmap_globals(pt);
kgsl_iommu_unmap_globals(mmu, pt);
}
if (iommu_pt->domain) {
@ -1206,7 +994,7 @@ static int _init_global_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
goto done;
}
ret = kgsl_iommu_map_globals(pt);
kgsl_iommu_map_globals(mmu, pt);
done:
if (ret)
@ -1326,7 +1114,7 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
goto done;
}
ret = kgsl_iommu_map_globals(pt);
kgsl_iommu_map_globals(mmu, pt);
done:
if (ret)
@ -1414,11 +1202,6 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
__free_page(kgsl_dummy_page);
kgsl_dummy_page = NULL;
}
kgsl_iommu_remove_global(mmu, &iommu->setstate);
kgsl_sharedmem_free(&iommu->setstate);
kgsl_cleanup_qdss_desc(mmu);
kgsl_cleanup_qtimer_desc(mmu);
}
static int kgsl_iommu_init(struct kgsl_mmu *mmu)
@ -1436,9 +1219,6 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
return -EINVAL;
}
status = kgsl_allocate_kernel(device, &iommu->setstate, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, 0);
iommu->regbase = ioremap(iommu->regstart, iommu->regsize);
if (iommu->regbase == NULL) {
dev_err(device->dev,
@ -1456,9 +1236,18 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu)
}
}
kgsl_iommu_add_global(mmu, &iommu->setstate, "setstate");
kgsl_setup_qdss_desc(device);
kgsl_setup_qtimer_desc(device);
iommu->setstate = kgsl_allocate_global(device, PAGE_SIZE,
KGSL_MEMFLAGS_GPUREADONLY, 0, "setstate");
status = PTR_ERR_OR_ZERO(iommu->setstate);
if (status)
goto done;
device->qdss_desc = kgsl_allocate_global_fixed(device,
"qcom,gpu-qdss-stm", "gpu-qdss");
device->qtimer_desc = kgsl_allocate_global_fixed(device,
"qcom,gpu-timer", "gpu-qtimer");
if (!mmu->secured)
goto done;
@ -2631,11 +2420,8 @@ struct kgsl_mmu_ops kgsl_iommu_ops = {
.mmu_set_pf_policy = kgsl_iommu_set_pf_policy,
.mmu_pagefault_resume = kgsl_iommu_pagefault_resume,
.mmu_init_pt = kgsl_iommu_init_pt,
.mmu_add_global = kgsl_iommu_add_global,
.mmu_remove_global = kgsl_iommu_remove_global,
.mmu_getpagetable = kgsl_iommu_getpagetable,
.mmu_get_qdss_global_entry = kgsl_iommu_get_qdss_global_entry,
.mmu_get_qtimer_global_entry = kgsl_iommu_get_qtimer_global_entry,
.mmu_get_global_base = kgsl_iommu_get_global_base,
.probe = kgsl_iommu_probe,
};

View file

@ -118,10 +118,10 @@ struct kgsl_iommu {
void __iomem *regbase;
unsigned long regstart;
unsigned int regsize;
struct kgsl_memdesc setstate;
struct kgsl_memdesc *setstate;
atomic_t clk_enable_count;
struct clk *clks[KGSL_IOMMU_MAX_CLKS];
struct kgsl_memdesc smmu_info;
struct kgsl_memdesc *smmu_info;
};
/*

View file

@ -527,22 +527,14 @@ int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
return 0;
}
void kgsl_mmu_remove_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc)
u64 kgsl_mmu_get_global_base(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
struct kgsl_mmu *mmu = &(device->mmu);
if (MMU_OP_VALID(mmu, mmu_remove_global))
mmu->mmu_ops->mmu_remove_global(mmu, memdesc);
}
if (MMU_OP_VALID(mmu, mmu_get_global_base))
return mmu->mmu_ops->mmu_get_global_base(mmu);
void kgsl_mmu_add_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc, const char *name)
{
struct kgsl_mmu *mmu = &device->mmu;
if (MMU_OP_VALID(mmu, mmu_add_global))
mmu->mmu_ops->mmu_add_global(mmu, memdesc, name);
return 0;
}
void kgsl_mmu_close(struct kgsl_device *device)
@ -567,27 +559,6 @@ bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable,
return false;
}
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
if (MMU_OP_VALID(mmu, mmu_get_qdss_global_entry))
return mmu->mmu_ops->mmu_get_qdss_global_entry();
return NULL;
}
struct kgsl_memdesc *kgsl_mmu_get_qtimer_global_entry(
struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
if (MMU_OP_VALID(mmu, mmu_get_qtimer_global_entry))
return mmu->mmu_ops->mmu_get_qtimer_global_entry();
return NULL;
}
/*
* NOMMU definitions - NOMMU really just means that the MMU is kept in pass
* through and the GPU directly accesses physical memory. Used in debug mode
@ -622,24 +593,20 @@ static struct kgsl_mmu_pt_ops nommu_pt_ops = {
.addr_in_range = nommu_gpuaddr_in_range,
};
static void nommu_add_global(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc, const char *name)
{
memdesc->gpuaddr = (uint64_t) sg_phys(memdesc->sgt->sgl);
}
static void nommu_remove_global(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc)
{
memdesc->gpuaddr = 0;
}
static int nommu_init_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
{
struct kgsl_device *device = KGSL_MMU_DEVICE(mmu);
struct kgsl_global_memdesc *md;
if (pt == NULL)
return -EINVAL;
pt->pt_ops = &nommu_pt_ops;
list_for_each_entry(md, &device->globals, node)
md->memdesc.gpuaddr =
(uint64_t) sg_phys(md->memdesc.sgt->sgl);
return 0;
}
@ -671,8 +638,6 @@ static int nommu_probe(struct kgsl_device *device)
static struct kgsl_mmu_ops kgsl_nommu_ops = {
.mmu_init = nommu_init,
.mmu_add_global = nommu_add_global,
.mmu_remove_global = nommu_remove_global,
.mmu_init_pt = nommu_init_pt,
.mmu_getpagetable = nommu_getpagetable,
.probe = nommu_probe,

View file

@ -68,14 +68,9 @@ struct kgsl_mmu_ops {
struct kgsl_pagetable *pt, u64 ttbr0);
int (*mmu_set_pf_policy)(struct kgsl_mmu *mmu, unsigned long pf_policy);
int (*mmu_init_pt)(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt);
void (*mmu_add_global)(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc, const char *name);
void (*mmu_remove_global)(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc);
struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu,
unsigned long name);
struct kgsl_memdesc* (*mmu_get_qdss_global_entry)(void);
struct kgsl_memdesc* (*mmu_get_qtimer_global_entry)(void);
u64 (*mmu_get_global_base)(struct kgsl_mmu *mmu);
};
struct kgsl_mmu_pt_ops {
@ -221,11 +216,6 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t offset,
uint64_t size);
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device);
struct kgsl_memdesc *kgsl_mmu_get_qtimer_global_entry(
struct kgsl_device *device);
int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size);
@ -346,6 +336,14 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable)
return 0;
}
/**
* kgsl_mmu_get_global_base - Return the base GPU address of the global region
* @device: A KGSL GPU device handle
*
* Return: The virtual address of the base of the global object region
*/
u64 kgsl_mmu_get_global_base(struct kgsl_device *device);
static inline struct device *kgsl_mmu_get_ctx(const char *name)
{
return ERR_PTR(-ENODEV);

View file

@ -4,8 +4,10 @@
*/
#include <asm/cacheflush.h>
#include <linux/of_platform.h>
#include <linux/highmem.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <soc/qcom/secure_buffer.h>
#include "kgsl_device.h"
@ -1265,11 +1267,104 @@ int kgsl_allocate_kernel(struct kgsl_device *device,
return 0;
}
int kgsl_allocate_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv,
const char *name)
#define KGSL_GLOBAL_MEM_SIZE (20 * SZ_1M)
#define KGSL_GLOBAL_MEM_PAGES (KGSL_GLOBAL_MEM_SIZE >> PAGE_SHIFT)
static u64 global_get_offset(struct kgsl_device *device, u64 size,
unsigned long priv)
{
int start = 0, bit;
if (!device->global_map) {
device->global_map =
kcalloc(BITS_TO_LONGS(KGSL_GLOBAL_MEM_PAGES),
sizeof(unsigned long), GFP_KERNEL);
if (!device->global_map)
return (unsigned long) -ENOMEM;
device->global_pages = KGSL_GLOBAL_MEM_PAGES;
}
if (priv & KGSL_MEMDESC_RANDOM) {
u32 offset = device->global_pages - (size >> PAGE_SHIFT);
start = get_random_int() % offset;
}
while (start >= 0) {
bit = bitmap_find_next_zero_area(device->global_map,
device->global_pages, start, size >> PAGE_SHIFT, 0);
if (bit < device->global_pages)
break;
/* FIXME: We should randomize this */
start--;
}
if (WARN_ON(start < 0))
return (unsigned long) -ENOMEM;
bitmap_set(device->global_map, bit, size >> PAGE_SHIFT);
return bit << PAGE_SHIFT;
}
struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device,
const char *resource, const char *name)
{
struct kgsl_global_memdesc *md;
u32 entry[2];
int ret;
u64 offset;
if (of_property_read_u32_array(device->pdev->dev.of_node,
resource, entry, 2))
return ERR_PTR(-ENODEV);
md = kzalloc(sizeof(*md), GFP_KERNEL);
if (!md)
return ERR_PTR(-ENOMEM);
kgsl_memdesc_init(device, &md->memdesc, 0);
md->memdesc.priv = KGSL_MEMDESC_GLOBAL;
md->memdesc.physaddr = entry[0];
md->memdesc.size = entry[1];
ret = kgsl_memdesc_sg_dma(&md->memdesc, entry[0], entry[1]);
if (ret) {
kfree(md);
return ERR_PTR(ret);
}
offset = global_get_offset(device,
kgsl_memdesc_footprint(&md->memdesc), 0);
if (IS_ERR_VALUE(offset)) {
kgsl_sharedmem_free(&md->memdesc);
kfree(md);
return (void *) offset;
}
if (!md->memdesc.gpuaddr)
md->memdesc.gpuaddr = kgsl_mmu_get_global_base(device) + offset;
md->name = name;
/*
* No lock here, because this function is only called during probe/init
* while the caller is holding the mutex
*/
list_add_tail(&md->node, &device->globals);
return &md->memdesc;
}
struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device,
u64 size, u64 flags, u32 priv, const char *name)
{
int ret;
struct kgsl_global_memdesc *md;
u64 offset;
/*
* For the moment, don't allow secure to be allocated through this
@ -1277,21 +1372,51 @@ int kgsl_allocate_global(struct kgsl_device *device,
*/
if (flags & KGSL_MEMFLAGS_SECURE)
return -EINVAL;
return ERR_PTR(-EINVAL);
ret = kgsl_allocate_kernel(device, memdesc, size, flags, priv);
if (ret)
return ret;
md = kzalloc(sizeof(*md), GFP_KERNEL);
if (!md)
return ERR_PTR(-ENOMEM);
kgsl_mmu_add_global(device, memdesc, name);
return 0;
priv |= KGSL_MEMDESC_GLOBAL;
ret = kgsl_allocate_kernel(device, &md->memdesc, size, flags, priv);
if (ret) {
kfree(md);
return ERR_PTR(ret);
}
offset = global_get_offset(device,
kgsl_memdesc_footprint(&md->memdesc), priv);
if (IS_ERR_VALUE(offset)) {
kgsl_sharedmem_free(&md->memdesc);
kfree(md);
return (void *) offset;
}
if (!md->memdesc.gpuaddr)
md->memdesc.gpuaddr = kgsl_mmu_get_global_base(device) + offset;
md->name = name;
/*
* No lock here, because this function is only called during probe/init
* while the caller is holding the mute
*/
list_add_tail(&md->node, &device->globals);
return &md->memdesc;
}
void kgsl_free_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc)
void kgsl_free_globals(struct kgsl_device *device)
{
kgsl_mmu_remove_global(device, memdesc);
kgsl_sharedmem_free(memdesc);
struct kgsl_global_memdesc *md, *tmp;
list_for_each_entry_safe(md, tmp, &device->globals, node) {
kgsl_sharedmem_free(&md->memdesc);
list_del(&md->node);
kfree(md);
}
}
void kgsl_sharedmem_set_noretry(bool val)

View file

@ -96,7 +96,6 @@ int kgsl_allocate_kernel(struct kgsl_device *device,
/**
* kgsl_allocate_global - Allocate a global GPU memory object
* @device: A GPU device handle
* @memdesc: Memory descriptor for the object
* @size: Size of the allocation in bytes
* @flags: Control flags for the allocation
* @priv: Internal flags for the allocation
@ -105,11 +104,38 @@ int kgsl_allocate_kernel(struct kgsl_device *device,
* Allocate a global GPU object for use by all processes. The buffer is
* automatically mapped into the kernel address space and added to the list of
* global buffers that get mapped into each newly created pagetable.
* Return: 0 on success or negative on failure.
* Return: The memory descriptor on success or a ERR_PTR encoded error on
* failure.
*/
int kgsl_allocate_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv,
const char *name);
struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device,
u64 size, u64 flags, u32 priv, const char *name);
/**
* kgsl_allocate_global_fixed - Allocate a global GPU memory object from a fixed
* region defined in the device tree
* @device: A GPU device handle
* @size: Size of the allocation in bytes
* @flags: Control flags for the allocation
* @priv: Internal flags for the allocation
*
* Allocate a global GPU object for use by all processes. The buffer is
* added to the list of global buffers that get mapped into each newly created
* pagetable.
*
* Return: The memory descriptor on success or a ERR_PTR encoded error on
* failure.
*/
struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device,
const char *resource, const char *name);
/**
* kgsl_free_globals - Free all global objects
* @device: A GPU device handle
*
* Free all the global buffer objects. Should only be called during shutdown
* after the pagetables have been freed
*/
void kgsl_free_globals(struct kgsl_device *device);
#define MEMFLAGS(_flags, _mask, _shift) \
((unsigned int) (((_flags) & (_mask)) >> (_shift)))
@ -278,18 +304,6 @@ kgsl_memdesc_footprint(const struct kgsl_memdesc *memdesc)
PAGE_SIZE);
}
/**
* kgsl_free_global() - Free a device wide GPU allocation and remove it from the
* global pagetable entry list
*
* @device: Pointer to the device
* @memdesc: Pointer to the GPU memory descriptor to free
*
* Remove the specific memory descriptor from the global pagetable entry list
* and free it
*/
void kgsl_free_global(struct kgsl_device *device, struct kgsl_memdesc *memdesc);
void kgsl_sharedmem_set_noretry(bool val);
bool kgsl_sharedmem_get_noretry(void);

View file

@ -124,7 +124,7 @@ static size_t snapshot_os(struct kgsl_device *device,
* Save the last active context from global index since its more
* reliable than currrent RB index
*/
kgsl_sharedmem_readl(&device->memstore, &header->current_context,
kgsl_sharedmem_readl(device->memstore, &header->current_context,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context));
context = kgsl_context_get(device, header->current_context);