From 16356049f5a3c1630b8da645226ef3f7e7ae4529 Mon Sep 17 00:00:00 2001
From: Jeff Boody <jboody@codeaurora.org>
Date: Thu, 10 Jul 2014 13:46:02 -0600
Subject: [PATCH] msm: kgsl: update KGSL to match most recent version
Over time chery-picks for KGSL have been skipped or
have been resolved differently between branches. As
a result, this branch of KGSL has become increasingly
difficult to maintain due to merge conflicts. With a
few exceptions KGSL should match the msm-3.4 mainline
exactly. To rectify the situation, this change brings
KGSL up-to-date with the msm-3.4 mainline as a bulk
change because cherry-picks are not practical.
Change-Id: I53f9f7fbf4942e147dea486ff5dbf179af75ea8c
Signed-off-by: Jeff Boody <jboody@codeaurora.org>
---
drivers/gpu/msm/Makefile | 2 +-
drivers/gpu/msm/a2xx_reg.h | 10 +-
drivers/gpu/msm/adreno.c | 53 +++--
drivers/gpu/msm/adreno.h | 42 +++-
drivers/gpu/msm/adreno_a2xx.c | 49 ++--
drivers/gpu/msm/adreno_a3xx.c | 43 ++--
drivers/gpu/msm/adreno_a3xx_snapshot.c | 3 -
drivers/gpu/msm/adreno_a3xx_trace.h | 4 +-
drivers/gpu/msm/adreno_debugfs.c | 39 +---
drivers/gpu/msm/adreno_dispatch.c | 100 ++++++--
drivers/gpu/msm/adreno_drawctxt.c | 35 +--
drivers/gpu/msm/adreno_drawctxt.h | 73 +++---
drivers/gpu/msm/adreno_pm4types.h | 6 +-
drivers/gpu/msm/adreno_postmortem.c | 2 +
drivers/gpu/msm/adreno_ringbuffer.c | 267 ++++++++++++++++------
drivers/gpu/msm/adreno_ringbuffer.h | 2 +-
drivers/gpu/msm/kgsl.c | 102 +++++----
drivers/gpu/msm/kgsl.h | 2 +-
drivers/gpu/msm/kgsl_debugfs.h | 4 +-
drivers/gpu/msm/kgsl_device.h | 41 +++-
drivers/gpu/msm/kgsl_drm.c | 39 +++-
drivers/gpu/msm/kgsl_events.c | 10 +-
drivers/gpu/msm/kgsl_gpummu.c | 18 +-
drivers/gpu/msm/kgsl_iommu.c | 59 +++--
drivers/gpu/msm/kgsl_log.h | 4 +-
drivers/gpu/msm/kgsl_mmu.c | 2 +-
drivers/gpu/msm/kgsl_mmu.h | 2 +-
drivers/gpu/msm/kgsl_pwrctrl.c | 29 +--
drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 8 +-
drivers/gpu/msm/kgsl_sharedmem.h | 11 +-
drivers/gpu/msm/kgsl_snapshot.c | 2 -
drivers/gpu/msm/kgsl_sync.c | 60 +----
drivers/gpu/msm/kgsl_sync.h | 2 -
drivers/gpu/msm/z180.c | 3 +-
34 files changed, 684 insertions(+), 444 deletions(-)
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 895235fa6e0b..53b7b94b9330 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -25,8 +25,8 @@ msm_adreno-y += \
adreno_dispatch.o \
adreno_postmortem.o \
adreno_snapshot.o \
- adreno_trace.o \
adreno_coresight.o \
+ adreno_trace.o \
adreno_a2xx.o \
adreno_a2xx_trace.o \
adreno_a2xx_snapshot.o \
diff --git a/drivers/gpu/msm/a2xx_reg.h b/drivers/gpu/msm/a2xx_reg.h
index c70c4eb86a4e..b2fb99f889bd 100644
--- a/drivers/gpu/msm/a2xx_reg.h
+++ b/drivers/gpu/msm/a2xx_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -252,7 +252,15 @@ union reg_cp_rb_cntl {
#define REG_CP_CSQ_IB1_STAT 0x01FE
#define REG_CP_CSQ_IB2_STAT 0x01FF
#define REG_CP_CSQ_RB_STAT 0x01FD
+
#define REG_CP_DEBUG 0x01FC
+/*
+ * CP DEBUG settings for a3xx and a2xx cores:
+ * DYNAMIC_CLK_DISABLE [27] - turn off the dynamic clock control
+ * MIU_128BIT_WRITE_ENABLE [25] - Allow 128 bit writes to the VBIF
+ */
+#define A2XX_CP_DEBUG_DEFAULT ((1 << 27) | (1 << 25))
+
#define REG_CP_IB1_BASE 0x0458
#define REG_CP_IB1_BUFSZ 0x0459
#define REG_CP_IB2_BASE 0x045A
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index c0f7aa626542..70fc17e3321d 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -17,7 +17,6 @@
#include <linux/sched.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/msm_kgsl.h>
#include <linux/delay.h>
#include <linux/of_coresight.h>
@@ -162,6 +161,12 @@ static const struct {
unsigned int pfp_jt_idx;
/* PFP jump table load addr */
unsigned int pfp_jt_addr;
+ /* PM4 bootstrap loader size */
+ unsigned int pm4_bstrp_size;
+ /* PFP bootstrap loader size */
+ unsigned int pfp_bstrp_size;
+ /* PFP bootstrap loader supported version */
+ unsigned int pfp_bstrp_ver;
} adreno_gpulist[] = {
{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
@@ -199,7 +204,8 @@ static const struct {
512, 0, 2, SZ_512K, 0x3FF037, 0x3FF016 },
{ ADRENO_REV_A330, 3, 3, 0, ANY_ID,
"a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev,
- 512, 0, 2, SZ_1M, NO_VER, NO_VER, 0x8AD, 0x2E4, 0x201, 0x200 },
+ 512, 0, 2, SZ_1M, NO_VER, NO_VER, 0x8AD, 0x2E4, 0x201, 0x200,
+ 0x6, 0x20, 0x330020 },
{ ADRENO_REV_A305B, 3, 0, 5, 0x10,
"a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_128K, NO_VER, NO_VER, 0x8AD, 0x2E4,
@@ -928,7 +934,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
*cmds++ = 0x7fff;
sizedwords += 2;
- if (sizedwords > (sizeof(link)/sizeof(unsigned int))) {
+ if (sizedwords > (ARRAY_SIZE(link))) {
KGSL_DRV_ERR(device, "Temp command buffer overflow\n");
BUG();
}
@@ -982,6 +988,7 @@ static int adreno_gpummu_setstate(struct kgsl_device *device,
context = kgsl_context_get(device, context_id);
if (context == NULL)
return -EINVAL;
+
adreno_ctx = ADRENO_CONTEXT(context);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
@@ -1197,8 +1204,11 @@ adreno_identify_gpu(struct adreno_device *adreno_dev)
adreno_dev->gmem_size = adreno_gpulist[i].gmem_size;
adreno_dev->pm4_jt_idx = adreno_gpulist[i].pm4_jt_idx;
adreno_dev->pm4_jt_addr = adreno_gpulist[i].pm4_jt_addr;
+ adreno_dev->pm4_bstrp_size = adreno_gpulist[i].pm4_bstrp_size;
adreno_dev->pfp_jt_idx = adreno_gpulist[i].pfp_jt_idx;
adreno_dev->pfp_jt_addr = adreno_gpulist[i].pfp_jt_addr;
+ adreno_dev->pfp_bstrp_size = adreno_gpulist[i].pfp_bstrp_size;
+ adreno_dev->pfp_bstrp_ver = adreno_gpulist[i].pfp_bstrp_ver;
adreno_dev->gpulist_index = i;
/*
* Initialize uninitialzed gpu registers, only needs to be done once
@@ -1607,7 +1617,6 @@ static int __devexit adreno_remove(struct platform_device *pdev)
static int adreno_init(struct kgsl_device *device)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int i;
int ret;
@@ -1655,8 +1664,6 @@ static int adreno_init(struct kgsl_device *device)
adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
- rb->global_ts = 0;
-
/* Initialize ft detection register offsets */
ft_detect_regs[0] = adreno_getreg(adreno_dev,
ADRENO_REG_RBBM_STATUS);
@@ -1685,7 +1692,6 @@ static int adreno_init(struct kgsl_device *device)
if (adreno_is_a330v2(adreno_dev))
adreno_a3xx_pwron_fixup_init(adreno_dev);
- set_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv);
done:
return ret;
}
@@ -1709,7 +1715,7 @@ static int adreno_start(struct kgsl_device *device)
regulator_is_enabled(device->pwrctrl.gpu_cx)));
/* Clear any GPU faults that might have been left over */
- adreno_set_gpu_fault(adreno_dev, 0);
+ adreno_clear_gpu_fault(adreno_dev);
/* Power up the device */
kgsl_pwrctrl_enable(device);
@@ -1755,7 +1761,7 @@ static int adreno_start(struct kgsl_device *device)
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
device->ftbl->irqctrl(device, 1);
- status = adreno_ringbuffer_start(&adreno_dev->ringbuffer);
+ status = adreno_ringbuffer_cold_start(&adreno_dev->ringbuffer);
if (status)
goto error_irq_off;
@@ -1822,7 +1828,9 @@ static int adreno_stop(struct kgsl_device *device)
* adreno_reset() - Helper function to reset the GPU
* @device: Pointer to the KGSL device structure for the GPU
*
- * Helper function to reset the GPU hardware by toggling the footswitch
+ * Try to reset the GPU to recover from a fault. First, try to do a low latency
+ * soft reset. If the soft reset fails for some reason, then bring out the big
+ * guns and toggle the footswitch.
*/
int adreno_reset(struct kgsl_device *device)
{
@@ -2301,6 +2309,7 @@ static int adreno_setproperty(struct kgsl_device_private *dev_priv,
}
if (enable) {
+ device->pwrctrl.ctrl_flags = 0;
adreno_dev->fast_hang_detect = 1;
kgsl_pwrscale_enable(device);
} else {
@@ -2358,7 +2367,6 @@ static bool adreno_hw_isidle(struct kgsl_device *device)
if (adreno_dev->gpudev->irq_pending(adreno_dev))
return false;
- /* Read the correct RBBM status for the GPU type */
adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
®_rbbm_status);
@@ -2391,6 +2399,9 @@ int adreno_soft_reset(struct kgsl_device *device)
return -EINVAL;
}
+ if (adreno_dev->drawctxt_active)
+ kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
adreno_dev->drawctxt_active = NULL;
/* Stop the ringbuffer */
@@ -2401,7 +2412,7 @@ int adreno_soft_reset(struct kgsl_device *device)
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
- adreno_set_gpu_fault(adreno_dev, 0);
+ adreno_clear_gpu_fault(adreno_dev);
/* Delete the idle timer */
del_timer_sync(&device->idle_timer);
@@ -2427,7 +2438,7 @@ int adreno_soft_reset(struct kgsl_device *device)
if (adreno_dev->pm4_jt_idx)
ret = adreno_ringbuffer_warm_start(&adreno_dev->ringbuffer);
else
- ret = adreno_ringbuffer_start(&adreno_dev->ringbuffer);
+ ret = adreno_ringbuffer_cold_start(&adreno_dev->ringbuffer);
if (ret)
return ret;
@@ -2437,7 +2448,7 @@ int adreno_soft_reset(struct kgsl_device *device)
return 0;
}
-/**
+/*
* adreno_isidle() - return true if the GPU hardware is idle
* @device: Pointer to the KGSL device structure for the GPU
*
@@ -2449,8 +2460,7 @@ bool adreno_isidle(struct kgsl_device *device)
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
unsigned int rptr;
- /* If the device isn't active, don't force it on. */
- if (device->state != KGSL_STATE_ACTIVE)
+ if (!kgsl_pwrctrl_isenabled(device))
return true;
rptr = adreno_get_rptr(&adreno_dev->ringbuffer);
@@ -2483,7 +2493,7 @@ int adreno_idle(struct kgsl_device *device)
if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev))
kgsl_cffdump_regpoll(device,
adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2,
- 0x00000000, 0x80000000);
+ 0x00000000, 0x80000000);
else
kgsl_cffdump_regpoll(device,
adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2,
@@ -2752,6 +2762,15 @@ static int adreno_waittimestamp(struct kgsl_device *device,
if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID)
ret = -EDEADLK;
+ /*
+ * Return -EPROTO if the device has faulted since the last time we
+ * checked. Userspace uses this as a marker for performing post
+ * fault activities
+ */
+
+ if (!ret && test_and_clear_bit(ADRENO_CONTEXT_FAULT, &drawctxt->priv))
+ ret = -EPROTO;
+
return ret;
}
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 52a6c51b1e77..67afda780e08 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -58,7 +58,6 @@
#define ADRENO_DEFAULT_PWRSCALE_POLICY NULL
#endif
-void adreno_debugfs_init(struct kgsl_device *device);
#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
@@ -168,8 +167,11 @@ struct adreno_device {
unsigned int wait_timeout;
unsigned int pm4_jt_idx;
unsigned int pm4_jt_addr;
+ unsigned int pm4_bstrp_size;
unsigned int pfp_jt_idx;
unsigned int pfp_jt_addr;
+ unsigned int pfp_bstrp_size;
+ unsigned int pfp_bstrp_ver;
unsigned int istore_size;
unsigned int pix_shader_start;
unsigned int instruction_size;
@@ -379,8 +381,8 @@ struct adreno_gpudev {
void (*coresight_disable) (struct kgsl_device *device);
void (*coresight_config_debug_reg) (struct kgsl_device *device,
int debug_reg, unsigned int val);
- void (*postmortem_dump)(struct adreno_device *adreno_dev);
void (*soft_reset)(struct adreno_device *device);
+ void (*postmortem_dump)(struct adreno_device *adreno_dev);
};
#define FT_DETECT_REGS_COUNT 12
@@ -726,13 +728,13 @@ static inline int adreno_add_idle_cmds(struct adreno_device *adreno_dev,
unsigned int *start = cmds;
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
- *cmds++ = 0x00000000;
+ *cmds++ = 0;
if ((adreno_dev->gpurev == ADRENO_REV_A305) ||
(adreno_dev->gpurev == ADRENO_REV_A305C) ||
(adreno_dev->gpurev == ADRENO_REV_A320)) {
*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
- *cmds++ = 0x00000000;
+ *cmds++ = 0;
}
return cmds - start;
@@ -849,6 +851,19 @@ static inline void adreno_set_gpu_fault(struct adreno_device *adreno_dev,
smp_wmb();
}
+/**
+ * adreno_clear_gpu_fault() - Clear the GPU fault register
+ * @adreno_dev: A pointer to an adreno_device structure
+ *
+ * Clear the GPU fault status for the adreno device
+ */
+
+static inline void adreno_clear_gpu_fault(struct adreno_device *adreno_dev)
+{
+ atomic_set(&adreno_dev->dispatcher.fault, 0);
+ smp_wmb();
+}
+
/*
* adreno_vbif_start() - Program VBIF registers, called in device start
* @device: Pointer to device whose vbif data is to be programmed
@@ -877,6 +892,25 @@ static inline void adreno_vbif_start(struct kgsl_device *device,
}
}
+#ifdef CONFIG_DEBUG_FS
+void adreno_debugfs_init(struct kgsl_device *device);
+#else
+static inline void adreno_debugfs_init(struct kgsl_device *device) { }
+#endif
+
+/*
+ * adreno_bootstrap_ucode() - Checks if Ucode bootstrapping is supported
+ * @adreno_dev: Pointer to the the adreno device
+ */
+static inline int adreno_bootstrap_ucode(struct adreno_device *adreno_dev)
+{
+ if ((adreno_dev->pfp_bstrp_size) && (adreno_dev->pm4_bstrp_size)
+ && (adreno_dev->pfp_fw_version >= adreno_dev->pfp_bstrp_ver))
+ return 1;
+ else
+ return 0;
+}
+
/**
* adreno_get_rptr() - Get the current ringbuffer read pointer
* @rb: Pointer the ringbuffer to query
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index a5987afaad82..e4888c89d7c3 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -655,7 +655,7 @@ static unsigned int *build_gmem2sys_cmds(struct adreno_device *adreno_dev,
unsigned int addr = shadow->gmemshadow.gpuaddr;
unsigned int offset = (addr - (addr & 0xfffff000)) / bytesperpixel;
- if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE)) {
/* Store TP0_CHICKEN register */
*cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
*cmds++ = REG_TP0_CHICKEN;
@@ -864,7 +864,7 @@ static unsigned int *build_sys2gmem_cmds(struct adreno_device *adreno_dev,
unsigned int *cmds = shadow->gmem_restore_commands;
unsigned int *start = cmds;
- if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE)) {
/* Store TP0_CHICKEN register */
*cmds++ = cp_type3_packet(CP_REG_TO_MEM, 2);
*cmds++ = REG_TP0_CHICKEN;
@@ -1334,8 +1334,6 @@ build_shader_save_restore_cmds(struct adreno_device *adreno_dev,
static int a2xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt)
{
- drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
-
/* build indirect command buffers to save & restore regs/constants */
build_regrestore_cmds(adreno_dev, drawctxt);
build_regsave_cmds(adreno_dev, drawctxt);
@@ -1361,9 +1359,6 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
if (result)
return result;
- /* set the gmem shadow flag for the context */
- drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
-
/* blank out gmem shadow. */
kgsl_sharedmem_set(drawctxt->base.device,
&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
@@ -1374,7 +1369,7 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev,
&tmp_ctx.cmd);
/* build TP0_CHICKEN register restore command buffer */
- if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE))
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE))
tmp_ctx.cmd = build_chicken_restore_cmds(drawctxt);
/* build indirect command buffers to save & restore gmem */
@@ -1437,8 +1432,8 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
{
int ret;
- if (drawctxt->flags & CTXT_FLAGS_PREAMBLE
- && drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC) {
+ if (drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE
+ && drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC) {
drawctxt->ops = (adreno_is_a225(adreno_dev))
? &a225_preamble_ctx_ops : &adreno_preamble_ctx_ops;
@@ -1467,15 +1462,14 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev,
tmp_ctx.cmd = tmp_ctx.start
= (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
- if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE)) {
ret = a2xx_create_gpustate_shadow(adreno_dev, drawctxt);
if (ret)
goto done;
- drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
}
- if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC)) {
ret = a2xx_create_gmem_shadow(adreno_dev, drawctxt);
if (ret)
goto done;
@@ -1555,7 +1549,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
struct kgsl_device *device = &adreno_dev->dev;
int ret;
- if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(context->base.flags & KGSL_CONTEXT_PREAMBLE)) {
kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->reg_save[1],
context->reg_save[2] << 2, true);
@@ -1567,7 +1561,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
if (ret)
return ret;
- if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
+ if (test_bit(ADRENO_CONTEXT_SHADER_SAVE, &context->priv)) {
kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_save[1],
@@ -1577,6 +1571,8 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
KGSL_CMD_FLAGS_PMODE,
context->shader_save, 3);
+ if (ret)
+ return ret;
kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_fixup[1],
@@ -1592,12 +1588,11 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
if (ret)
return ret;
- context->flags |= CTXT_FLAGS_SHADER_RESTORE;
+ set_bit(ADRENO_CONTEXT_SHADER_RESTORE, &context->priv);
}
}
- if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
- (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
+ if (test_bit(ADRENO_CONTEXT_GMEM_SAVE, &context->priv)) {
kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->context_gmem_shadow.gmem_save[1],
context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -1610,12 +1605,13 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
if (ret)
return ret;
+
kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->chicken_restore[1],
context->chicken_restore[2] << 2, true);
/* Restore TP0_CHICKEN */
- if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(context->base.flags & KGSL_CONTEXT_PREAMBLE)) {
ret = adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
context->chicken_restore, 3);
@@ -1625,7 +1621,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev,
}
adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
- context->flags |= CTXT_FLAGS_GMEM_RESTORE;
+ set_bit(ADRENO_CONTEXT_GMEM_RESTORE, &context->priv);
} else if (adreno_is_a2xx(adreno_dev))
return a2xx_drawctxt_draw_workaround(adreno_dev, context);
@@ -1646,7 +1642,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
* restore gmem.
* (note: changes shader. shader must not already be restored.)
*/
- if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+ if (test_bit(ADRENO_CONTEXT_GMEM_RESTORE, &context->priv)) {
kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
context->context_gmem_shadow.gmem_restore[2] << 2,
@@ -1658,7 +1654,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
if (ret)
return ret;
- if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(context->base.flags & KGSL_CONTEXT_PREAMBLE)) {
kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->chicken_restore[1],
@@ -1671,11 +1667,10 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
if (ret)
return ret;
}
-
- context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
+ clear_bit(ADRENO_CONTEXT_GMEM_RESTORE, &context->priv);
}
- if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(context->base.flags & KGSL_CONTEXT_PREAMBLE)) {
kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
context->reg_restore[1],
context->reg_restore[2] << 2, true);
@@ -1687,7 +1682,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
return ret;
/* restore shader instructions & partitioning. */
- if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
+ if (test_bit(ADRENO_CONTEXT_SHADER_RESTORE, &context->priv)) {
kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->shader_restore[1],
@@ -2093,6 +2088,8 @@ static void a2xx_start(struct adreno_device *adreno_dev)
kgsl_regwrite(device, REG_SQ_INT_CNTL, 0);
a2xx_gmeminit(adreno_dev);
+
+ kgsl_regwrite(device, REG_CP_DEBUG, A2XX_CP_DEBUG_DEFAULT);
}
static void a2xx_postmortem_dump(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index cf0e66a6f2b3..ee34a1df333e 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2297,8 +2297,6 @@ static void build_restore_fixup_cmds(struct adreno_device *adreno_dev,
static int a3xx_create_gpustate_shadow(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt)
{
- drawctxt->flags |= CTXT_FLAGS_STATE_SHADOW;
-
build_regrestore_cmds(adreno_dev, drawctxt);
build_constantrestore_cmds(adreno_dev, drawctxt);
build_hlsqcontrol_restore_cmds(adreno_dev, drawctxt);
@@ -2338,8 +2336,6 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev,
kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
KGSL_CACHE_OP_FLUSH);
- drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
-
return 0;
}
@@ -2371,8 +2367,8 @@ static int a3xx_drawctxt_create(struct adreno_device *adreno_dev,
* Nothing to do here if the context is using preambles and doesn't need
* GMEM save/restore
*/
- if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) &&
- (drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) {
+ if ((drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE) &&
+ (drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC)) {
drawctxt->ops = &adreno_preamble_ctx_ops;
return 0;
}
@@ -2388,15 +2384,15 @@ static int a3xx_drawctxt_create(struct adreno_device *adreno_dev,
CONTEXT_SIZE);
tmp_ctx.cmd = drawctxt->gpustate.hostptr + CMD_OFFSET;
- if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE)) {
ret = a3xx_create_gpustate_shadow(adreno_dev, drawctxt);
if (ret)
goto done;
- drawctxt->flags |= CTXT_FLAGS_SHADER_SAVE;
+ set_bit(ADRENO_CONTEXT_SHADER_SAVE, &drawctxt->priv);
}
- if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC))
+ if (!(drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC))
ret = a3xx_create_gmem_shadow(adreno_dev, drawctxt);
done:
@@ -2415,7 +2411,7 @@ static int a3xx_drawctxt_save(struct adreno_device *adreno_dev,
if (context->state == ADRENO_CONTEXT_STATE_INVALID)
return 0;
- if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(context->base.flags & KGSL_CONTEXT_PREAMBLE)) {
/* Fixup self modifying IBs for save operations */
ret = adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE, context->save_fixup, 3);
@@ -2429,19 +2425,17 @@ static int a3xx_drawctxt_save(struct adreno_device *adreno_dev,
if (ret)
return ret;
- if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
+ if (test_bit(ADRENO_CONTEXT_SHADER_SAVE, &context->priv)) {
/* Save shader instructions */
ret = adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_PMODE, context->shader_save, 3);
if (ret)
return ret;
-
- context->flags |= CTXT_FLAGS_SHADER_RESTORE;
+ set_bit(ADRENO_CONTEXT_SHADER_RESTORE, &context->priv);
}
}
- if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
- (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
+ if (test_bit(ADRENO_CONTEXT_GMEM_SAVE, &context->priv)) {
/*
* Save GMEM (note: changes shader. shader must
* already be saved.)
@@ -2459,7 +2453,7 @@ static int a3xx_drawctxt_save(struct adreno_device *adreno_dev,
if (ret)
return ret;
- context->flags |= CTXT_FLAGS_GMEM_RESTORE;
+ set_bit(ADRENO_CONTEXT_GMEM_RESTORE, &context->priv);
}
return 0;
@@ -2481,7 +2475,7 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
* Shader must not already be restored.)
*/
- if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+ if (test_bit(ADRENO_CONTEXT_GMEM_RESTORE, &context->priv)) {
kgsl_cffdump_syncmem(context->base.device,
&context->gpustate,
context->context_gmem_shadow.gmem_restore[1],
@@ -2494,10 +2488,10 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
gmem_restore, 3);
if (ret)
return ret;
- context->flags &= ~CTXT_FLAGS_GMEM_RESTORE;
+ clear_bit(ADRENO_CONTEXT_GMEM_RESTORE, &context->priv);
}
- if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ if (!(context->base.flags & KGSL_CONTEXT_PREAMBLE)) {
ret = adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE, context->reg_restore, 3);
if (ret)
@@ -2516,12 +2510,13 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
if (ret)
return ret;
- if (context->flags & CTXT_FLAGS_SHADER_RESTORE)
+ if (test_bit(ADRENO_CONTEXT_SHADER_RESTORE, &context->priv)) {
ret = adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
context->shader_restore, 3);
if (ret)
return ret;
+ }
/* Restore HLSQ_CONTROL_0 register */
ret = adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
@@ -3137,7 +3132,6 @@ static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
device->pwrctrl.irq_last = 1;
queue_work(device->work_queue, &device->ts_expired_ws);
-
adreno_dispatcher_schedule(device);
}
@@ -3427,7 +3421,7 @@ static uint64_t a3xx_perfcounter_read(struct adreno_device *adreno_dev,
static struct {
void (*func)(struct adreno_device *, int);
} a3xx_irq_funcs[] = {
- A3XX_IRQ_CALLBACK(NULL), /* 0 - RBBM_GPU_IDLE */
+ A3XX_IRQ_CALLBACK(NULL), /* 0 - RBBM_GPU_IDLE */
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 1 - RBBM_AHB_ERROR */
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 2 - RBBM_REG_TIMEOUT */
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 3 - RBBM_ME_MS_TIMEOUT */
@@ -4036,6 +4030,9 @@ static void a3xx_start(struct adreno_device *adreno_dev)
/* Turn on the GPU busy counter and let it run free */
adreno_dev->gpu_cycles = 0;
+
+ /* the CP_DEBUG register offset and value are same as A2XX */
+ kgsl_regwrite(device, REG_CP_DEBUG, A2XX_CP_DEBUG_DEFAULT);
}
/**
@@ -4419,6 +4416,6 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
.coresight_enable = a3xx_coresight_enable,
.coresight_disable = a3xx_coresight_disable,
.coresight_config_debug_reg = a3xx_coresight_config_debug_reg,
- .postmortem_dump = a3xx_postmortem_dump,
.soft_reset = a3xx_soft_reset,
+ .postmortem_dump = a3xx_postmortem_dump,
};
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index 79431933ff9a..9f5765d16710 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -277,7 +277,6 @@ static int a3xx_snapshot_debugbus_block(struct kgsl_device *device,
struct kgsl_snapshot_debugbus *header = snapshot;
struct debugbus_block *block = priv;
- unsigned int val;
int i;
unsigned int *data = snapshot + sizeof(*header);
unsigned int dwords;
@@ -300,8 +299,6 @@ static int a3xx_snapshot_debugbus_block(struct kgsl_device *device,
return 0;
}
- val = (block->block_id << 8) | (1 << 16);
-
header->id = block->block_id;
header->count = dwords;
diff --git a/drivers/gpu/msm/adreno_a3xx_trace.h b/drivers/gpu/msm/adreno_a3xx_trace.h
index d48faf4717f6..75156e47274c 100644
--- a/drivers/gpu/msm/adreno_a3xx_trace.h
+++ b/drivers/gpu/msm/adreno_a3xx_trace.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -48,7 +48,7 @@ TRACE_EVENT(kgsl_a3xx_irq_status,
"d_name=%s status=%s",
__get_str(device_name),
__entry->status ? __print_flags(__entry->status, "|",
- { 1 << A3XX_INT_RBBM_AHB_ERROR, "RBBM_GPU_IDLE" },
+ { 1 << A3XX_INT_RBBM_GPU_IDLE, "RBBM_GPU_IDLE" },
{ 1 << A3XX_INT_RBBM_AHB_ERROR, "RBBM_AHB_ERR" },
{ 1 << A3XX_INT_RBBM_REG_TIMEOUT, "RBBM_REG_TIMEOUT" },
{ 1 << A3XX_INT_RBBM_ME_MS_TIMEOUT,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 12804a358f88..a7d1b7fb5f78 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -23,8 +23,6 @@
#include "a2xx_reg.h"
-unsigned int kgsl_cff_dump_enable;
-
DEFINE_SIMPLE_ATTRIBUTE(kgsl_cff_dump_enable_fops, kgsl_cff_dump_enable_get,
kgsl_cff_dump_enable_set, "%llu\n");
@@ -56,41 +54,6 @@ void adreno_debugfs_init(struct kgsl_device *device)
&adreno_dev->wait_timeout);
debugfs_create_u32("ib_check", 0644, device->d_debugfs,
&adreno_dev->ib_check_level);
- /* By Default enable fast hang detection */
- adreno_dev->fast_hang_detect = 1;
- debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
- &adreno_dev->fast_hang_detect);
- /*
- * FT policy can be set to any of the options below.
- * KGSL_FT_OFF -> BIT(0) Set to turn off FT
- * KGSL_FT_REPLAY -> BIT(1) Set to enable replay
- * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB
- * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
- * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
- * by default set FT policy to KGSL_FT_DEFAULT_POLICY
- */
- adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
- debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
- &adreno_dev->ft_policy);
- /* By default enable long IB detection */
- adreno_dev->long_ib_detect = 1;
- debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
- &adreno_dev->long_ib_detect);
-
- /*
- * FT pagefault policy can be set to any of the options below.
- * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
- * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on
- * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
- * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one
- * pagefault per page.
- * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
- * pagefault per INT.
- */
- adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
- debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
- &adreno_dev->ft_pf_policy);
-
debugfs_create_file("active_cnt", 0444, device->d_debugfs, device,
&_active_count_fops);
}
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 6b3e5902ca7f..ddf275c56cc2 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -233,7 +233,6 @@ static void dispatcher_queue_context(struct adreno_device *adreno_dev,
spin_lock(&dispatcher->plist_lock);
-
if (plist_node_empty(&drawctxt->pending)) {
/* Get a reference to the context while it sits on the list */
if (_kgsl_context_get(&drawctxt->base)) {
@@ -569,7 +568,7 @@ static int get_timestamp(struct adreno_context *drawctxt,
return 0;
}
- if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
+ if (drawctxt->base.flags & KGSL_CONTEXT_USER_GENERATED_TS) {
/*
* User specified timestamps need to be greater than the last
* issued timestamp in the context
@@ -586,7 +585,7 @@ static int get_timestamp(struct adreno_context *drawctxt,
}
/**
- * adreno_dispatcher_queue_cmd() - Queue a new command in the context
+ * adreno_dispactcher_queue_cmd() - Queue a new command in the context
* @adreno_dev: Pointer to the adreno device struct
* @drawctxt: Pointer to the adreno draw context
* @cmdbatch: Pointer to the command batch being submitted
@@ -613,10 +612,8 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
* to run (if it exists) regardless of the context state.
*/
- if (drawctxt->flags & CTXT_FLAGS_FORCE_PREAMBLE) {
+ if (test_and_clear_bit(ADRENO_CONTEXT_FORCE_PREAMBLE, &drawctxt->priv))
set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &cmdbatch->priv);
- drawctxt->flags &= ~CTXT_FLAGS_FORCE_PREAMBLE;
- }
/*
* If we are waiting for the end of frame and it hasn't appeared yet,
@@ -624,7 +621,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
* through the pipeline but it won't actually send any commands
*/
- if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
+ if (test_bit(ADRENO_CONTEXT_SKIP_EOF, &drawctxt->priv)) {
set_bit(CMDBATCH_FLAG_SKIP, &cmdbatch->priv);
/*
@@ -633,14 +630,13 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
*/
if (cmdbatch->flags & KGSL_CONTEXT_END_OF_FRAME) {
- drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
+ clear_bit(ADRENO_CONTEXT_SKIP_EOF, &drawctxt->priv);
/*
* Force the preamble on the next command to ensure that
* the state is correct
*/
-
- drawctxt->flags |= CTXT_FLAGS_FORCE_PREAMBLE;
+ set_bit(ADRENO_CONTEXT_FORCE_PREAMBLE, &drawctxt->priv);
}
}
@@ -686,10 +682,10 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
/*
* Set the fault tolerance policy for the command batch - assuming the
- * context hsn't disabled FT use the current device policy
+ * context hasn't disabled FT use the current device policy
*/
- if (drawctxt->flags & CTXT_FLAGS_NO_FAULT_TOLERANCE)
+ if (drawctxt->base.flags & KGSL_CONTEXT_NO_FAULT_TOLERANCE)
set_bit(KGSL_FT_DISABLE, &cmdbatch->fault_policy);
else
cmdbatch->fault_policy = adreno_dev->ft_policy;
@@ -723,6 +719,44 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,
return 0;
}
+static int _mark_context(int id, void *ptr, void *data)
+{
+ unsigned int guilty = *((unsigned int *) data);
+ struct kgsl_context *context = ptr;
+
+ /*
+ * If the context is guilty mark it as such. Otherwise mark it as
+ * innocent if it had not already been marked as guilty. If id is
+ * passed as 0 then mark EVERYBODY guilty (recovery failed)
+ */
+
+ if (guilty == 0 || guilty == context->id)
+ context->reset_status =
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT;
+ else if (context->reset_status !=
+ KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT)
+ context->reset_status =
+ KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
+
+ return 0;
+}
+
+/**
+ * mark_guilty_context() - Mark the given context as guilty (failed recovery)
+ * @device: Pointer to a KGSL device structure
+ * @id: Context ID of the guilty context (or 0 to mark all as guilty)
+ *
+ * Mark the given (or all) context(s) as guilty (failed recovery)
+ */
+static void mark_guilty_context(struct kgsl_device *device, unsigned int id)
+{
+ /* Mark the status for all the contexts in the device */
+
+ read_lock(&device->context_lock);
+ idr_for_each(&device->context_idr, _mark_context, &id);
+ read_unlock(&device->context_lock);
+}
+
/*
* If an IB inside of the command batch has a gpuaddr that matches the base
* passed in then zero the size which effectively skips it when it is submitted
@@ -781,7 +815,7 @@ static void cmdbatch_skip_frame(struct kgsl_cmdbatch *cmdbatch,
*/
if (skip && drawctxt)
- drawctxt->flags |= CTXT_FLAGS_SKIP_EOF;
+ set_bit(ADRENO_CONTEXT_SKIP_EOF, &drawctxt->priv);
/*
* If we did see the EOF flag then force the preamble on for the
@@ -789,7 +823,7 @@ static void cmdbatch_skip_frame(struct kgsl_cmdbatch *cmdbatch,
*/
if (!skip && drawctxt)
- drawctxt->flags |= CTXT_FLAGS_FORCE_PREAMBLE;
+ set_bit(ADRENO_CONTEXT_FORCE_PREAMBLE, &drawctxt->priv);
}
static void remove_invalidated_cmdbatches(struct kgsl_device *device,
@@ -956,6 +990,9 @@ static int dispatcher_do_fault(struct kgsl_device *device)
if (replay == NULL) {
unsigned int ptr = dispatcher->head;
+ /* Recovery failed - mark everybody guilty */
+ mark_guilty_context(device, 0);
+
while (ptr != dispatcher->tail) {
struct kgsl_context *context =
dispatcher->cmdqueue[ptr]->context;
@@ -1028,6 +1065,7 @@ static int dispatcher_do_fault(struct kgsl_device *device)
pr_fault(device, cmdbatch, "gpu skipped ctx %d ts %d\n",
cmdbatch->context->id, cmdbatch->timestamp);
+ mark_guilty_context(device, cmdbatch->context->id);
adreno_drawctxt_invalidate(device, cmdbatch->context);
}
@@ -1123,6 +1161,9 @@ static int dispatcher_do_fault(struct kgsl_device *device)
pr_fault(device, cmdbatch, "gpu failed ctx %d ts %d\n",
cmdbatch->context->id, cmdbatch->timestamp);
+ /* Mark the context as failed */
+ mark_guilty_context(device, cmdbatch->context->id);
+
/* Invalidate the context */
adreno_drawctxt_invalidate(device, cmdbatch->context);
@@ -1183,6 +1224,9 @@ replay:
"gpu reset failed ctx %d ts %d\n",
replay[i]->context->id, replay[i]->timestamp);
+ /* Mark this context as guilty (failed recovery) */
+ mark_guilty_context(device, replay[i]->context->id);
+
adreno_drawctxt_invalidate(device, replay[i]->context);
remove_invalidated_cmdbatches(device, &replay[i],
count - i);
@@ -1239,6 +1283,7 @@ static void adreno_dispatcher_work(struct work_struct *work)
container_of(dispatcher, struct adreno_device, dispatcher);
struct kgsl_device *device = &adreno_dev->dev;
int count = 0;
+ int last_context = KGSL_CONTEXT_INVALID;
int fault_handled = 0;
mutex_lock(&dispatcher->mutex);
@@ -1270,12 +1315,22 @@ static void adreno_dispatcher_work(struct work_struct *work)
* successful completion to the world
*/
- if (cmdbatch->fault_recovery != 0)
+ if (cmdbatch->fault_recovery != 0) {
+ struct adreno_context *drawctxt =
+ ADRENO_CONTEXT(cmdbatch->context);
+
+ /* Mark the context as faulted and recovered */
+ set_bit(ADRENO_CONTEXT_FAULT, &drawctxt->priv);
+
_print_recovery(device, cmdbatch);
+ }
trace_adreno_cmdbatch_retired(cmdbatch,
dispatcher->inflight - 1);
+ /* Remember the last context that got retired */
+ last_context = cmdbatch->context->id;
+
/* Reduce the number of inflight command batches */
dispatcher->inflight--;
@@ -1324,7 +1379,7 @@ static void adreno_dispatcher_work(struct work_struct *work)
*/
if (!adreno_dev->long_ib_detect ||
- drawctxt->flags & CTXT_FLAGS_NO_FAULT_TOLERANCE)
+ drawctxt->base.flags & KGSL_CONTEXT_NO_FAULT_TOLERANCE)
break;
/*
@@ -1380,6 +1435,18 @@ done:
/* Update the timeout timer for the next command batch */
mod_timer(&dispatcher->timer, cmdbatch->expires);
+ /*
+ * if the context for the next pending cmdbatch is different
+ * than the last one we retired, then trace it as a GPU switch
+ */
+
+ if (cmdbatch->context->id != last_context) {
+ u64 now = ktime_to_ns(ktime_get());
+ kgsl_trace_gpu_sched_switch(device->name, now,
+ cmdbatch->context->id, cmdbatch->priority,
+ cmdbatch->timestamp);
+ }
+
/* There are still things in flight - update the idle counts */
mutex_lock(&device->mutex);
kgsl_pwrscale_idle(device);
@@ -1498,7 +1565,6 @@ void adreno_dispatcher_irq_fault(struct kgsl_device *device)
* adreno_dispatcher_start() - activate the dispatcher
* @adreno_dev: pointer to the adreno device structure
*
- * Set the disaptcher active and start the loop once to get things going
*/
void adreno_dispatcher_start(struct kgsl_device *device)
{
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 1cd24e5871bc..fa03a06cf6c6 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -412,6 +412,7 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
int ret;
drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
+
if (drawctxt == NULL)
return ERR_PTR(-ENOMEM);
@@ -424,7 +425,7 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
drawctxt->bin_base_offset = 0;
drawctxt->timestamp = 0;
- *flags &= (KGSL_CONTEXT_PREAMBLE |
+ drawctxt->base.flags = *flags & (KGSL_CONTEXT_PREAMBLE |
KGSL_CONTEXT_NO_GMEM_ALLOC |
KGSL_CONTEXT_PER_CONTEXT_TS |
KGSL_CONTEXT_USER_GENERATED_TS |
@@ -433,20 +434,7 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
KGSL_CONTEXT_PWR_CONSTRAINT);
/* Always enable per-context timestamps */
- *flags |= KGSL_CONTEXT_PER_CONTEXT_TS;
- drawctxt->flags |= CTXT_FLAGS_PER_CONTEXT_TS;
-
- if (*flags & KGSL_CONTEXT_PREAMBLE)
- drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
-
- if (*flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
- drawctxt->flags |= CTXT_FLAGS_NOGMEMALLOC;
-
- if (*flags & KGSL_CONTEXT_USER_GENERATED_TS)
- drawctxt->flags |= CTXT_FLAGS_USER_GENERATED_TS;
-
- if (*flags & KGSL_CONTEXT_PWR_CONSTRAINT)
- drawctxt->flags |= CTXT_FLAGS_PWR_CONSTRAINT;
+ drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS;
mutex_init(&drawctxt->mutex);
init_waitqueue_head(&drawctxt->wq);
@@ -460,18 +448,12 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
plist_node_init(&drawctxt->pending, ADRENO_CONTEXT_DEFAULT_PRIORITY);
- if (*flags & KGSL_CONTEXT_NO_FAULT_TOLERANCE)
- drawctxt->flags |= CTXT_FLAGS_NO_FAULT_TOLERANCE;
-
- drawctxt->type =
- (*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
-
if (adreno_dev->gpudev->ctxt_create) {
ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
if (ret)
goto err;
- } else if ((*flags & KGSL_CONTEXT_PREAMBLE) == 0 ||
- (*flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) {
+ } else if ((drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE) == 0 ||
+ (drawctxt->base.flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) {
KGSL_DEV_ERR_ONCE(device,
"legacy context switch not supported\n");
ret = -EINVAL;
@@ -487,7 +469,8 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
kgsl_sharedmem_writel(device, &device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
0);
-
+ /* copy back whatever flags we dediced were valid */
+ *flags = drawctxt->base.flags;
return &drawctxt->base;
err:
kgsl_context_detach(&drawctxt->base);
@@ -715,10 +698,10 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
if (flags & KGSL_CONTEXT_SAVE_GMEM)
/* Set the flag in context so that the save is done
* when this context is switched out. */
- drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE;
+ set_bit(ADRENO_CONTEXT_GMEM_SAVE, &drawctxt->priv);
else
/* Remove GMEM saving flag from the context */
- drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE;
+ clear_bit(ADRENO_CONTEXT_GMEM_SAVE, &drawctxt->priv);
}
/* already current? */
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 670b0db49cbf..97147c0e40d7 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -16,46 +16,6 @@
#include "adreno_pm4types.h"
#include "a2xx_reg.h"
-/* Flags */
-
-#define CTXT_FLAGS_NOT_IN_USE 0x00000000
-#define CTXT_FLAGS_IN_USE BIT(0)
-
-/* state shadow memory allocated */
-#define CTXT_FLAGS_STATE_SHADOW BIT(1)
-
-/* gmem shadow memory allocated */
-#define CTXT_FLAGS_GMEM_SHADOW BIT(2)
-/* gmem must be copied to shadow */
-#define CTXT_FLAGS_GMEM_SAVE BIT(3)
-/* gmem can be restored from shadow */
-#define CTXT_FLAGS_GMEM_RESTORE BIT(4)
-/* preamble packed in cmdbuffer for context switching */
-#define CTXT_FLAGS_PREAMBLE BIT(5)
-/* shader must be copied to shadow */
-#define CTXT_FLAGS_SHADER_SAVE BIT(6)
-/* shader can be restored from shadow */
-#define CTXT_FLAGS_SHADER_RESTORE BIT(7)
-/* Context has caused a GPU hang */
-#define CTXT_FLAGS_GPU_HANG BIT(8)
-/* Specifies there is no need to save GMEM */
-#define CTXT_FLAGS_NOGMEMALLOC BIT(9)
-/* Trash state for context */
-#define CTXT_FLAGS_TRASHSTATE BIT(10)
-/* per context timestamps enabled */
-#define CTXT_FLAGS_PER_CONTEXT_TS BIT(11)
-/* Context has caused a GPU hang and fault tolerance successful */
-#define CTXT_FLAGS_GPU_HANG_FT BIT(12)
-/* User mode generated timestamps enabled */
-#define CTXT_FLAGS_USER_GENERATED_TS BIT(14)
-/* Context skip till EOF */
-#define CTXT_FLAGS_SKIP_EOF BIT(15)
-/* Context no fault tolerance */
-#define CTXT_FLAGS_NO_FAULT_TOLERANCE BIT(16)
-/* Force the preamble for the next submission */
-#define CTXT_FLAGS_FORCE_PREAMBLE BIT(17)
-/* power constraints enabled */
-#define CTXT_FLAGS_PWR_CONSTRAINT BIT(18)
/* Symbolic table for the adreno draw context type */
#define ADRENO_DRAWCTXT_TYPES \
@@ -132,7 +92,7 @@ extern const struct adreno_context_ops adreno_preamble_ctx_ops;
* @internal_timestamp: Global timestamp of the last issued command
* NOTE: guarded by device->mutex, not drawctxt->mutex!
* @state: Current state of the context
- * @flags: Bitfield controlling behavior of the context
+ * @priv: Internal flags
* @type: Context type (GL, CL, RS)
* @mutex: Mutex to protect the cmdqueue
* @pagetable: Pointer to the GPU pagetable for the context
@@ -171,7 +131,7 @@ struct adreno_context {
unsigned int timestamp;
unsigned int internal_timestamp;
int state;
- uint32_t flags;
+ unsigned long priv;
unsigned int type;
struct mutex mutex;
struct kgsl_memdesc gpustate;
@@ -202,8 +162,8 @@ struct adreno_context {
/* Dispatcher */
struct kgsl_cmdbatch *cmdqueue[ADRENO_CONTEXT_CMDQUEUE_SIZE];
- int cmdqueue_head;
- int cmdqueue_tail;
+ unsigned int cmdqueue_head;
+ unsigned int cmdqueue_tail;
struct plist_node pending;
wait_queue_head_t wq;
@@ -214,6 +174,31 @@ struct adreno_context {
const struct adreno_context_ops *ops;
};
+/**
+ * enum adreno_context_priv - Private flags for an adreno draw context
+ * @ADRENO_CONTEXT_FAULT - set if the context has faulted (and recovered)
+ * @ADRENO_CONTEXT_GMEM_SAVE - gmem must be copied to shadow
+ * @ADRENO_CONTEXT_GMEM_RESTORE - gmem can be restored from shadow
+ * @ADRENO_CONTEXT_SHADER_SAVE - shader must be copied to shadow
+ * @ADRENO_CONTEXT_SHADER_RESTORE - shader can be restored from shadow
+ * @ADRENO_CONTEXT_GPU_HANG - Context has caused a GPU hang
+ * @ADRENO_CONTEXT_GPU_HANG_FT - Context has caused a GPU hang
+ * and fault tolerance was successful
+ * @ADRENO_CONTEXT_SKIP_EOF - Context skip IBs until the next end of frame
+ * marker.
+ * @ADRENO_CONTEXT_FORCE_PREAMBLE - Force the preamble for the next submission.
+ */
+enum adreno_context_priv {
+ ADRENO_CONTEXT_FAULT = 0,
+ ADRENO_CONTEXT_GMEM_SAVE,
+ ADRENO_CONTEXT_GMEM_RESTORE,
+ ADRENO_CONTEXT_SHADER_SAVE,
+ ADRENO_CONTEXT_SHADER_RESTORE,
+ ADRENO_CONTEXT_GPU_HANG,
+ ADRENO_CONTEXT_GPU_HANG_FT,
+ ADRENO_CONTEXT_SKIP_EOF,
+ ADRENO_CONTEXT_FORCE_PREAMBLE,
+};
struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
uint32_t *flags);
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index e6ec91df079e..37c3c50a6f2c 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -143,10 +143,10 @@
#define CP_IM_STORE 0x2c
/* test 2 memory locations to dword values specified */
-#define CP_TEST_TWO_MEMS 0x71
+#define CP_TEST_TWO_MEMS 0x71
/* PFP waits until the FIFO between the PFP and the ME is empty */
-#define CP_WAIT_FOR_ME 0x13
+#define CP_WAIT_FOR_ME 0x13
/*
* for a20x
@@ -164,6 +164,8 @@
#define CP_SET_PROTECTED_MODE 0x5f /* sets the register protection mode */
+#define CP_BOOTSTRAP_UCODE 0x6f /* bootstraps microcode */
+
/*
* for a3xx
*/
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 2c9b968a1984..9e807cbe5a22 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -12,6 +12,7 @@
*/
#include <linux/vmalloc.h>
+#include <mach/board.h>
#include "kgsl.h"
#include "kgsl_sharedmem.h"
@@ -51,6 +52,7 @@ static const struct pm_id_name pm3_types[] = {
{CP_DRAW_INDX, "DRW_NDX_"},
{CP_DRAW_INDX_BIN, "DRW_NDXB"},
{CP_EVENT_WRITE, "EVENT_WT"},
+ {CP_MEM_WRITE, "MEM_WRIT"},
{CP_IM_LOAD, "IN__LOAD"},
{CP_IM_LOAD_IMMEDIATE, "IM_LOADI"},
{CP_IM_STORE, "IM_STORE"},
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 32dd0149b13a..bd5c6095283f 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -30,14 +30,6 @@
#define GSL_RB_NOP_SIZEDWORDS 2
-/*
- * CP DEBUG settings for all cores:
- * DYNAMIC_CLK_DISABLE [27] - turn off the dynamic clock control
- * PROG_END_PTR_ENABLE [25] - Allow 128 bit writes to the VBIF
- */
-
-#define CP_DEBUG_DEFAULT ((1 << 27) | (1 << 25))
-
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
@@ -215,28 +207,19 @@ err:
* adreno_ringbuffer_load_pm4_ucode() - Load pm4 ucode
* @device: Pointer to a KGSL device
* @start: Starting index in pm4 ucode to load
+ * @end: Ending index of pm4 ucode to load
* @addr: Address to load the pm4 ucode
*
* Load the pm4 ucode from @start at @addr.
*/
-int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device,
- unsigned int start, unsigned int addr)
+inline int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device,
+ unsigned int start, unsigned int end, unsigned int addr)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int i;
- if (adreno_dev->pm4_fw == NULL) {
- int ret = adreno_ringbuffer_read_pm4_ucode(device);
- if (ret)
- return ret;
- }
-
- KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n",
- adreno_dev->pm4_fw_version);
-
- adreno_writereg(adreno_dev, ADRENO_REG_CP_DEBUG, CP_DEBUG_DEFAULT);
adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_WADDR, addr);
- for (i = 1; i < adreno_dev->pm4_fw_size; i++)
+ for (i = start; i < end; i++)
adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_DATA,
adreno_dev->pm4_fw[i]);
@@ -278,27 +261,19 @@ err:
* adreno_ringbuffer_load_pfp_ucode() - Load pfp ucode
* @device: Pointer to a KGSL device
* @start: Starting index in pfp ucode to load
+ * @end: Ending index of pfp ucode to load
* @addr: Address to load the pfp ucode
*
* Load the pfp ucode from @start at @addr.
*/
-int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device,
- unsigned int start, unsigned int addr)
+inline int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device,
+ unsigned int start, unsigned int end, unsigned int addr)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int i;
- if (adreno_dev->pfp_fw == NULL) {
- int ret = adreno_ringbuffer_read_pfp_ucode(device);
- if (ret)
- return ret;
- }
-
- KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n",
- adreno_dev->pfp_fw_version);
-
adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_ADDR, addr);
- for (i = 1; i < adreno_dev->pfp_fw_size; i++)
+ for (i = start; i < end; i++)
adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_DATA,
adreno_dev->pfp_fw[i]);
@@ -306,19 +281,95 @@ int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device,
}
/**
- * _ringbuffer_start_common() - Ringbuffer start
+ * _ringbuffer_bootstrap_ucode() - Bootstrap GPU Ucode
* @rb: Pointer to adreno ringbuffer
+ * @load_jt: If non zero only load Jump tables
*
- * Setup ringbuffer for GPU.
+ * Bootstrap ucode for GPU
+ * load_jt == 0, bootstrap full microcode
+ * load_jt == 1, bootstrap jump tables of microcode
+ *
+ * For example a bootstrap packet would like below
+ * Setup a type3 bootstrap packet
+ * PFP size to bootstrap
+ * PFP addr to write the PFP data
+ * PM4 size to bootstrap
+ * PM4 addr to write the PM4 data
+ * PFP dwords from microcode to bootstrap
+ * PM4 size dwords from microcode to bootstrap
*/
-int _ringbuffer_start_common(struct adreno_ringbuffer *rb)
+static int _ringbuffer_bootstrap_ucode(struct adreno_ringbuffer *rb,
+ unsigned int load_jt)
{
- int status;
+ unsigned int *cmds, cmds_gpu, bootstrap_size;
+ int i = 0;
struct kgsl_device *device = rb->device;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ unsigned int pm4_size, pm4_idx, pm4_addr, pfp_size, pfp_idx, pfp_addr;
+
+ /* Only bootstrap jump tables of ucode */
+ if (load_jt) {
+ pm4_idx = adreno_dev->pm4_jt_idx;
+ pm4_addr = adreno_dev->pm4_jt_addr;
+ pfp_idx = adreno_dev->pfp_jt_idx;
+ pfp_addr = adreno_dev->pfp_jt_addr;
+ } else {
+ /* Bootstrap full ucode */
+ pm4_idx = 1;
+ pm4_addr = 0;
+ pfp_idx = 1;
+ pfp_addr = 0;
+ }
- if (rb->flags & KGSL_FLAGS_STARTED)
- return 0;
+ pm4_size = (adreno_dev->pm4_fw_size - pm4_idx);
+ pfp_size = (adreno_dev->pfp_fw_size - pfp_idx);
+
+ /*
+ * Below set of commands register with PFP that 6f is the
+ * opcode for bootstrapping
+ */
+ adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_ADDR, 0x200);
+ adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_DATA, 0x6f0005);
+
+ /* clear ME_HALT to start micro engine */
+ adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, 0);
+
+ bootstrap_size = (pm4_size + pfp_size + 5);
+
+ cmds = adreno_ringbuffer_allocspace(rb, NULL, bootstrap_size);
+ if (cmds == NULL)
+ return -ENOMEM;
+
+ cmds_gpu = rb->buffer_desc.gpuaddr +
+ sizeof(uint) * (rb->wptr - bootstrap_size);
+ /* Construct the packet that bootsraps the ucode */
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu,
+ cp_type3_packet(CP_BOOTSTRAP_UCODE,
+ (bootstrap_size - 1)));
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, pfp_size);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, pfp_addr);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, pm4_size);
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, pm4_addr);
+ for (i = pfp_idx; i < adreno_dev->pfp_fw_size; i++)
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, adreno_dev->pfp_fw[i]);
+ for (i = pm4_idx; i < adreno_dev->pm4_fw_size; i++)
+ GSL_RB_WRITE(rb->device, cmds, cmds_gpu, adreno_dev->pm4_fw[i]);
+
+ adreno_ringbuffer_submit(rb);
+ /* idle device to validate bootstrap */
+ return adreno_idle(device);
+}
+
+/**
+ * _ringbuffer_setup_common() - Ringbuffer start
+ * @rb: Pointer to adreno ringbuffer
+ *
+ * Setup ringbuffer for GPU.
+ */
+void _ringbuffer_setup_common(struct adreno_ringbuffer *rb)
+{
+ struct kgsl_device *device = rb->device;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
kgsl_sharedmem_set(rb->device, &rb->buffer_desc, 0, 0xAA,
(rb->sizedwords << 2));
@@ -359,6 +410,19 @@ int _ringbuffer_start_common(struct adreno_ringbuffer *rb)
kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
rb->wptr = 0;
+}
+
+/**
+ * _ringbuffer_start_common() - Ringbuffer start
+ * @rb: Pointer to adreno ringbuffer
+ *
+ * Start ringbuffer for GPU.
+ */
+int _ringbuffer_start_common(struct adreno_ringbuffer *rb)
+{
+ int status;
+ struct kgsl_device *device = rb->device;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
/* clear ME_HALT to start micro engine */
adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, 0);
@@ -390,39 +454,99 @@ int adreno_ringbuffer_warm_start(struct adreno_ringbuffer *rb)
struct kgsl_device *device = rb->device;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- /* load the CP ucode */
- status = adreno_ringbuffer_load_pm4_ucode(device,
- adreno_dev->pm4_jt_idx, adreno_dev->pm4_jt_addr);
- if (status != 0)
- return status;
+ if (rb->flags & KGSL_FLAGS_STARTED)
+ return 0;
- /* load the prefetch parser ucode */
- status = adreno_ringbuffer_load_pfp_ucode(device,
- adreno_dev->pfp_jt_idx, adreno_dev->pfp_jt_addr);
- if (status != 0)
- return status;
+ _ringbuffer_setup_common(rb);
- return _ringbuffer_start_common(rb);
+ /* If bootstrapping if supported to load jump tables */
+ if (adreno_bootstrap_ucode(adreno_dev)) {
+ status = _ringbuffer_bootstrap_ucode(rb, 1);
+ if (status != 0)
+ return status;
+
+ } else {
+ /* load the CP jump tables using AHB writes */
+ status = adreno_ringbuffer_load_pm4_ucode(device,
+ adreno_dev->pm4_jt_idx, adreno_dev->pm4_fw_size,
+ adreno_dev->pm4_jt_addr);
+ if (status != 0)
+ return status;
+
+ /* load the prefetch parser jump tables using AHB writes */
+ status = adreno_ringbuffer_load_pfp_ucode(device,
+ adreno_dev->pfp_jt_idx, adreno_dev->pfp_fw_size,
+ adreno_dev->pfp_jt_addr);
+ if (status != 0)
+ return status;
+ }
+
+ status = _ringbuffer_start_common(rb);
+
+ return status;
}
-int adreno_ringbuffer_start(struct adreno_ringbuffer *rb)
+/**
+ * adreno_ringbuffer_cold_start() - Ringbuffer cold start
+ * @rb: Pointer to adreno ringbuffer
+ *
+ * Start the ringbuffer from power collapse.
+ */
+int adreno_ringbuffer_cold_start(struct adreno_ringbuffer *rb)
{
int status;
+ struct kgsl_device *device = rb->device;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
if (rb->flags & KGSL_FLAGS_STARTED)
return 0;
- /* load the CP ucode */
- status = adreno_ringbuffer_load_pm4_ucode(rb->device, 1, 0);
- if (status != 0)
- return status;
+ _ringbuffer_setup_common(rb);
- /* load the prefetch parser ucode */
- status = adreno_ringbuffer_load_pfp_ucode(rb->device, 1, 0);
- if (status != 0)
- return status;
+ /* If bootstrapping if supported to load ucode */
+ if (adreno_bootstrap_ucode(adreno_dev)) {
+
+ /*
+ * load first adreno_dev->pm4_bstrp_size +
+ * adreno_dev->pfp_bstrp_size microcode dwords using AHB write,
+ * this small microcode has dispatcher + booter, this initial
+ * microcode enables CP to understand CP_BOOTSTRAP_UCODE packet
+ * in function _ringbuffer_bootstrap_ucode. CP_BOOTSTRAP_UCODE
+ * packet loads rest of the microcode.
+ */
+
+ status = adreno_ringbuffer_load_pm4_ucode(rb->device, 1,
+ adreno_dev->pm4_bstrp_size+1, 0);
+ if (status != 0)
+ return status;
+
+ status = adreno_ringbuffer_load_pfp_ucode(rb->device, 1,
+ adreno_dev->pfp_bstrp_size+1, 0);
+ if (status != 0)
+ return status;
+
+ /* Bootstrap rest of the ucode here */
+ status = _ringbuffer_bootstrap_ucode(rb, 0);
+ if (status != 0)
+ return status;
+
+ } else {
+ /* load the CP ucode using AHB writes */
+ status = adreno_ringbuffer_load_pm4_ucode(rb->device, 1,
+ adreno_dev->pm4_fw_size, 0);
+ if (status != 0)
+ return status;
+
+ /* load the prefetch parser ucode using AHB writes */
+ status = adreno_ringbuffer_load_pfp_ucode(rb->device, 1,
+ adreno_dev->pfp_fw_size, 0);
+ if (status != 0)
+ return status;
+ }
- return _ringbuffer_start_common(rb);
+ status = _ringbuffer_start_common(rb);
+
+ return status;
}
void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb)
@@ -545,6 +669,9 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
total_sizedwords += 3; /* sop timestamp */
total_sizedwords += 4; /* eop timestamp */
+ if (adreno_is_a20x(adreno_dev))
+ total_sizedwords += 2; /* CACHE_FLUSH */
+
if (drawctxt) {
total_sizedwords += 3; /* global timestamp without cache
* flush for non-zero context */
@@ -660,7 +787,8 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr +
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp)));
- GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, rb->global_ts);
+ GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
+ rb->global_ts);
}
if (adreno_is_a20x(adreno_dev)) {
@@ -965,7 +1093,7 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
timestamp);
if (ret)
- KGSL_DRV_ERR(device, "adreno_dispatcher_queue_cmd returned %d\n",
+ KGSL_DRV_ERR(device, "adreno_context_queue_cmd returned %d\n",
ret);
else {
/*
@@ -984,6 +1112,13 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
}
}
+ /*
+ * Return -EPROTO if the device has faulted since the last time we
+ * checked - userspace uses this to perform post-fault activities
+ */
+ if (!ret && test_and_clear_bit(ADRENO_CONTEXT_FAULT, &drawctxt->priv))
+ ret = -EPROTO;
+
return ret;
}
@@ -1017,14 +1152,12 @@ void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
{
unsigned int constraint;
struct kgsl_context *context = cmdbatch->context;
- struct adreno_context *drawctxt;
- drawctxt = ADRENO_CONTEXT(context);
/*
* Check if the context has a constraint and constraint flags are
* set.
*/
if (context->pwr_constraint.type &&
- ((drawctxt->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
+ ((context->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
(cmdbatch->flags & KGSL_CONTEXT_PWR_CONSTRAINT))) {
constraint = adreno_ringbuffer_get_constraint(device, context);
@@ -1076,7 +1209,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
commands are stored in the first node of the IB chain. We can skip that
if a context switch hasn't occured */
- if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) &&
+ if ((drawctxt->base.flags & KGSL_CONTEXT_PREAMBLE) &&
!test_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &cmdbatch->priv) &&
(adreno_dev->drawctxt_active == drawctxt))
start_index = 1;
@@ -1181,7 +1314,7 @@ done:
device->pwrctrl.irq_last = 0;
kgsl_trace_issueibcmds(device, context->id, cmdbatch,
cmdbatch->timestamp, cmdbatch->flags, ret,
- drawctxt ? drawctxt->type : 0);
+ drawctxt->type);
kfree(link);
return ret;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index b7169495722f..697e113c576d 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -73,7 +73,7 @@ int adreno_ringbuffer_init(struct kgsl_device *device);
int adreno_ringbuffer_warm_start(struct adreno_ringbuffer *rb);
-int adreno_ringbuffer_start(struct adreno_ringbuffer *rb);
+int adreno_ringbuffer_cold_start(struct adreno_ringbuffer *rb);
void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index c5e7556e7fc4..cdea8ac1fb88 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -20,7 +20,6 @@
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/dma-buf.h>
-
#include <linux/vmalloc.h>
#include <linux/pm_runtime.h>
#include <linux/genlock.h>
@@ -41,6 +40,7 @@
#include "kgsl_device.h"
#include "kgsl_trace.h"
#include "kgsl_sync.h"
+#include "adreno.h"
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "kgsl."
@@ -513,31 +513,29 @@ EXPORT_SYMBOL(kgsl_context_init);
*/
int kgsl_context_detach(struct kgsl_context *context)
{
- struct kgsl_device *device;
int ret;
- if (context == NULL || kgsl_context_detached(context))
+ if (context == NULL)
return -EINVAL;
- device = context->device;
-
- trace_kgsl_context_detach(device, context);
-
/*
* Mark the context as detached to keep others from using
- * the context before it gets fully removed
+ * the context before it gets fully removed, and to make sure
+ * we don't try to detach twice.
*/
- set_bit(KGSL_CONTEXT_DETACHED, &context->priv);
+ if (test_and_set_bit(KGSL_CONTEXT_DETACHED, &context->priv))
+ return -EINVAL;
+
+ trace_kgsl_context_detach(context->device, context);
- ret = device->ftbl->drawctxt_detach(context);
+ ret = context->device->ftbl->drawctxt_detach(context);
/*
* Cancel events after the device-specific context is
* detached, to avoid possibly freeing memory while
* it is still in use by the GPU.
*/
-
- kgsl_context_cancel_events(device, context);
+ kgsl_context_cancel_events(context->device, context);
kgsl_context_put(context);
@@ -842,7 +840,7 @@ kgsl_process_private_put(struct kgsl_process_private *private)
return;
}
-/*
+/**
* find_process_private() - Helper function to search for process private
* @cur_dev_priv: Pointer to device private structure which contains pointers
* to device and process_private structs.
@@ -883,7 +881,7 @@ done:
return private;
}
-/*
+/**
* kgsl_get_process_private() - Used to find the process private structure
* @cur_dev_priv: Current device pointer
* Finds or creates a new porcess private structire and initializes its members
@@ -897,13 +895,12 @@ kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv)
private = kgsl_find_process_private(cur_dev_priv);
+ if (!private)
+ return NULL;
+
mutex_lock(&private->process_private_mutex);
- /*
- * If debug root initialized then it means the rest of the fields
- * are also initialized
- */
- if (private->debug_root)
+ if (test_bit(KGSL_PROCESS_INIT, &private->priv))
goto done;
private->mem_rb = RB_ROOT;
@@ -924,6 +921,8 @@ kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv)
if (kgsl_process_init_debugfs(private))
goto error;
+ set_bit(KGSL_PROCESS_INIT, &private->priv);
+
done:
mutex_unlock(&private->process_private_mutex);
return private;
@@ -1027,6 +1026,7 @@ static int kgsl_release(struct inode *inodep, struct file *filep)
result = kgsl_close_device(device);
mutex_unlock(&device->mutex);
+
kfree(dev_priv);
kgsl_process_private_put(private);
@@ -1305,10 +1305,12 @@ kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id)
static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry)
{
bool ret = false;
+
+ if (entry == NULL)
+ return false;
+
spin_lock(&entry->priv->mem_lock);
- if (entry && entry->pending_free) {
- ret = false;
- } else if (entry) {
+ if (!entry->pending_free) {
entry->pending_free = 1;
ret = true;
}
@@ -1363,6 +1365,7 @@ static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
result = -EINVAL;
break;
}
+
/*
* Copy the reset status to value which also serves as
* the out parameter
@@ -1931,7 +1934,8 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device,
/**
* _kgsl_cmdbatch_verify() - Perform a quick sanity check on a command batch
- * @device: Pointer to a KGSL device that owns the command batch
+ * @device: Pointer to a KGSL instance that owns the command batch
+ * @pagetable: Pointer to the pagetable for the current process
* @cmdbatch: Number of indirect buffers to make room for in the cmdbatch
*
* Do a quick sanity test on the list of indirect buffers in a command batch
@@ -1941,7 +1945,6 @@ static bool _kgsl_cmdbatch_verify(struct kgsl_device_private *dev_priv,
struct kgsl_cmdbatch *cmdbatch)
{
int i;
-
struct kgsl_process_private *private = dev_priv->process_priv;
for (i = 0; i < cmdbatch->ibcount; i++) {
@@ -2106,7 +2109,11 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
cmdbatch, ¶m->timestamp);
free_cmdbatch:
- if (result)
+ /*
+ * -EPROTO is a "success" error - it just tells the user that the
+ * context had previously faulted
+ */
+ if (result && result != -EPROTO)
kgsl_cmdbatch_destroy(cmdbatch);
done:
@@ -2154,7 +2161,11 @@ static long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv,
cmdbatch, ¶m->timestamp);
free_cmdbatch:
- if (result)
+ /*
+ * -EPROTO is a "success" error - it just tells the user that the
+ * context had previously faulted
+ */
+ if (result && result != -EPROTO)
kgsl_cmdbatch_destroy(cmdbatch);
done:
@@ -2363,6 +2374,11 @@ static long kgsl_ioctl_gpumem_free_id(struct kgsl_device_private *dev_priv,
trace_kgsl_mem_free(entry);
+ kgsl_memfree_hist_set_event(entry->priv->pid,
+ entry->memdesc.gpuaddr,
+ entry->memdesc.size,
+ entry->memdesc.flags);
+
/*
* First kgsl_mem_entry_put is for the reference that we took in
* this function when calling kgsl_sharedmem_find_id, second one is
@@ -2445,10 +2461,8 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry,
ret = -ERANGE;
- if (phys == 0) {
- KGSL_CORE_ERR("kgsl_get_phys_file returned phys=0\n");
+ if (phys == 0)
goto err;
- }
/* Make sure the length of the region, the offset and the desired
* size are all page aligned or bail
@@ -2456,19 +2470,13 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry,
if ((len & ~PAGE_MASK) ||
(offset & ~PAGE_MASK) ||
(size & ~PAGE_MASK)) {
- KGSL_CORE_ERR("length %lu, offset %u or size %u "
- "is not page aligned\n",
- len, offset, size);
+ KGSL_CORE_ERR("length offset or size is not page aligned\n");
goto err;
}
/* The size or offset can never be greater than the PMEM length */
- if (offset >= len || size > len) {
- KGSL_CORE_ERR("offset %u or size %u "
- "exceeds pmem length %lu\n",
- offset, size, len);
+ if (offset >= len || size > len)
goto err;
- }
/* If size is 0, then adjust it to default to the size of the region
* minus the offset. If size isn't zero, then make sure that it will
@@ -3104,7 +3112,8 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv,
align = (flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
if (align >= 32) {
- KGSL_CORE_ERR("Alignment too big, restricting to 2^32\n");
+ KGSL_CORE_ERR("Alignment too big, restricting to 2^31\n");
+
flags &= ~KGSL_MEMALIGN_MASK;
flags |= (31 << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK;
}
@@ -3275,11 +3284,12 @@ struct kgsl_genlock_event_priv {
};
/**
- * kgsl_genlock_event_cb - Event callback for a genlock timestamp event
- * @device - The KGSL device that expired the timestamp
- * @priv - private data for the event
- * @context_id - the context id that goes with the timestamp
- * @timestamp - the timestamp that triggered the event
+ * kgsl_genlock_event_cb() - Event callback for a genlock timestamp event
+ * @device: The KGSL device that expired the timestamp
+ * @priv: private data for the event
+ * @context_id: the context id that goes with the timestamp
+ * @timestamp: the timestamp that triggered the event
+ * @type: Type of event that signaled the callback
*
* Release a genlock lock following the expiration of a timestamp
*/
@@ -3400,7 +3410,7 @@ typedef long (*kgsl_ioctl_func_t)(struct kgsl_device_private *,
static const struct {
unsigned int cmd;
kgsl_ioctl_func_t func;
- int flags;
+ unsigned int flags;
} kgsl_ioctl_funcs[] = {
KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY,
kgsl_ioctl_device_getproperty,
@@ -3679,7 +3689,7 @@ err_put:
static inline bool
mmap_range_valid(unsigned long addr, unsigned long len)
{
- return (addr + len) > addr && (addr + len) < TASK_SIZE;
+ return ((ULONG_MAX - addr) > len) && ((addr + len) < TASK_SIZE);
}
static unsigned long
@@ -4163,7 +4173,7 @@ int kgsl_postmortem_dump(struct kgsl_device *device, int manual)
pwr->power_flags, pwr->active_pwrlevel);
KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
- pwr->interval_timeout);
+ pwr->interval_timeout);
}
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 44be5346ac6a..10122786979e 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -272,7 +272,7 @@ static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
size = 1;
/* don't overflow */
- if ((gpuaddr + size) < gpuaddr)
+ if (size > UINT_MAX - gpuaddr)
return 0;
if (gpuaddr >= memdesc->gpuaddr &&
diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h
index b2f137cd4b09..fe9bc7683903 100644
--- a/drivers/gpu/msm/kgsl_debugfs.h
+++ b/drivers/gpu/msm/kgsl_debugfs.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2011,2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -35,7 +35,7 @@ static inline void kgsl_core_debugfs_init(void) { }
static inline void kgsl_device_debugfs_init(struct kgsl_device *device) { }
static inline void kgsl_core_debugfs_close(void) { }
static inline struct dentry *kgsl_get_debugfs_dir(void) { return NULL; }
-static inline int kgsl_process_init_debugfs(struct kgsl_process_private *)
+static inline int kgsl_process_init_debugfs(struct kgsl_process_private *priv)
{
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 3d22733772fd..b78f2753b042 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -311,7 +311,6 @@ struct kgsl_device {
};
void kgsl_process_events(struct work_struct *work);
-void kgsl_check_fences(struct work_struct *work);
#define KGSL_DEVICE_COMMON_INIT(_dev) \
.hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\
@@ -359,6 +358,7 @@ struct kgsl_process_private;
* @pagefault: flag set if this context caused a pagefault.
* @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
* is set.
+ * @flags: flags from userspace controlling the behavior of this context
* @fault_count: number of times gpu hanged in last _context_throttle_time ms
* @fault_time: time of the first gpu hang in last _context_throttle_time ms
* @pwr_constraint: power constraint from userspace for this context
@@ -377,13 +377,29 @@ struct kgsl_context {
struct list_head events;
struct list_head events_list;
unsigned int pagefault_ts;
+ unsigned int flags;
unsigned int fault_count;
unsigned long fault_time;
struct kgsl_pwr_constraint pwr_constraint;
};
+/**
+ * struct kgsl_process_private - Private structure for a KGSL process (across
+ * all devices)
+ * @priv: Internal flags, use KGSL_PROCESS_* values
+ * @pid: ID for the task owner of the process
+ * @mem_lock: Spinlock to protect the process memory lists
+ * @refcount: kref object for reference counting the process
+ * @process_private_mutex: Mutex to synchronize access to the process struct
+ * @mem_rb: RB tree node for the memory owned by this process
+ * @idr: Iterator for assigning IDs to memory allocations
+ * @pagetable: Pointer to the pagetable owned by this process
+ * @kobj: Pointer to a kobj for the sysfs directory for this process
+ * @debug_root: Pointer to the debugfs root for this process
+ * @stats: Memory allocation statistics for this process
+ */
struct kgsl_process_private {
- unsigned int refcnt;
+ unsigned long priv;
pid_t pid;
spinlock_t mem_lock;
@@ -405,6 +421,14 @@ struct kgsl_process_private {
} stats[KGSL_MEM_ENTRY_MAX];
};
+/**
+ * enum kgsl_process_priv_flags - Private flags for kgsl_process_private
+ * @KGSL_PROCESS_INIT: Set if the process structure has been set up
+ */
+enum kgsl_process_priv_flags {
+ KGSL_PROCESS_INIT = 0,
+};
+
struct kgsl_device_private {
struct kgsl_device *device;
struct kgsl_process_private *process_priv;
@@ -637,7 +661,7 @@ static inline int _kgsl_context_get(struct kgsl_context *context)
* Find the context associated with the given ID number, increase the reference
* count on it and return it. The caller must make sure that this call is
* paired with a kgsl_context_put. This function validates that the context id
- * given is owned by the dev_priv instancet that is passed in. see
+ * given is owned by the dev_priv instancet that is passed in. See
* kgsl_context_get for the internal version that doesn't do the check
*/
static inline struct kgsl_context *kgsl_context_get_owner(
@@ -724,7 +748,16 @@ static inline void kgsl_cmdbatch_put(struct kgsl_cmdbatch *cmdbatch)
*/
static inline int kgsl_cmdbatch_sync_pending(struct kgsl_cmdbatch *cmdbatch)
{
- return list_empty(&cmdbatch->synclist) ? 0 : 1;
+ int ret;
+
+ if (cmdbatch == NULL)
+ return 0;
+
+ spin_lock(&cmdbatch->lock);
+ ret = list_empty(&cmdbatch->synclist) ? 0 : 1;
+ spin_unlock(&cmdbatch->lock);
+
+ return ret;
}
#if defined(CONFIG_GPU_TRACEPOINTS)
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 6402bf4cb31f..1fc7467701bd 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -224,11 +224,23 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj)
return result;
}
- result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
- GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ result = kgsl_mmu_get_gpuaddr(priv->pagetable,
+ &priv->memdesc);
+ if (result) {
+ DRM_ERROR(
+ "kgsl_mmu_get_gpuaddr failed. result = %d\n",
+ result);
+ ion_free(kgsl_drm_ion_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ return result;
+ }
+ result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (result) {
DRM_ERROR(
"kgsl_mmu_map failed. result = %d\n", result);
+ kgsl_mmu_put_gpuaddr(priv->pagetable,
+ &priv->memdesc);
ion_free(kgsl_drm_ion_client,
priv->ion_handle);
priv->ion_handle = NULL;
@@ -274,10 +286,17 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj)
priv->memdesc.sglen++;
}
+ result = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+ if (result) {
+ DRM_ERROR(
+ "kgsl_mmu_get_gpuaddr failed. result = %d\n", result);
+ goto memerr;
+ }
result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (result) {
DRM_ERROR(
"kgsl_mmu_map failed. result = %d\n", result);
+ kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
goto memerr;
}
@@ -312,8 +331,10 @@ kgsl_gem_free_memory(struct drm_gem_object *obj)
if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type))
return;
- if (priv->memdesc.gpuaddr)
+ if (priv->memdesc.gpuaddr) {
kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc);
+ kgsl_mmu_put_gpuaddr(priv->memdesc.pagetable, &priv->memdesc);
+ }
/* ION will take care of freeing the sg table. */
priv->memdesc.sg = NULL;
@@ -646,9 +667,21 @@ kgsl_gem_create_from_ion_ioctl(struct drm_device *dev, void *data,
priv->memdesc.sglen++;
}
+ ret = kgsl_mmu_get_gpuaddr(priv->pagetable, &priv->memdesc);
+ if (ret) {
+ DRM_ERROR("kgsl_mmu_get_gpuaddr failed. ret = %d\n", ret);
+ ion_free(kgsl_drm_ion_client,
+ priv->ion_handle);
+ priv->ion_handle = NULL;
+ kgsl_mmu_putpagetable(priv->pagetable);
+ drm_gem_object_release(obj);
+ kfree(priv);
+ return -ENOMEM;
+ }
ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
if (ret) {
DRM_ERROR("kgsl_mmu_map failed. ret = %d\n", ret);
+ kgsl_mmu_put_gpuaddr(priv->pagetable, &priv->memdesc);
ion_free(kgsl_drm_ion_client,
priv->ion_handle);
priv->ion_handle = NULL;
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index d58b844dbba4..342d76c6dd06 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -213,7 +213,6 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
struct kgsl_event *event;
unsigned int queued = 0, cur_ts;
struct kgsl_context *context = NULL;
- struct adreno_context *drawctxt = NULL;
BUG_ON(!mutex_is_locked(&device->mutex));
@@ -224,7 +223,6 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
context = kgsl_context_get(device, id);
if (context == NULL)
return -EINVAL;
- drawctxt = ADRENO_CONTEXT(context);
}
/*
* If the caller is creating their own timestamps, let them schedule
@@ -232,7 +230,7 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
* queued.
*/
if (context == NULL ||
- ((drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) == 0)) {
+ ((context->flags & KGSL_CONTEXT_USER_GENERATED_TS) == 0)) {
queued = kgsl_readtimestamp(device, context,
KGSL_TIMESTAMP_QUEUED);
@@ -340,7 +338,11 @@ void kgsl_cancel_event(struct kgsl_device *device, struct kgsl_context *context,
void *priv)
{
struct kgsl_event *event;
- struct list_head *head = _get_list_head(device, context);
+ struct list_head *head;
+
+ BUG_ON(!mutex_is_locked(&device->mutex));
+
+ head = _get_list_head(device, context);
event = _find_event(device, head, timestamp, func, priv);
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 1a1e2e3549f6..2634e4f05a2a 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -23,6 +23,7 @@
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"
#include "kgsl_trace.h"
+#include "adreno.h"
#define KGSL_PAGETABLE_SIZE \
ALIGN(KGSL_PAGETABLE_ENTRIES(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE) * \
@@ -403,11 +404,22 @@ static void kgsl_gpummu_pagefault(struct kgsl_mmu *mmu)
{
unsigned int reg;
unsigned int ptbase;
+ struct kgsl_device *device;
+ struct adreno_device *adreno_dev;
+ unsigned int no_page_fault_log = 0;
- kgsl_regread(mmu->device, MH_MMU_PAGE_FAULT, ®);
- kgsl_regread(mmu->device, MH_MMU_PT_BASE, &ptbase);
+ device = mmu->device;
+ adreno_dev = ADRENO_DEVICE(device);
+
+ kgsl_regread(device, MH_MMU_PAGE_FAULT, ®);
+ kgsl_regread(device, MH_MMU_PT_BASE, &ptbase);
+
+
+ if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE)
+ no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, reg);
- KGSL_MEM_CRIT(mmu->device,
+ if (!no_page_fault_log)
+ KGSL_MEM_CRIT(mmu->device,
"mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
reg & ~(PAGE_SIZE - 1),
kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index f8b61c78f4ba..03a58e9ed1a2 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -47,7 +47,7 @@ static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = {
{ 0x03C, 1 }, /* TLBLKCR */
{ 0x818, 1 }, /* V2PUR */
{ 0x2C, 1 }, /* FSYNR0 */
- { 0x30, 1 }, /* FSYNR0 */
+ { 0x30, 1 }, /* FSYNR1 */
{ 0, 0 }, /* TLBSYNC, not in v0 */
{ 0, 0 }, /* TLBSTATUS, not in v0 */
{ 0, 0 } /* IMPLDEF_MICRO_MMU_CRTL, not in v0 */
@@ -322,13 +322,13 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
struct kgsl_iommu_unit *iommu_unit;
struct kgsl_iommu_device *iommu_dev;
unsigned int ptbase, fsr;
- struct kgsl_device *device;
- struct adreno_device *adreno_dev;
- unsigned int no_page_fault_log = 0;
unsigned int pid;
+ struct _mem_entry prev, next;
unsigned int fsynr0, fsynr1;
int write;
- struct _mem_entry prev, next;
+ struct kgsl_device *device;
+ struct adreno_device *adreno_dev;
+ unsigned int no_page_fault_log = 0;
unsigned int curr_context_id = 0;
unsigned int curr_global_ts = 0;
struct kgsl_context *context;
@@ -432,6 +432,7 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
_print_entry(iommu_dev->kgsldev, &next);
else
KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n");
+
}
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
@@ -820,6 +821,7 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu,
struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[unit_id];
int i, j;
int found_ctx;
+ int ret = 0;
for (j = 0; j < KGSL_IOMMU_MAX_DEVS_PER_UNIT; j++) {
found_ctx = 0;
@@ -833,17 +835,22 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu,
break;
if (!data->iommu_ctxs[i].iommu_ctx_name) {
KGSL_CORE_ERR("Context name invalid\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
atomic_set(&(iommu_unit->clk_enable_count), 0);
iommu_unit->dev[iommu_unit->dev_count].dev =
msm_iommu_get_ctx(data->iommu_ctxs[i].iommu_ctx_name);
- if (iommu_unit->dev[iommu_unit->dev_count].dev == NULL) {
- KGSL_CORE_ERR("Failed to get iommu dev handle for "
- "device %s\n", data->iommu_ctxs[i].iommu_ctx_name);
- return -EINVAL;
+ if (NULL == iommu_unit->dev[iommu_unit->dev_count].dev)
+ ret = -EINVAL;
+ if (IS_ERR(iommu_unit->dev[iommu_unit->dev_count].dev)) {
+ ret = PTR_ERR(
+ iommu_unit->dev[iommu_unit->dev_count].dev);
+ iommu_unit->dev[iommu_unit->dev_count].dev = NULL;
}
+ if (ret)
+ goto done;
iommu_unit->dev[iommu_unit->dev_count].ctx_id =
data->iommu_ctxs[i].ctx_id;
iommu_unit->dev[iommu_unit->dev_count].kgsldev = mmu->device;
@@ -855,12 +862,23 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu,
iommu_unit->dev_count++;
}
- if (!j) {
- KGSL_CORE_ERR("No ctxts initialized, user ctxt absent\n ");
- return -EINVAL;
+done:
+ if (!iommu_unit->dev_count && !ret)
+ ret = -EINVAL;
+ if (ret) {
+ /*
+ * If at least the first context is initialized on v1
+ * then we can continue
+ */
+ if (!msm_soc_version_supports_iommu_v1() &&
+ iommu_unit->dev_count)
+ ret = 0;
+ else
+ KGSL_CORE_ERR(
+ "Failed to initialize iommu contexts, err: %d\n", ret);
}
- return 0;
+ return ret;
}
/*
@@ -923,6 +941,17 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)
!kgsl_mmu_is_perprocess(mmu))
return status;
+ /*
+ * For 2D devices cpu side sync lock is required. For 3D device,
+ * since we only have a single 3D core and we always ensure that
+ * 3D core is idle while writing to IOMMU register using CPU this
+ * lock is not required
+ */
+ if (KGSL_DEVICE_2D0 == mmu->device->id ||
+ KGSL_DEVICE_2D1 == mmu->device->id) {
+ return status;
+ }
+
/* Return if already initialized */
if (iommu->sync_lock_initialized)
return status;
@@ -1915,7 +1944,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu,
int temp;
int i;
int ret = 0;
- unsigned int pt_base = kgsl_iommu_get_pt_base_addr(mmu,
+ phys_addr_t pt_base = kgsl_iommu_get_pt_base_addr(mmu,
mmu->hwpagetable);
phys_addr_t pt_val;
diff --git a/drivers/gpu/msm/kgsl_log.h b/drivers/gpu/msm/kgsl_log.h
index 81a35e0d20e5..f90627e8dbe5 100644
--- a/drivers/gpu/msm/kgsl_log.h
+++ b/drivers/gpu/msm/kgsl_log.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2008-2011,2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,8 +13,6 @@
#ifndef __KGSL_LOG_H
#define __KGSL_LOG_H
-extern unsigned int kgsl_cff_dump_enable;
-
#define KGSL_LOG_INFO(dev, lvl, fmt, args...) \
do { \
if ((lvl) >= 6) \
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 1910a46e9952..6b04aadb9a03 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -348,7 +348,7 @@ kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, phys_addr_t pt_base,
unsigned int ret = 0;
if (!mmu->mmu_ops || !mmu->mmu_ops->mmu_pt_equal)
- return KGSL_MMU_GLOBAL_PT;
+ return 0;
spin_lock(&kgsl_driver.ptlock);
list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
if (kref_get_unless_zero(&pt->refcount)) {
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index ac4bae36055a..5fcc6f4b1908 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 80492d71a90b..e7eaa93b12ae 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -766,12 +766,12 @@ DEVICE_ATTR(thermal_pwrlevel, 0644,
DEVICE_ATTR(num_pwrlevels, 0444,
kgsl_pwrctrl_num_pwrlevels_show,
NULL);
-DEVICE_ATTR(reset_count, 0444,
- kgsl_pwrctrl_reset_count_show,
- NULL);
DEVICE_ATTR(pmqos_latency, 0644,
kgsl_pwrctrl_pmqos_latency_show,
kgsl_pwrctrl_pmqos_latency_store);
+DEVICE_ATTR(reset_count, 0444,
+ kgsl_pwrctrl_reset_count_show,
+ NULL);
DEVICE_ATTR(force_clk_on, 0644,
kgsl_pwrctrl_force_clk_on_show,
kgsl_pwrctrl_force_clk_on_store);
@@ -793,8 +793,8 @@ static const struct device_attribute *pwrctrl_attr_list[] = {
&dev_attr_min_pwrlevel,
&dev_attr_thermal_pwrlevel,
&dev_attr_num_pwrlevels,
- &dev_attr_reset_count,
&dev_attr_pmqos_latency,
+ &dev_attr_reset_count,
&dev_attr_force_clk_on,
&dev_attr_force_bus_on,
&dev_attr_force_rail_on,
@@ -1381,7 +1381,6 @@ int kgsl_pwrctrl_sleep(struct kgsl_device *device)
break;
case KGSL_STATE_SLEEP:
status = _sleep(device);
- kgsl_mmu_disable_clk_on_ts(&device->mmu, 0, false);
break;
case KGSL_STATE_SLUMBER:
status = _slumber(device);
@@ -1432,6 +1431,7 @@ int kgsl_pwrctrl_wake(struct kgsl_device *device)
kgsl_pwrstate_to_str(state),
context ? context->id : -1, ts_processed);
kgsl_context_put(context);
+
/* fall through */
case KGSL_STATE_NAP:
/* Turn on the core clocks */
@@ -1538,13 +1538,11 @@ int kgsl_active_count_get(struct kgsl_device *device)
int ret = 0;
BUG_ON(!mutex_is_locked(&device->mutex));
- if (atomic_read(&device->active_cnt) == 0) {
- if (device->requested_state == KGSL_STATE_SUSPEND ||
- device->state == KGSL_STATE_SUSPEND) {
- mutex_unlock(&device->mutex);
- wait_for_completion(&device->hwaccess_gate);
- mutex_lock(&device->mutex);
- }
+ if ((atomic_read(&device->active_cnt) == 0) &&
+ (device->state != KGSL_STATE_ACTIVE)) {
+ mutex_unlock(&device->mutex);
+ wait_for_completion(&device->hwaccess_gate);
+ mutex_lock(&device->mutex);
ret = kgsl_pwrctrl_wake(device);
}
@@ -1597,12 +1595,9 @@ void kgsl_active_count_put(struct kgsl_device *device)
if (atomic_dec_and_test(&device->active_cnt)) {
if (device->state == KGSL_STATE_ACTIVE &&
- device->requested_state == KGSL_STATE_NONE) {
+ device->requested_state == KGSL_STATE_NONE) {
kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
- if (kgsl_pwrctrl_sleep(device)) {
- kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
- queue_work(device->work_queue, &device->idle_check_ws);
- }
+ queue_work(device->work_queue, &device->idle_check_ws);
}
mod_timer(&device->idle_timer,
diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
index 81336638f497..d3ebf24d71e5 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c
@@ -160,11 +160,13 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale)
(priv->bin.total_time < FLOOR))
return;
- /* If there is an extended block of busy processing,
- * increase frequency. Otherwise run the normal algorithm.
+ /* If there is an extended block of busy processing, set
+ * frequency to turbo. Otherwise run the normal algorithm.
*/
if (priv->bin.busy_time > CEILING) {
- val = -1;
+ val = 0;
+ kgsl_pwrctrl_pwrlevel_change(device,
+ KGSL_PWRLEVEL_TURBO);
} else if (priv->idle_dcvs) {
idle = priv->bin.total_time - priv->bin.busy_time;
idle = (idle > 0) ? idle : 0;
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 4a43d1480975..f0114ad195fc 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -146,13 +146,8 @@ static inline void *kgsl_sg_alloc(unsigned int sglen)
if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE)
return kzalloc(sglen * sizeof(struct scatterlist), GFP_KERNEL);
- else {
- void *ptr = vmalloc(sglen * sizeof(struct scatterlist));
- if (ptr)
- memset(ptr, 0, sglen * sizeof(struct scatterlist));
-
- return ptr;
- }
+ else
+ return vmalloc(sglen * sizeof(struct scatterlist));
}
static inline void kgsl_sg_free(void *ptr, unsigned int sglen)
@@ -168,7 +163,7 @@ memdesc_sg_phys(struct kgsl_memdesc *memdesc,
phys_addr_t physaddr, unsigned int size)
{
memdesc->sg = kgsl_sg_alloc(1);
- if (!memdesc->sg)
+ if (memdesc->sg == NULL)
return -ENOMEM;
kmemleak_not_leak(memdesc->sg);
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index a81e19c520ae..beda17f31693 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -210,10 +210,8 @@ static int snapshot_os(struct kgsl_device *device,
header->ctxtcount = ctxtcount;
_ctxtptr = snapshot + sizeof(*header);
-
/* append information for the global context */
snapshot_context_info(KGSL_MEMSTORE_GLOBAL, NULL, device);
-
/* append information for each context */
read_lock(&device->context_lock);
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 0e7606e842c3..dd32e1479436 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -13,12 +13,9 @@
#include <linux/err.h>
#include <linux/file.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
-#include <asm/current.h>
-
#include "kgsl_sync.h"
struct sync_pt *kgsl_sync_pt_create(struct sync_timeline *timeline,
@@ -90,9 +87,7 @@ static inline void kgsl_fence_event_cb(struct kgsl_device *device,
void *priv, u32 context_id, u32 timestamp, u32 type)
{
struct kgsl_fence_event_priv *ev = priv;
-
- /* Signal time timeline for every event type */
- kgsl_sync_timeline_signal(ev->context->timeline, timestamp);
+ kgsl_sync_timeline_signal(ev->context->timeline, ev->timestamp);
kgsl_context_put(ev->context);
kfree(ev);
}
@@ -130,10 +125,8 @@ int kgsl_add_fence_event(struct kgsl_device *device,
context = kgsl_context_get_owner(owner, context_id);
- if (context == NULL) {
- kfree(event);
- return -EINVAL;
- }
+ if (context == NULL)
+ goto fail_pt;
event->context = context;
event->timestamp = timestamp;
@@ -192,35 +185,6 @@ fail_pt:
return ret;
}
-static unsigned int kgsl_sync_get_timestamp(
- struct kgsl_sync_timeline *ktimeline, enum kgsl_timestamp_type type)
-{
- struct kgsl_context *context = idr_find(&ktimeline->device->context_idr,
- ktimeline->context_id);
- if (context == NULL)
- return 0;
-
- return kgsl_readtimestamp(ktimeline->device, context, type);
-}
-
-static void kgsl_sync_timeline_value_str(struct sync_timeline *sync_timeline,
- char *str, int size)
-{
- struct kgsl_sync_timeline *ktimeline =
- (struct kgsl_sync_timeline *) sync_timeline;
- unsigned int timestamp_retired = kgsl_sync_get_timestamp(ktimeline,
- KGSL_TIMESTAMP_RETIRED);
- snprintf(str, size, "%u retired:%u", ktimeline->last_timestamp,
- timestamp_retired);
-}
-
-static void kgsl_sync_pt_value_str(struct sync_pt *sync_pt,
- char *str, int size)
-{
- struct kgsl_sync_pt *kpt = (struct kgsl_sync_pt *) sync_pt;
- snprintf(str, size, "%u", kpt->timestamp);
-}
-
static void kgsl_sync_timeline_release_obj(struct sync_timeline *sync_timeline)
{
/*
@@ -235,8 +199,6 @@ static const struct sync_timeline_ops kgsl_sync_timeline_ops = {
.dup = kgsl_sync_pt_dup,
.has_signaled = kgsl_sync_pt_has_signaled,
.compare = kgsl_sync_pt_compare,
- .timeline_value_str = kgsl_sync_timeline_value_str,
- .pt_value_str = kgsl_sync_pt_value_str,
.release_obj = kgsl_sync_timeline_release_obj,
};
@@ -244,25 +206,13 @@ int kgsl_sync_timeline_create(struct kgsl_context *context)
{
struct kgsl_sync_timeline *ktimeline;
- /* Generate a name which includes the thread name, thread id, process
- * name, process id, and context id. This makes it possible to
- * identify the context of a timeline in the sync dump. */
- char ktimeline_name[sizeof(context->timeline->name)] = {};
- snprintf(ktimeline_name, sizeof(ktimeline_name),
- "%s_%.15s(%d)-%.15s(%d)-%d",
- context->device->name,
- current->group_leader->comm, current->group_leader->pid,
- current->comm, current->pid, context->id);
-
context->timeline = sync_timeline_create(&kgsl_sync_timeline_ops,
- (int) sizeof(struct kgsl_sync_timeline), ktimeline_name);
+ (int) sizeof(struct kgsl_sync_timeline), "kgsl-timeline");
if (context->timeline == NULL)
return -EINVAL;
ktimeline = (struct kgsl_sync_timeline *) context->timeline;
ktimeline->last_timestamp = 0;
- ktimeline->device = context->dev_priv->device;
- ktimeline->context_id = context->id;
return 0;
}
@@ -305,7 +255,7 @@ struct kgsl_sync_fence_waiter *kgsl_sync_fence_async_wait(int fd,
return ERR_PTR(-EINVAL);
/* create the waiter */
- kwaiter = kzalloc(sizeof(*kwaiter), GFP_KERNEL);
+ kwaiter = kzalloc(sizeof(*kwaiter), GFP_ATOMIC);
if (kwaiter == NULL) {
sync_fence_put(fence);
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index 275eaf07dfb5..2f28b21fc6dd 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -19,8 +19,6 @@
struct kgsl_sync_timeline {
struct sync_timeline timeline;
unsigned int last_timestamp;
- struct kgsl_device *device;
- u32 context_id;
};
struct kgsl_sync_pt {
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 45f200c3454e..ae7aee0a0f59 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -514,7 +514,7 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv,
z180_cmdwindow_write(device, ADDR_VGV3_CONTROL, 0);
error:
kgsl_trace_issueibcmds(device, context->id, cmdbatch,
- *timestamp, cmdbatch->flags, result, 0);
+ *timestamp, cmdbatch ? cmdbatch->flags : 0, result, 0);
kgsl_active_count_put(device);
error_active_count:
@@ -614,7 +614,6 @@ static int z180_start(struct kgsl_device *device)
z180_cmdstream_start(device);
- mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
device->ftbl->irqctrl(device, 1);
--
GitLab