msm: kgsl: Add per context timestamp
Add new ioctls for per context timestamps. Timestamp functions (read/write/wait) will now be context specific rather than only using the global timestamp. Per context timestamps is a requirement for priority based queueing.
This commit is contained in:
parent
1e188cc5e1
commit
55ece772cd
@ -565,13 +565,13 @@ adreno_recover_hang(struct kgsl_device *device)
|
||||
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
|
||||
unsigned int timestamp;
|
||||
unsigned int num_rb_contents;
|
||||
unsigned int bad_context;
|
||||
unsigned int reftimestamp;
|
||||
unsigned int enable_ts;
|
||||
unsigned int soptimestamp;
|
||||
unsigned int eoptimestamp;
|
||||
struct adreno_context *drawctxt;
|
||||
unsigned int context_id;
|
||||
struct kgsl_context *context;
|
||||
struct adreno_context *adreno_context;
|
||||
int next = 0;
|
||||
|
||||
KGSL_DRV_ERR(device, "Starting recovery from 3D GPU hang....\n");
|
||||
@ -587,22 +587,35 @@ adreno_recover_hang(struct kgsl_device *device)
|
||||
ret = adreno_ringbuffer_extract(rb, rb_buffer, &num_rb_contents);
|
||||
if (ret)
|
||||
goto done;
|
||||
timestamp = rb->timestamp;
|
||||
KGSL_DRV_ERR(device, "Last issued timestamp: %x\n", timestamp);
|
||||
kgsl_sharedmem_readl(&device->memstore, &bad_context,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(current_context));
|
||||
kgsl_sharedmem_readl(&device->memstore, &context_id,
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
current_context));
|
||||
context = idr_find(&device->context_idr, context_id);
|
||||
if (context == NULL) {
|
||||
KGSL_DRV_ERR(device, "Last context unknown id:%d\n",
|
||||
context_id);
|
||||
context_id = KGSL_MEMSTORE_GLOBAL;
|
||||
}
|
||||
|
||||
timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
|
||||
KGSL_DRV_ERR(device, "Last issued global timestamp: %x\n", timestamp);
|
||||
|
||||
kgsl_sharedmem_readl(&device->memstore, &reftimestamp,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts));
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ref_wait_ts));
|
||||
kgsl_sharedmem_readl(&device->memstore, &enable_ts,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable));
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ts_cmp_enable));
|
||||
kgsl_sharedmem_readl(&device->memstore, &soptimestamp,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp));
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
soptimestamp));
|
||||
kgsl_sharedmem_readl(&device->memstore, &eoptimestamp,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp));
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
eoptimestamp));
|
||||
/* Make sure memory is synchronized before restarting the GPU */
|
||||
mb();
|
||||
KGSL_CTXT_ERR(device,
|
||||
"Context that caused a GPU hang: %x\n", bad_context);
|
||||
"Context id that caused a GPU hang: %d\n", context_id);
|
||||
/* restart device */
|
||||
ret = adreno_stop(device);
|
||||
if (ret)
|
||||
@ -613,20 +626,20 @@ adreno_recover_hang(struct kgsl_device *device)
|
||||
KGSL_DRV_ERR(device, "Device has been restarted after hang\n");
|
||||
/* Restore timestamp states */
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp),
|
||||
KGSL_MEMSTORE_OFFSET(context_id, soptimestamp),
|
||||
soptimestamp);
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp),
|
||||
KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp),
|
||||
eoptimestamp);
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp),
|
||||
KGSL_MEMSTORE_OFFSET(context_id, soptimestamp),
|
||||
soptimestamp);
|
||||
if (num_rb_contents) {
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
|
||||
KGSL_MEMSTORE_OFFSET(context_id, ref_wait_ts),
|
||||
reftimestamp);
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
|
||||
KGSL_MEMSTORE_OFFSET(context_id, ts_cmp_enable),
|
||||
enable_ts);
|
||||
}
|
||||
/* Make sure all writes are posted before the GPU reads them */
|
||||
@ -634,12 +647,12 @@ adreno_recover_hang(struct kgsl_device *device)
|
||||
/* Mark the invalid context so no more commands are accepted from
|
||||
* that context */
|
||||
|
||||
drawctxt = (struct adreno_context *) bad_context;
|
||||
adreno_context = context->devctxt;
|
||||
|
||||
KGSL_CTXT_ERR(device,
|
||||
"Context that caused a GPU hang: %x\n", bad_context);
|
||||
"Context that caused a GPU hang: %d\n", adreno_context->id);
|
||||
|
||||
drawctxt->flags |= CTXT_FLAGS_GPU_HANG;
|
||||
adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
|
||||
|
||||
/*
|
||||
* Set the reset status of all contexts to
|
||||
@ -649,7 +662,7 @@ adreno_recover_hang(struct kgsl_device *device)
|
||||
while ((context = idr_get_next(&device->context_idr, &next))) {
|
||||
if (KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT !=
|
||||
context->reset_status) {
|
||||
if (context->devctxt != drawctxt)
|
||||
if (context->id != context_id)
|
||||
context->reset_status =
|
||||
KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT;
|
||||
else
|
||||
@ -661,7 +674,7 @@ adreno_recover_hang(struct kgsl_device *device)
|
||||
|
||||
/* Restore valid commands in ringbuffer */
|
||||
adreno_ringbuffer_restore(rb, rb_buffer, num_rb_contents);
|
||||
rb->timestamp = timestamp;
|
||||
rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
|
||||
done:
|
||||
vfree(rb_buffer);
|
||||
return ret;
|
||||
@ -755,7 +768,8 @@ static int adreno_getproperty(struct kgsl_device *device,
|
||||
shadowprop.size = device->memstore.size;
|
||||
/* GSL needs this to be set, even if it
|
||||
appears to be meaningless */
|
||||
shadowprop.flags = KGSL_FLAGS_INITIALIZED;
|
||||
shadowprop.flags = KGSL_FLAGS_INITIALIZED |
|
||||
KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS;
|
||||
}
|
||||
if (copy_to_user(value, &shadowprop,
|
||||
sizeof(shadowprop))) {
|
||||
@ -1011,38 +1025,58 @@ void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
|
||||
__raw_writel(value, reg);
|
||||
}
|
||||
|
||||
static unsigned int _get_context_id(struct kgsl_context *k_ctxt)
|
||||
{
|
||||
unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
|
||||
|
||||
if (k_ctxt != NULL) {
|
||||
struct adreno_context *a_ctxt = k_ctxt->devctxt;
|
||||
/*
|
||||
* if the context was not created with per context timestamp
|
||||
* support, we must use the global timestamp since issueibcmds
|
||||
* will be returning that one.
|
||||
*/
|
||||
if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
|
||||
context_id = a_ctxt->id;
|
||||
}
|
||||
|
||||
return context_id;
|
||||
}
|
||||
|
||||
static int kgsl_check_interrupt_timestamp(struct kgsl_device *device,
|
||||
unsigned int timestamp)
|
||||
struct kgsl_context *context, unsigned int timestamp)
|
||||
{
|
||||
int status;
|
||||
unsigned int ref_ts, enableflag;
|
||||
unsigned int context_id = _get_context_id(context);
|
||||
|
||||
status = kgsl_check_timestamp(device, timestamp);
|
||||
status = kgsl_check_timestamp(device, context, timestamp);
|
||||
if (!status) {
|
||||
mutex_lock(&device->mutex);
|
||||
kgsl_sharedmem_readl(&device->memstore, &enableflag,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable));
|
||||
KGSL_MEMSTORE_OFFSET(context_id, ts_cmp_enable));
|
||||
mb();
|
||||
|
||||
if (enableflag) {
|
||||
kgsl_sharedmem_readl(&device->memstore, &ref_ts,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts));
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ref_wait_ts));
|
||||
mb();
|
||||
if (timestamp_cmp(ref_ts, timestamp) >= 0) {
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
|
||||
timestamp);
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ref_wait_ts), timestamp);
|
||||
wmb();
|
||||
}
|
||||
} else {
|
||||
unsigned int cmds[2];
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
|
||||
timestamp);
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ref_wait_ts), timestamp);
|
||||
enableflag = 1;
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
|
||||
enableflag);
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ts_cmp_enable), enableflag);
|
||||
wmb();
|
||||
/* submit a dummy packet so that even if all
|
||||
* commands upto timestamp get executed we will still
|
||||
@ -1076,6 +1110,7 @@ static int kgsl_check_interrupt_timestamp(struct kgsl_device *device,
|
||||
|
||||
/* MUST be called with the device mutex held */
|
||||
static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
struct kgsl_context *context,
|
||||
unsigned int timestamp,
|
||||
unsigned int msecs)
|
||||
{
|
||||
@ -1087,15 +1122,19 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
int retries;
|
||||
unsigned int msecs_first;
|
||||
unsigned int msecs_part;
|
||||
unsigned int ts_issued;
|
||||
unsigned int context_id = _get_context_id(context);
|
||||
|
||||
ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
|
||||
|
||||
/* Don't wait forever, set a max value for now */
|
||||
if (msecs == -1)
|
||||
msecs = adreno_dev->wait_timeout;
|
||||
|
||||
if (timestamp_cmp(timestamp, adreno_dev->ringbuffer.timestamp) > 0) {
|
||||
KGSL_DRV_ERR(device, "Cannot wait for invalid ts: %x, "
|
||||
"rb->timestamp: %x\n",
|
||||
timestamp, adreno_dev->ringbuffer.timestamp);
|
||||
if (timestamp_cmp(timestamp, ts_issued) > 0) {
|
||||
KGSL_DRV_ERR(device, "Cannot wait for invalid ts <%d:0x%x>, "
|
||||
"last issued ts <%d:0x%x>\n",
|
||||
context_id, timestamp, context_id, ts_issued);
|
||||
status = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
@ -1107,7 +1146,7 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
|
||||
msecs_part = (msecs - msecs_first + 3) / 4;
|
||||
for (retries = 0; retries < 5; retries++) {
|
||||
if (kgsl_check_timestamp(device, timestamp)) {
|
||||
if (kgsl_check_timestamp(device, context, timestamp)) {
|
||||
/* if the timestamp happens while we're not
|
||||
* waiting, there's a chance that an interrupt
|
||||
* will not be generated and thus the timestamp
|
||||
@ -1130,7 +1169,7 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
status = kgsl_wait_event_interruptible_timeout(
|
||||
device->wait_queue,
|
||||
kgsl_check_interrupt_timestamp(device,
|
||||
timestamp),
|
||||
context, timestamp),
|
||||
msecs_to_jiffies(retries ?
|
||||
msecs_part : msecs_first), io);
|
||||
mutex_lock(&device->mutex);
|
||||
@ -1147,9 +1186,10 @@ static int adreno_waittimestamp(struct kgsl_device *device,
|
||||
}
|
||||
status = -ETIMEDOUT;
|
||||
KGSL_DRV_ERR(device,
|
||||
"Device hang detected while waiting for timestamp: %x,"
|
||||
"last submitted(rb->timestamp): %x, wptr: %x\n",
|
||||
timestamp, adreno_dev->ringbuffer.timestamp,
|
||||
"Device hang detected while waiting for timestamp: "
|
||||
"<%d:0x%x>, last submitted timestamp: <%d:0x%x>, "
|
||||
"wptr: 0x%x\n",
|
||||
context_id, timestamp, context_id, ts_issued,
|
||||
adreno_dev->ringbuffer.wptr);
|
||||
if (!adreno_dump_and_recover(device)) {
|
||||
/* wait for idle after recovery as the
|
||||
@ -1163,15 +1203,17 @@ done:
|
||||
}
|
||||
|
||||
static unsigned int adreno_readtimestamp(struct kgsl_device *device,
|
||||
enum kgsl_timestamp_type type)
|
||||
struct kgsl_context *context, enum kgsl_timestamp_type type)
|
||||
{
|
||||
unsigned int timestamp = 0;
|
||||
unsigned int context_id = _get_context_id(context);
|
||||
|
||||
if (type == KGSL_TIMESTAMP_CONSUMED)
|
||||
adreno_regread(device, REG_CP_TIMESTAMP, ×tamp);
|
||||
else if (type == KGSL_TIMESTAMP_RETIRED)
|
||||
kgsl_sharedmem_readl(&device->memstore, ×tamp,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp));
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
eoptimestamp));
|
||||
rmb();
|
||||
|
||||
return timestamp;
|
||||
|
@ -1427,8 +1427,8 @@ static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
|
||||
cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
|
||||
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
|
||||
cmds[3] = device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
|
||||
cmds[4] = (unsigned int) context;
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
|
||||
cmds[4] = context->id;
|
||||
adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
|
||||
kgsl_mmu_setstate(device, context->pagetable);
|
||||
|
||||
@ -1551,11 +1551,18 @@ static void a2xx_cp_intrcallback(struct kgsl_device *device)
|
||||
|
||||
if (status & CP_INT_CNTL__RB_INT_MASK) {
|
||||
/* signal intr completion event */
|
||||
unsigned int enableflag = 0;
|
||||
unsigned int context_id;
|
||||
kgsl_sharedmem_readl(&device->memstore,
|
||||
&context_id,
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
current_context));
|
||||
if (context_id < KGSL_MEMSTORE_MAX) {
|
||||
kgsl_sharedmem_writel(&rb->device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable),
|
||||
enableflag);
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ts_cmp_enable), 0);
|
||||
device->last_expired_ctxt_id = context_id;
|
||||
wmb();
|
||||
}
|
||||
KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
|
||||
}
|
||||
|
||||
@ -1780,7 +1787,6 @@ static void a2xx_gmeminit(struct adreno_device *adreno_dev)
|
||||
static void a2xx_start(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = &adreno_dev->dev;
|
||||
int init_reftimestamp = 0x7fffffff;
|
||||
|
||||
/*
|
||||
* We need to make sure all blocks are powered up and clocked
|
||||
@ -1833,12 +1839,6 @@ static void a2xx_start(struct adreno_device *adreno_dev)
|
||||
else
|
||||
adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80);
|
||||
|
||||
kgsl_sharedmem_set(&device->memstore, 0, 0, device->memstore.size);
|
||||
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts),
|
||||
init_reftimestamp);
|
||||
|
||||
adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000);
|
||||
|
||||
/* Make sure interrupts are disabled */
|
||||
|
@ -2222,8 +2222,8 @@ static void a3xx_drawctxt_restore(struct adreno_device *adreno_dev,
|
||||
cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER;
|
||||
cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
|
||||
cmds[3] = device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(current_context);
|
||||
cmds[4] = (unsigned int)context;
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
|
||||
cmds[4] = context->id;
|
||||
adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
|
||||
kgsl_mmu_setstate(device, context->pagetable);
|
||||
|
||||
@ -2366,9 +2366,17 @@ static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
|
||||
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
|
||||
|
||||
if (irq == A3XX_INT_CP_RB_INT) {
|
||||
unsigned int context_id;
|
||||
kgsl_sharedmem_readl(&adreno_dev->dev.memstore,
|
||||
&context_id,
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
current_context));
|
||||
if (context_id < KGSL_MEMSTORE_MAX) {
|
||||
kgsl_sharedmem_writel(&rb->device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable), 0);
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
ts_cmp_enable), 0);
|
||||
wmb();
|
||||
}
|
||||
KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
|
||||
/* Copyright (c) 2002,2007-2012, Code Aurora Forum. 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
|
||||
@ -17,6 +17,8 @@
|
||||
#include "kgsl_sharedmem.h"
|
||||
#include "adreno.h"
|
||||
|
||||
#define KGSL_INIT_REFTIMESTAMP 0x7FFFFFFF
|
||||
|
||||
/* quad for copying GMEM to context shadow */
|
||||
#define QUAD_LEN 12
|
||||
#define QUAD_RESTORE_LEN 14
|
||||
@ -154,6 +156,7 @@ int adreno_drawctxt_create(struct kgsl_device *device,
|
||||
|
||||
drawctxt->pagetable = pagetable;
|
||||
drawctxt->bin_base_offset = 0;
|
||||
drawctxt->id = context->id;
|
||||
|
||||
if (flags & KGSL_CONTEXT_PREAMBLE)
|
||||
drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
|
||||
@ -161,10 +164,17 @@ int adreno_drawctxt_create(struct kgsl_device *device,
|
||||
if (flags & KGSL_CONTEXT_NO_GMEM_ALLOC)
|
||||
drawctxt->flags |= CTXT_FLAGS_NOGMEMALLOC;
|
||||
|
||||
if (flags & KGSL_CONTEXT_PER_CONTEXT_TS)
|
||||
drawctxt->flags |= CTXT_FLAGS_PER_CONTEXT_TS;
|
||||
|
||||
ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
|
||||
KGSL_INIT_REFTIMESTAMP);
|
||||
|
||||
context->devctxt = drawctxt;
|
||||
return 0;
|
||||
err:
|
||||
|
@ -40,6 +40,10 @@
|
||||
#define CTXT_FLAGS_GPU_HANG 0x00008000
|
||||
/* Specifies there is no need to save GMEM */
|
||||
#define CTXT_FLAGS_NOGMEMALLOC 0x00010000
|
||||
/* Trash state for context */
|
||||
#define CTXT_FLAGS_TRASHSTATE 0x00020000
|
||||
/* per context timestamps enabled */
|
||||
#define CTXT_FLAGS_PER_CONTEXT_TS 0x00040000
|
||||
|
||||
struct kgsl_device;
|
||||
struct adreno_device;
|
||||
@ -72,6 +76,7 @@ struct gmem_shadow_t {
|
||||
};
|
||||
|
||||
struct adreno_context {
|
||||
unsigned int id;
|
||||
uint32_t flags;
|
||||
struct kgsl_pagetable *pagetable;
|
||||
struct kgsl_memdesc gpustate;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include "kgsl.h"
|
||||
#include "kgsl_sharedmem.h"
|
||||
|
||||
#include "adreno.h"
|
||||
#include "adreno_pm4types.h"
|
||||
@ -464,7 +465,9 @@ static int adreno_dump(struct kgsl_device *device)
|
||||
const uint32_t *rb_vaddr;
|
||||
int num_item = 0;
|
||||
int read_idx, write_idx;
|
||||
unsigned int ts_processed;
|
||||
unsigned int ts_processed = 0xdeaddead;
|
||||
struct kgsl_context *context;
|
||||
unsigned int context_id;
|
||||
|
||||
static struct ib_list ib_list;
|
||||
|
||||
@ -660,9 +663,18 @@ static int adreno_dump(struct kgsl_device *device)
|
||||
KGSL_LOG_DUMP(device,
|
||||
"MH_INTERRUPT: MASK = %08X | STATUS = %08X\n", r1, r2);
|
||||
|
||||
ts_processed = device->ftbl->readtimestamp(device,
|
||||
kgsl_sharedmem_readl(&device->memstore,
|
||||
(unsigned int *) &context_id,
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
current_context));
|
||||
context = idr_find(&device->context_idr, context_id);
|
||||
if (context) {
|
||||
ts_processed = device->ftbl->readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
KGSL_LOG_DUMP(device, "TIMESTM RTRD: %08X\n", ts_processed);
|
||||
KGSL_LOG_DUMP(device, "CTXT: %d TIMESTM RTRD: %08X\n",
|
||||
context->id, ts_processed);
|
||||
} else
|
||||
KGSL_LOG_DUMP(device, "BAD CTXT: %d\n", context_id);
|
||||
|
||||
num_item = adreno_ringbuffer_count(&adreno_dev->ringbuffer,
|
||||
cp_rb_rptr);
|
||||
|
@ -236,7 +236,7 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
|
||||
return 0;
|
||||
|
||||
if (init_ram) {
|
||||
rb->timestamp = 0;
|
||||
rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
|
||||
GSL_RB_INIT_TIMESTAMP(rb);
|
||||
}
|
||||
|
||||
@ -321,18 +321,13 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb, unsigned int init_ram)
|
||||
}
|
||||
|
||||
/* setup scratch/timestamp */
|
||||
adreno_regwrite(device, REG_SCRATCH_ADDR,
|
||||
device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(soptimestamp));
|
||||
adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr +
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
soptimestamp));
|
||||
|
||||
adreno_regwrite(device, REG_SCRATCH_UMSK,
|
||||
GSL_RB_MEMPTRS_SCRATCH_MASK);
|
||||
|
||||
/* update the eoptimestamp field with the last retired timestamp */
|
||||
kgsl_sharedmem_writel(&device->memstore,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp),
|
||||
rb->timestamp);
|
||||
|
||||
/* load the CP ucode */
|
||||
|
||||
status = adreno_ringbuffer_load_pm4_ucode(device);
|
||||
@ -431,15 +426,28 @@ void adreno_ringbuffer_close(struct adreno_ringbuffer *rb)
|
||||
|
||||
static uint32_t
|
||||
adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||
struct adreno_context *context,
|
||||
unsigned int flags, unsigned int *cmds,
|
||||
int sizedwords)
|
||||
{
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
|
||||
unsigned int *ringcmds;
|
||||
unsigned int timestamp;
|
||||
unsigned int total_sizedwords = sizedwords + 6;
|
||||
unsigned int total_sizedwords = sizedwords;
|
||||
unsigned int i;
|
||||
unsigned int rcmd_gpu;
|
||||
unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
|
||||
unsigned int gpuaddr = rb->device->memstore.gpuaddr;
|
||||
|
||||
if (context != NULL) {
|
||||
/*
|
||||
* if the context was not created with per context timestamp
|
||||
* support, we must use the global timestamp since issueibcmds
|
||||
* will be returning that one.
|
||||
*/
|
||||
if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
|
||||
context_id = context->id;
|
||||
}
|
||||
|
||||
/* reserve space to temporarily turn off protected mode
|
||||
* error checking if needed
|
||||
@ -451,6 +459,13 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||
if (adreno_is_a3xx(adreno_dev))
|
||||
total_sizedwords += 7;
|
||||
|
||||
total_sizedwords += 2; /* scratchpad ts for recovery */
|
||||
if (context) {
|
||||
total_sizedwords += 3; /* sop timestamp */
|
||||
total_sizedwords += 4; /* eop timestamp */
|
||||
}
|
||||
total_sizedwords += 4; /* global timestamp for recovery*/
|
||||
|
||||
ringcmds = adreno_ringbuffer_allocspace(rb, total_sizedwords);
|
||||
rcmd_gpu = rb->buffer_desc.gpuaddr
|
||||
+ sizeof(uint)*(rb->wptr-total_sizedwords);
|
||||
@ -478,12 +493,20 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, 1);
|
||||
}
|
||||
|
||||
rb->timestamp++;
|
||||
timestamp = rb->timestamp;
|
||||
/* always increment the global timestamp. once. */
|
||||
rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
|
||||
if (context) {
|
||||
if (context_id == KGSL_MEMSTORE_GLOBAL)
|
||||
rb->timestamp[context_id] =
|
||||
rb->timestamp[KGSL_MEMSTORE_GLOBAL];
|
||||
else
|
||||
rb->timestamp[context_id]++;
|
||||
}
|
||||
timestamp = rb->timestamp[context_id];
|
||||
|
||||
/* start-of-pipeline and end-of-pipeline timestamps */
|
||||
/* scratchpad ts for recovery */
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type0_packet(REG_CP_TIMESTAMP, 1));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
|
||||
|
||||
if (adreno_is_a3xx(adreno_dev)) {
|
||||
/*
|
||||
@ -499,22 +522,41 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
|
||||
}
|
||||
|
||||
if (context) {
|
||||
/* start-of-pipeline timestamp */
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu,
|
||||
cp_type3_packet(CP_MEM_WRITE, 2));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
|
||||
KGSL_MEMSTORE_OFFSET(context->id, soptimestamp)));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
|
||||
|
||||
/* end-of-pipeline timestamp */
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu,
|
||||
cp_type3_packet(CP_EVENT_WRITE, 3));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
|
||||
KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp)));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
|
||||
}
|
||||
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu,
|
||||
(rb->device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp)));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
eoptimestamp)));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
|
||||
|
||||
if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
|
||||
/* Conditional execution based on memory values */
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu,
|
||||
cp_type3_packet(CP_COND_EXEC, 4));
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ts_cmp_enable)) >> 2);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (rb->device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(ref_wait_ts)) >> 2);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
|
||||
KGSL_MEMSTORE_OFFSET(
|
||||
context_id, ts_cmp_enable)) >> 2);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
|
||||
KGSL_MEMSTORE_OFFSET(
|
||||
context_id, ref_wait_ts)) >> 2);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
|
||||
/* # of conditional command DWORDs */
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu, 2);
|
||||
GSL_RB_WRITE(ringcmds, rcmd_gpu,
|
||||
@ -533,7 +575,6 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
|
||||
|
||||
adreno_ringbuffer_submit(rb);
|
||||
|
||||
/* return timestamp of issued coREG_ands */
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@ -548,7 +589,7 @@ adreno_ringbuffer_issuecmds(struct kgsl_device *device,
|
||||
|
||||
if (device->state & KGSL_STATE_HUNG)
|
||||
return;
|
||||
adreno_ringbuffer_addcmds(rb, flags, cmds, sizedwords);
|
||||
adreno_ringbuffer_addcmds(rb, NULL, flags, cmds, sizedwords);
|
||||
}
|
||||
|
||||
static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
|
||||
@ -769,8 +810,8 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
|
||||
|
||||
if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
|
||||
KGSL_CTXT_WARN(device, "Context %p caused a gpu hang.."
|
||||
" will not accept commands for this context\n",
|
||||
drawctxt);
|
||||
" will not accept commands for context %d\n",
|
||||
drawctxt, drawctxt->id);
|
||||
return -EDEADLK;
|
||||
}
|
||||
|
||||
@ -822,6 +863,7 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
|
||||
adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
|
||||
|
||||
*timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
|
||||
drawctxt,
|
||||
KGSL_CMD_FLAGS_NOT_KERNEL_CMD,
|
||||
&link[0], (cmds - link));
|
||||
|
||||
@ -855,11 +897,25 @@ int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
|
||||
unsigned int val2;
|
||||
unsigned int val3;
|
||||
unsigned int copy_rb_contents = 0;
|
||||
unsigned int cur_context;
|
||||
struct kgsl_context *context;
|
||||
unsigned int context_id;
|
||||
|
||||
GSL_RB_GET_READPTR(rb, &rb->rptr);
|
||||
|
||||
retired_timestamp = device->ftbl->readtimestamp(device,
|
||||
/* current_context is the context that is presently active in the
|
||||
* GPU, i.e the context in which the hang is caused */
|
||||
kgsl_sharedmem_readl(&device->memstore, &context_id,
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
current_context));
|
||||
KGSL_DRV_ERR(device, "Last context id: %d\n", context_id);
|
||||
context = idr_find(&device->context_idr, context_id);
|
||||
if (context == NULL) {
|
||||
KGSL_DRV_ERR(device,
|
||||
"GPU recovery from hang not possible because last"
|
||||
" context id is invalid.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
retired_timestamp = device->ftbl->readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
KGSL_DRV_ERR(device, "GPU successfully executed till ts: %x\n",
|
||||
retired_timestamp);
|
||||
@ -894,7 +950,8 @@ int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
|
||||
(val1 == cp_type3_packet(CP_EVENT_WRITE, 3)
|
||||
&& val2 == CACHE_FLUSH_TS &&
|
||||
val3 == (rb->device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(eoptimestamp)))) {
|
||||
KGSL_MEMSTORE_OFFSET(context_id,
|
||||
eoptimestamp)))) {
|
||||
rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
|
||||
rb->buffer_desc.size);
|
||||
KGSL_DRV_ERR(device,
|
||||
@ -940,10 +997,6 @@ int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* current_context is the context that is presently active in the
|
||||
* GPU, i.e the context in which the hang is caused */
|
||||
kgsl_sharedmem_readl(&device->memstore, &cur_context,
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(current_context));
|
||||
while ((rb_rptr / sizeof(unsigned int)) != rb->wptr) {
|
||||
kgsl_sharedmem_readl(&rb->buffer_desc, &value, rb_rptr);
|
||||
rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
|
||||
@ -958,7 +1011,8 @@ int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
|
||||
rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
|
||||
rb->buffer_desc.size);
|
||||
BUG_ON(val1 != (device->memstore.gpuaddr +
|
||||
KGSL_DEVICE_MEMSTORE_OFFSET(current_context)));
|
||||
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
|
||||
current_context)));
|
||||
kgsl_sharedmem_readl(&rb->buffer_desc, &value, rb_rptr);
|
||||
rb_rptr = adreno_ringbuffer_inc_wrapped(rb_rptr,
|
||||
rb->buffer_desc.size);
|
||||
@ -970,7 +1024,7 @@ int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
|
||||
* and leave.
|
||||
*/
|
||||
|
||||
if ((copy_rb_contents == 0) && (value == cur_context)) {
|
||||
if ((copy_rb_contents == 0) && (value == context_id)) {
|
||||
KGSL_DRV_ERR(device, "GPU recovery could not "
|
||||
"find the previous context\n");
|
||||
return -EINVAL;
|
||||
@ -986,7 +1040,7 @@ int adreno_ringbuffer_extract(struct adreno_ringbuffer *rb,
|
||||
/* if context switches to a context that did not cause
|
||||
* hang then start saving the rb contents as those
|
||||
* commands can be executed */
|
||||
if (value != cur_context) {
|
||||
if (value != context_id) {
|
||||
copy_rb_contents = 1;
|
||||
temp_rb_buffer[temp_idx++] = cp_nop_packet(1);
|
||||
temp_rb_buffer[temp_idx++] =
|
||||
|
@ -54,7 +54,8 @@ struct adreno_ringbuffer {
|
||||
|
||||
unsigned int wptr; /* write pointer offset in dwords from baseaddr */
|
||||
unsigned int rptr; /* read pointer offset in dwords from baseaddr */
|
||||
uint32_t timestamp;
|
||||
|
||||
unsigned int timestamp[KGSL_MEMSTORE_MAX];
|
||||
};
|
||||
|
||||
|
||||
|
@ -58,22 +58,30 @@ static struct ion_client *kgsl_ion_client;
|
||||
* @returns - 0 on success or error code on failure
|
||||
*/
|
||||
|
||||
static int kgsl_add_event(struct kgsl_device *device, u32 ts,
|
||||
void (*cb)(struct kgsl_device *, void *, u32), void *priv,
|
||||
static int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts,
|
||||
void (*cb)(struct kgsl_device *, void *, u32, u32), void *priv,
|
||||
struct kgsl_device_private *owner)
|
||||
{
|
||||
struct kgsl_event *event;
|
||||
struct list_head *n;
|
||||
unsigned int cur = device->ftbl->readtimestamp(device,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
unsigned int cur_ts;
|
||||
struct kgsl_context *context = NULL;
|
||||
|
||||
if (cb == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (id != KGSL_MEMSTORE_GLOBAL) {
|
||||
context = idr_find(&device->context_idr, id);
|
||||
if (context == NULL)
|
||||
return -EINVAL;
|
||||
}
|
||||
cur_ts = device->ftbl->readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
|
||||
/* Check to see if the requested timestamp has already fired */
|
||||
|
||||
if (timestamp_cmp(cur, ts) >= 0) {
|
||||
cb(device, priv, cur);
|
||||
if (timestamp_cmp(cur_ts, ts) >= 0) {
|
||||
cb(device, priv, id, cur_ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -81,17 +89,24 @@ static int kgsl_add_event(struct kgsl_device *device, u32 ts,
|
||||
if (event == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
event->context = context;
|
||||
event->timestamp = ts;
|
||||
event->priv = priv;
|
||||
event->func = cb;
|
||||
event->owner = owner;
|
||||
|
||||
/* Add the event in order to the list */
|
||||
/*
|
||||
* Add the event in order to the list. Order is by context id
|
||||
* first and then by timestamp for that context.
|
||||
*/
|
||||
|
||||
for (n = device->events.next ; n != &device->events; n = n->next) {
|
||||
struct kgsl_event *e =
|
||||
list_entry(n, struct kgsl_event, list);
|
||||
|
||||
if (e->context != context)
|
||||
continue;
|
||||
|
||||
if (timestamp_cmp(e->timestamp, ts) > 0) {
|
||||
list_add(&event->list, n->prev);
|
||||
break;
|
||||
@ -115,12 +130,16 @@ static void kgsl_cancel_events(struct kgsl_device *device,
|
||||
struct kgsl_device_private *owner)
|
||||
{
|
||||
struct kgsl_event *event, *event_tmp;
|
||||
unsigned int cur = device->ftbl->readtimestamp(device,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
unsigned int id, cur;
|
||||
|
||||
list_for_each_entry_safe(event, event_tmp, &device->events, list) {
|
||||
if (event->owner != owner)
|
||||
continue;
|
||||
|
||||
cur = device->ftbl->readtimestamp(device, event->context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
|
||||
id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
|
||||
/*
|
||||
* "cancel" the events by calling their callback.
|
||||
* Currently, events are used for lock and memory
|
||||
@ -128,7 +147,7 @@ static void kgsl_cancel_events(struct kgsl_device *device,
|
||||
* thing to do is release or free.
|
||||
*/
|
||||
if (event->func)
|
||||
event->func(device, event->priv, cur);
|
||||
event->func(device, event->priv, id, cur);
|
||||
|
||||
list_del(&event->list);
|
||||
kfree(event);
|
||||
@ -265,8 +284,8 @@ kgsl_create_context(struct kgsl_device_private *dev_priv)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = idr_get_new(&dev_priv->device->context_idr,
|
||||
context, &id);
|
||||
ret = idr_get_new_above(&dev_priv->device->context_idr,
|
||||
context, 1, &id);
|
||||
|
||||
if (ret != -EAGAIN)
|
||||
break;
|
||||
@ -277,6 +296,16 @@ kgsl_create_context(struct kgsl_device_private *dev_priv)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* MAX - 1, there is one memdesc in memstore for device info */
|
||||
if (id >= KGSL_MEMSTORE_MAX) {
|
||||
KGSL_DRV_ERR(dev_priv->device, "cannot have more than %d "
|
||||
"ctxts due to memstore limitation\n",
|
||||
KGSL_MEMSTORE_MAX);
|
||||
idr_remove(&dev_priv->device->context_idr, id);
|
||||
kfree(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->id = id;
|
||||
context->dev_priv = dev_priv;
|
||||
|
||||
@ -307,25 +336,28 @@ static void kgsl_timestamp_expired(struct work_struct *work)
|
||||
ts_expired_ws);
|
||||
struct kgsl_event *event, *event_tmp;
|
||||
uint32_t ts_processed;
|
||||
unsigned int id;
|
||||
|
||||
mutex_lock(&device->mutex);
|
||||
|
||||
/* get current EOP timestamp */
|
||||
ts_processed = device->ftbl->readtimestamp(device,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
|
||||
/* Process expired events */
|
||||
list_for_each_entry_safe(event, event_tmp, &device->events, list) {
|
||||
ts_processed = device->ftbl->readtimestamp(device,
|
||||
event->context, KGSL_TIMESTAMP_RETIRED);
|
||||
if (timestamp_cmp(ts_processed, event->timestamp) < 0)
|
||||
break;
|
||||
continue;
|
||||
|
||||
id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL;
|
||||
|
||||
if (event->func)
|
||||
event->func(device, event->priv, ts_processed);
|
||||
event->func(device, event->priv, id, ts_processed);
|
||||
|
||||
list_del(&event->list);
|
||||
kfree(event);
|
||||
}
|
||||
|
||||
device->last_expired_ctxt_id = KGSL_CONTEXT_INVALID;
|
||||
|
||||
mutex_unlock(&device->mutex);
|
||||
}
|
||||
|
||||
@ -400,11 +432,15 @@ int kgsl_unregister_ts_notifier(struct kgsl_device *device,
|
||||
}
|
||||
EXPORT_SYMBOL(kgsl_unregister_ts_notifier);
|
||||
|
||||
int kgsl_check_timestamp(struct kgsl_device *device, unsigned int timestamp)
|
||||
int kgsl_check_timestamp(struct kgsl_device *device,
|
||||
struct kgsl_context *context, unsigned int timestamp)
|
||||
{
|
||||
unsigned int ts_processed;
|
||||
unsigned int global;
|
||||
|
||||
ts_processed = device->ftbl->readtimestamp(device,
|
||||
ts_processed = device->ftbl->readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
global = device->ftbl->readtimestamp(device, NULL,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
|
||||
return (timestamp_cmp(ts_processed, timestamp) >= 0);
|
||||
@ -745,6 +781,9 @@ static int kgsl_open(struct inode *inodep, struct file *filep)
|
||||
kgsl_check_suspended(device);
|
||||
|
||||
if (device->open_count == 0) {
|
||||
kgsl_sharedmem_set(&device->memstore, 0, 0,
|
||||
device->memstore.size);
|
||||
|
||||
result = device->ftbl->start(device, true);
|
||||
|
||||
if (result) {
|
||||
@ -885,21 +924,35 @@ static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
|
||||
return result;
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_device_waittimestamp(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
static long kgsl_ioctl_device_setproperty(struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data)
|
||||
{
|
||||
int result = 0;
|
||||
struct kgsl_device_waittimestamp *param = data;
|
||||
/* The getproperty struct is reused for setproperty too */
|
||||
struct kgsl_device_getproperty *param = data;
|
||||
|
||||
/* Set the active count so that suspend doesn't do the
|
||||
wrong thing */
|
||||
if (dev_priv->device->ftbl->setproperty)
|
||||
result = dev_priv->device->ftbl->setproperty(
|
||||
dev_priv->device, param->type,
|
||||
param->value, param->sizebytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static long _device_waittimestamp(struct kgsl_device_private *dev_priv,
|
||||
struct kgsl_context *context,
|
||||
unsigned int timestamp,
|
||||
unsigned int timeout)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/* Set the active count so that suspend doesn't do the wrong thing */
|
||||
|
||||
dev_priv->device->active_cnt++;
|
||||
|
||||
result = dev_priv->device->ftbl->waittimestamp(dev_priv->device,
|
||||
param->timestamp,
|
||||
param->timeout);
|
||||
context, timestamp, timeout);
|
||||
|
||||
|
||||
/* Fire off any pending suspend operations that are in flight */
|
||||
|
||||
@ -910,6 +963,34 @@ static long kgsl_ioctl_device_waittimestamp(struct kgsl_device_private
|
||||
return result;
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_device_waittimestamp(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
{
|
||||
struct kgsl_device_waittimestamp *param = data;
|
||||
|
||||
return _device_waittimestamp(dev_priv, KGSL_MEMSTORE_GLOBAL,
|
||||
param->timestamp, param->timeout);
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_device_waittimestamp_ctxtid(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
{
|
||||
struct kgsl_device_waittimestamp_ctxtid *param = data;
|
||||
struct kgsl_context *context;
|
||||
|
||||
context = kgsl_find_context(dev_priv, param->context_id);
|
||||
if (context == NULL) {
|
||||
KGSL_DRV_ERR(dev_priv->device, "invalid context_id %d\n",
|
||||
param->context_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return _device_waittimestamp(dev_priv, context,
|
||||
param->timestamp, param->timeout);
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data)
|
||||
{
|
||||
@ -926,7 +1007,7 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
|
||||
if (context == NULL) {
|
||||
result = -EINVAL;
|
||||
KGSL_DRV_ERR(dev_priv->device,
|
||||
"invalid drawctxt drawctxt_id %d\n",
|
||||
"invalid context_id %d\n",
|
||||
param->drawctxt_id);
|
||||
goto done;
|
||||
}
|
||||
@ -997,21 +1078,46 @@ done:
|
||||
return result;
|
||||
}
|
||||
|
||||
static long _cmdstream_readtimestamp(struct kgsl_device_private *dev_priv,
|
||||
struct kgsl_context *context, unsigned int type,
|
||||
unsigned int *timestamp)
|
||||
{
|
||||
*timestamp = dev_priv->device->ftbl->readtimestamp(dev_priv->device,
|
||||
context, type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_cmdstream_readtimestamp(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
{
|
||||
struct kgsl_cmdstream_readtimestamp *param = data;
|
||||
|
||||
param->timestamp =
|
||||
dev_priv->device->ftbl->readtimestamp(dev_priv->device,
|
||||
param->type);
|
||||
return _cmdstream_readtimestamp(dev_priv, NULL,
|
||||
param->type, ¶m->timestamp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
static long kgsl_ioctl_cmdstream_readtimestamp_ctxtid(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
{
|
||||
struct kgsl_cmdstream_readtimestamp_ctxtid *param = data;
|
||||
struct kgsl_context *context;
|
||||
|
||||
context = kgsl_find_context(dev_priv, param->context_id);
|
||||
if (context == NULL) {
|
||||
KGSL_DRV_ERR(dev_priv->device, "invalid context_id %d\n",
|
||||
param->context_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return _cmdstream_readtimestamp(dev_priv, context,
|
||||
param->type, ¶m->timestamp);
|
||||
}
|
||||
|
||||
static void kgsl_freemem_event_cb(struct kgsl_device *device,
|
||||
void *priv, u32 timestamp)
|
||||
void *priv, u32 id, u32 timestamp)
|
||||
{
|
||||
struct kgsl_mem_entry *entry = priv;
|
||||
spin_lock(&entry->priv->mem_lock);
|
||||
@ -1020,30 +1126,65 @@ static void kgsl_freemem_event_cb(struct kgsl_device *device,
|
||||
kgsl_mem_entry_detach_process(entry);
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv,
|
||||
unsigned int gpuaddr, struct kgsl_context *context,
|
||||
unsigned int timestamp, unsigned int type)
|
||||
{
|
||||
int result = 0;
|
||||
struct kgsl_cmdstream_freememontimestamp *param = data;
|
||||
struct kgsl_mem_entry *entry = NULL;
|
||||
struct kgsl_device *device = dev_priv->device;
|
||||
unsigned int cur;
|
||||
unsigned int context_id = context ? context->id : KGSL_MEMSTORE_GLOBAL;
|
||||
|
||||
spin_lock(&dev_priv->process_priv->mem_lock);
|
||||
entry = kgsl_sharedmem_find(dev_priv->process_priv, param->gpuaddr);
|
||||
entry = kgsl_sharedmem_find(dev_priv->process_priv, gpuaddr);
|
||||
spin_unlock(&dev_priv->process_priv->mem_lock);
|
||||
|
||||
if (entry) {
|
||||
result = kgsl_add_event(dev_priv->device, param->timestamp,
|
||||
kgsl_freemem_event_cb, entry, dev_priv);
|
||||
cur = device->ftbl->readtimestamp(device, context,
|
||||
KGSL_TIMESTAMP_RETIRED);
|
||||
|
||||
result = kgsl_add_event(dev_priv->device, context_id,
|
||||
timestamp, kgsl_freemem_event_cb,
|
||||
entry, dev_priv);
|
||||
} else {
|
||||
KGSL_DRV_ERR(dev_priv->device,
|
||||
"invalid gpuaddr %08x\n", param->gpuaddr);
|
||||
"invalid gpuaddr %08x\n", gpuaddr);
|
||||
result = -EINVAL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_cmdstream_freememontimestamp(struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
{
|
||||
struct kgsl_cmdstream_freememontimestamp *param = data;
|
||||
|
||||
return _cmdstream_freememontimestamp(dev_priv, param->gpuaddr,
|
||||
NULL, param->timestamp, param->type);
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_cmdstream_freememontimestamp_ctxtid(
|
||||
struct kgsl_device_private
|
||||
*dev_priv, unsigned int cmd,
|
||||
void *data)
|
||||
{
|
||||
struct kgsl_cmdstream_freememontimestamp_ctxtid *param = data;
|
||||
struct kgsl_context *context;
|
||||
|
||||
context = kgsl_find_context(dev_priv, param->context_id);
|
||||
if (context == NULL) {
|
||||
KGSL_DRV_ERR(dev_priv->device,
|
||||
"invalid drawctxt context_id %d\n", param->context_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return _cmdstream_freememontimestamp(dev_priv, param->gpuaddr,
|
||||
context, param->timestamp, param->type);
|
||||
}
|
||||
|
||||
static long kgsl_ioctl_drawctxt_create(struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data)
|
||||
{
|
||||
@ -1760,13 +1901,14 @@ 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
|
||||
*
|
||||
* Release a genlock lock following the expiration of a timestamp
|
||||
*/
|
||||
|
||||
static void kgsl_genlock_event_cb(struct kgsl_device *device,
|
||||
void *priv, u32 timestamp)
|
||||
void *priv, u32 context_id, u32 timestamp)
|
||||
{
|
||||
struct kgsl_genlock_event_priv *ev = priv;
|
||||
int ret;
|
||||
@ -1794,7 +1936,7 @@ static void kgsl_genlock_event_cb(struct kgsl_device *device,
|
||||
*/
|
||||
|
||||
static int kgsl_add_genlock_event(struct kgsl_device *device,
|
||||
u32 timestamp, void __user *data, int len,
|
||||
u32 context_id, u32 timestamp, void __user *data, int len,
|
||||
struct kgsl_device_private *owner)
|
||||
{
|
||||
struct kgsl_genlock_event_priv *event;
|
||||
@ -1820,8 +1962,8 @@ static int kgsl_add_genlock_event(struct kgsl_device *device,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = kgsl_add_event(device, timestamp, kgsl_genlock_event_cb, event,
|
||||
owner);
|
||||
ret = kgsl_add_event(device, context_id, timestamp,
|
||||
kgsl_genlock_event_cb, event, owner);
|
||||
if (ret)
|
||||
kfree(event);
|
||||
|
||||
@ -1829,7 +1971,7 @@ static int kgsl_add_genlock_event(struct kgsl_device *device,
|
||||
}
|
||||
#else
|
||||
static long kgsl_add_genlock_event(struct kgsl_device *device,
|
||||
u32 timestamp, void __user *data, int len,
|
||||
u32 context_id, u32 timestamp, void __user *data, int len,
|
||||
struct kgsl_device_private *owner)
|
||||
{
|
||||
return -EINVAL;
|
||||
@ -1853,8 +1995,8 @@ static long kgsl_ioctl_timestamp_event(struct kgsl_device_private *dev_priv,
|
||||
switch (param->type) {
|
||||
case KGSL_TIMESTAMP_EVENT_GENLOCK:
|
||||
ret = kgsl_add_genlock_event(dev_priv->device,
|
||||
param->timestamp, param->priv, param->len,
|
||||
dev_priv);
|
||||
param->context_id, param->timestamp, param->priv,
|
||||
param->len, dev_priv);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@ -1878,12 +2020,18 @@ static const struct {
|
||||
kgsl_ioctl_device_getproperty, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP,
|
||||
kgsl_ioctl_device_waittimestamp, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID,
|
||||
kgsl_ioctl_device_waittimestamp_ctxtid, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS,
|
||||
kgsl_ioctl_rb_issueibcmds, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_READTIMESTAMP,
|
||||
kgsl_ioctl_cmdstream_readtimestamp, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID,
|
||||
kgsl_ioctl_cmdstream_readtimestamp_ctxtid, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP,
|
||||
kgsl_ioctl_cmdstream_freememontimestamp, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID,
|
||||
kgsl_ioctl_cmdstream_freememontimestamp_ctxtid, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE,
|
||||
kgsl_ioctl_drawctxt_create, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY,
|
||||
@ -1906,6 +2054,8 @@ static const struct {
|
||||
kgsl_ioctl_cff_user_event, 0),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
|
||||
kgsl_ioctl_timestamp_event, 1),
|
||||
KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY,
|
||||
kgsl_ioctl_device_setproperty, 1),
|
||||
};
|
||||
|
||||
static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
@ -2211,13 +2361,13 @@ kgsl_register_device(struct kgsl_device *device)
|
||||
|
||||
INIT_LIST_HEAD(&device->events);
|
||||
|
||||
device->last_expired_ctxt_id = KGSL_CONTEXT_INVALID;
|
||||
|
||||
ret = kgsl_mmu_init(device);
|
||||
if (ret != 0)
|
||||
goto err_dest_work_q;
|
||||
|
||||
ret = kgsl_allocate_contiguous(&device->memstore,
|
||||
sizeof(struct kgsl_devmemstore));
|
||||
|
||||
ret = kgsl_allocate_contiguous(&device->memstore, KGSL_MEMSTORE_SIZE);
|
||||
if (ret != 0)
|
||||
goto err_close_mmu;
|
||||
|
||||
|
@ -25,6 +25,14 @@
|
||||
|
||||
#define KGSL_NAME "kgsl"
|
||||
|
||||
/* The number of memstore arrays limits the number of contexts allowed.
|
||||
* If more contexts are needed, update multiple for MEMSTORE_SIZE
|
||||
*/
|
||||
#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 2))
|
||||
#define KGSL_MEMSTORE_GLOBAL (0)
|
||||
#define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \
|
||||
sizeof(struct kgsl_devmemstore) - 1)
|
||||
|
||||
/* Timestamp window used to detect rollovers */
|
||||
#define KGSL_TIMESTAMP_WINDOW 0x80000000
|
||||
|
||||
@ -150,6 +158,7 @@ struct kgsl_mem_entry {
|
||||
void *priv_data;
|
||||
struct list_head list;
|
||||
uint32_t free_timestamp;
|
||||
unsigned int context_id;
|
||||
/* back pointer to private structure under whose context this
|
||||
* allocation is made */
|
||||
struct kgsl_process_private *priv;
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
|
||||
/* Copyright (c) 2002,2007-2012, Code Aurora Forum. 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
|
||||
@ -47,6 +46,7 @@
|
||||
#define KGSL_STATE_SUSPEND 0x00000010
|
||||
#define KGSL_STATE_HUNG 0x00000020
|
||||
#define KGSL_STATE_DUMP_AND_RECOVER 0x00000040
|
||||
#define KGSL_STATE_SLUMBER 0x00000080
|
||||
|
||||
#define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK 0x1000000
|
||||
|
||||
@ -76,9 +76,10 @@ struct kgsl_functable {
|
||||
enum kgsl_property_type type, void *value,
|
||||
unsigned int sizebytes);
|
||||
int (*waittimestamp) (struct kgsl_device *device,
|
||||
unsigned int timestamp, unsigned int msecs);
|
||||
struct kgsl_context *context, unsigned int timestamp,
|
||||
unsigned int msecs);
|
||||
unsigned int (*readtimestamp) (struct kgsl_device *device,
|
||||
enum kgsl_timestamp_type type);
|
||||
struct kgsl_context *context, enum kgsl_timestamp_type type);
|
||||
int (*issueibcmds) (struct kgsl_device_private *dev_priv,
|
||||
struct kgsl_context *context, struct kgsl_ibdesc *ibdesc,
|
||||
unsigned int sizedwords, uint32_t *timestamp,
|
||||
@ -101,6 +102,9 @@ struct kgsl_functable {
|
||||
struct kgsl_context *context);
|
||||
long (*ioctl) (struct kgsl_device_private *dev_priv,
|
||||
unsigned int cmd, void *data);
|
||||
int (*setproperty) (struct kgsl_device *device,
|
||||
enum kgsl_property_type type, void *value,
|
||||
unsigned int sizebytes);
|
||||
};
|
||||
|
||||
struct kgsl_memregion {
|
||||
@ -120,8 +124,9 @@ struct kgsl_mh {
|
||||
};
|
||||
|
||||
struct kgsl_event {
|
||||
struct kgsl_context *context;
|
||||
uint32_t timestamp;
|
||||
void (*func)(struct kgsl_device *, void *, u32);
|
||||
void (*func)(struct kgsl_device *, void *, u32, u32);
|
||||
void *priv;
|
||||
struct list_head list;
|
||||
struct kgsl_device_private *owner;
|
||||
@ -153,6 +158,7 @@ struct kgsl_device {
|
||||
uint32_t state;
|
||||
uint32_t requested_state;
|
||||
|
||||
unsigned int last_expired_ctxt_id;
|
||||
unsigned int active_cnt;
|
||||
struct completion suspend_gate;
|
||||
|
||||
@ -304,7 +310,8 @@ kgsl_find_context(struct kgsl_device_private *dev_priv, uint32_t id)
|
||||
return (ctxt && ctxt->dev_priv == dev_priv) ? ctxt : NULL;
|
||||
}
|
||||
|
||||
int kgsl_check_timestamp(struct kgsl_device *device, unsigned int timestamp);
|
||||
int kgsl_check_timestamp(struct kgsl_device *device,
|
||||
struct kgsl_context *context, unsigned int timestamp);
|
||||
|
||||
int kgsl_register_ts_notifier(struct kgsl_device *device,
|
||||
struct notifier_block *nb);
|
||||
|
14
drivers/gpu/msm/z180.c
Normal file → Executable file
14
drivers/gpu/msm/z180.c
Normal file → Executable file
@ -100,6 +100,7 @@ enum z180_cmdwindow_type {
|
||||
static int z180_start(struct kgsl_device *device, unsigned int init_ram);
|
||||
static int z180_stop(struct kgsl_device *device);
|
||||
static int z180_wait(struct kgsl_device *device,
|
||||
struct kgsl_context *context,
|
||||
unsigned int timestamp,
|
||||
unsigned int msecs);
|
||||
static void z180_regread(struct kgsl_device *device,
|
||||
@ -382,8 +383,8 @@ static int z180_idle(struct kgsl_device *device, unsigned int timeout)
|
||||
|
||||
if (timestamp_cmp(z180_dev->current_timestamp,
|
||||
z180_dev->timestamp) > 0)
|
||||
status = z180_wait(device, z180_dev->current_timestamp,
|
||||
timeout);
|
||||
status = z180_wait(device, NULL,
|
||||
z180_dev->current_timestamp, timeout);
|
||||
|
||||
if (status)
|
||||
KGSL_DRV_ERR(device, "z180_waittimestamp() timed out\n");
|
||||
@ -793,14 +794,16 @@ static void z180_cmdwindow_write(struct kgsl_device *device,
|
||||
}
|
||||
|
||||
static unsigned int z180_readtimestamp(struct kgsl_device *device,
|
||||
enum kgsl_timestamp_type type)
|
||||
struct kgsl_context *context, enum kgsl_timestamp_type type)
|
||||
{
|
||||
struct z180_device *z180_dev = Z180_DEVICE(device);
|
||||
(void)context;
|
||||
/* get current EOP timestamp */
|
||||
return z180_dev->timestamp;
|
||||
}
|
||||
|
||||
static int z180_waittimestamp(struct kgsl_device *device,
|
||||
struct kgsl_context *context,
|
||||
unsigned int timestamp,
|
||||
unsigned int msecs)
|
||||
{
|
||||
@ -811,13 +814,14 @@ static int z180_waittimestamp(struct kgsl_device *device,
|
||||
msecs = 10 * MSEC_PER_SEC;
|
||||
|
||||
mutex_unlock(&device->mutex);
|
||||
status = z180_wait(device, timestamp, msecs);
|
||||
status = z180_wait(device, context, timestamp, msecs);
|
||||
mutex_lock(&device->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int z180_wait(struct kgsl_device *device,
|
||||
struct kgsl_context *context,
|
||||
unsigned int timestamp,
|
||||
unsigned int msecs)
|
||||
{
|
||||
@ -826,7 +830,7 @@ static int z180_wait(struct kgsl_device *device,
|
||||
|
||||
timeout = wait_io_event_interruptible_timeout(
|
||||
device->wait_queue,
|
||||
kgsl_check_timestamp(device, timestamp),
|
||||
kgsl_check_timestamp(device, context, timestamp),
|
||||
msecs_to_jiffies(msecs));
|
||||
|
||||
if (timeout > 0)
|
||||
|
@ -35,14 +35,18 @@
|
||||
#define _MSM_KGSL_H
|
||||
|
||||
#define KGSL_VERSION_MAJOR 3
|
||||
#define KGSL_VERSION_MINOR 8
|
||||
#define KGSL_VERSION_MINOR 10
|
||||
|
||||
/*context flags */
|
||||
#define KGSL_CONTEXT_SAVE_GMEM 1
|
||||
#define KGSL_CONTEXT_NO_GMEM_ALLOC 2
|
||||
#define KGSL_CONTEXT_SUBMIT_IB_LIST 4
|
||||
#define KGSL_CONTEXT_CTX_SWITCH 8
|
||||
#define KGSL_CONTEXT_PREAMBLE 16
|
||||
#define KGSL_CONTEXT_SAVE_GMEM 0x00000001
|
||||
#define KGSL_CONTEXT_NO_GMEM_ALLOC 0x00000002
|
||||
#define KGSL_CONTEXT_SUBMIT_IB_LIST 0x00000004
|
||||
#define KGSL_CONTEXT_CTX_SWITCH 0x00000008
|
||||
#define KGSL_CONTEXT_PREAMBLE 0x00000010
|
||||
#define KGSL_CONTEXT_TRASH_STATE 0x00000020
|
||||
#define KGSL_CONTEXT_PER_CONTEXT_TS 0x00000040
|
||||
|
||||
#define KGSL_CONTEXT_INVALID 0xffffffff
|
||||
|
||||
/* Memory allocayion flags */
|
||||
#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000
|
||||
@ -58,6 +62,7 @@
|
||||
#define KGSL_FLAGS_RESERVED1 0x00000040
|
||||
#define KGSL_FLAGS_RESERVED2 0x00000080
|
||||
#define KGSL_FLAGS_SOFT_RESET 0x00000100
|
||||
#define KGSL_FLAGS_PER_CONTEXT_TIMESTAMPS 0x00000200
|
||||
|
||||
/* Clock flags to show which clocks should be controled by a given platform */
|
||||
#define KGSL_CLK_SRC 0x00000001
|
||||
@ -132,9 +137,9 @@ struct kgsl_devmemstore {
|
||||
unsigned int sbz5;
|
||||
};
|
||||
|
||||
#define KGSL_DEVICE_MEMSTORE_OFFSET(field) \
|
||||
offsetof(struct kgsl_devmemstore, field)
|
||||
|
||||
#define KGSL_MEMSTORE_OFFSET(ctxt_id, field) \
|
||||
((ctxt_id)*sizeof(struct kgsl_devmemstore) + \
|
||||
offsetof(struct kgsl_devmemstore, field))
|
||||
|
||||
/* timestamp id*/
|
||||
enum kgsl_timestamp_type {
|
||||
@ -268,6 +273,14 @@ struct kgsl_device_waittimestamp {
|
||||
#define IOCTL_KGSL_DEVICE_WAITTIMESTAMP \
|
||||
_IOW(KGSL_IOC_TYPE, 0x6, struct kgsl_device_waittimestamp)
|
||||
|
||||
struct kgsl_device_waittimestamp_ctxtid {
|
||||
unsigned int context_id;
|
||||
unsigned int timestamp;
|
||||
unsigned int timeout;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID \
|
||||
_IOW(KGSL_IOC_TYPE, 0x7, struct kgsl_device_waittimestamp_ctxtid)
|
||||
|
||||
/* issue indirect commands to the GPU.
|
||||
* drawctxt_id must have been created with IOCTL_KGSL_DRAWCTXT_CREATE
|
||||
@ -361,6 +374,26 @@ struct kgsl_map_user_mem {
|
||||
#define IOCTL_KGSL_MAP_USER_MEM \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x15, struct kgsl_map_user_mem)
|
||||
|
||||
struct kgsl_cmdstream_readtimestamp_ctxtid {
|
||||
unsigned int context_id;
|
||||
unsigned int type;
|
||||
unsigned int timestamp; /*output param */
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID \
|
||||
_IOWR(KGSL_IOC_TYPE, 0x16, struct kgsl_cmdstream_readtimestamp_ctxtid)
|
||||
|
||||
struct kgsl_cmdstream_freememontimestamp_ctxtid {
|
||||
unsigned int context_id;
|
||||
unsigned int gpuaddr;
|
||||
unsigned int type;
|
||||
unsigned int timestamp;
|
||||
};
|
||||
|
||||
#define IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID \
|
||||
_IOW(KGSL_IOC_TYPE, 0x17, \
|
||||
struct kgsl_cmdstream_freememontimestamp_ctxtid)
|
||||
|
||||
/* add a block of pmem or fb into the GPU address space */
|
||||
struct kgsl_sharedmem_from_pmem {
|
||||
int pmem_fd;
|
||||
@ -504,6 +537,14 @@ struct kgsl_timestamp_event_genlock {
|
||||
int handle; /* Handle of the genlock lock to release */
|
||||
};
|
||||
|
||||
/*
|
||||
* Set a property within the kernel. Uses the same structure as
|
||||
* IOCTL_KGSL_GETPROPERTY
|
||||
*/
|
||||
|
||||
#define IOCTL_KGSL_SETPROPERTY \
|
||||
_IOW(KGSL_IOC_TYPE, 0x32, struct kgsl_device_getproperty)
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef CONFIG_MSM_KGSL_DRM
|
||||
int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
|
||||
|
Loading…
x
Reference in New Issue
Block a user