msm: kgsl: Write the profiling reference data before submission

Update the GPU ticks and CPU time in the user profiling buffer
before sending the command to the GPU. This removes a small
race condition where the GPU updates the execution profiling
data before the CPU has updated the reference data.
In this case the reference data is still set to the default
value when the profiling data is read by the user.

Change-Id: I65c9d5c3235eeee2353816d65d8eefdab961f9f8
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
tirimbino
Harshdeep Dhatt 7 years ago committed by Gerrit - the friendly Code Review server
parent 2873410996
commit bb9bfbc606
  1. 2
      drivers/gpu/msm/adreno_dispatch.c
  2. 86
      drivers/gpu/msm/adreno_ringbuffer.c
  3. 4
      drivers/gpu/msm/adreno_ringbuffer.h

@ -565,6 +565,8 @@ static int sendcmd(struct adreno_device *adreno_dev,
return -EBUSY;
}
memset(&time, 0x0, sizeof(time));
dispatcher->inflight++;
dispatch_q->inflight++;

@ -121,13 +121,60 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev,
}
static void adreno_profile_submit_time(struct adreno_submit_time *time)
{
struct kgsl_drawobj *drawobj;
struct kgsl_drawobj_cmd *cmdobj;
struct kgsl_mem_entry *entry;
if (time == NULL)
return;
drawobj = time->drawobj;
if (drawobj == NULL)
return;
cmdobj = CMDOBJ(drawobj);
entry = cmdobj->profiling_buf_entry;
if (entry) {
struct kgsl_drawobj_profiling_buffer *profile_buffer;
profile_buffer = kgsl_gpuaddr_to_vaddr(&entry->memdesc,
cmdobj->profiling_buffer_gpuaddr);
if (profile_buffer == NULL)
return;
/* Return kernel clock time to the the client if requested */
if (drawobj->flags & KGSL_DRAWOBJ_PROFILING_KTIME) {
uint64_t secs = time->ktime;
profile_buffer->wall_clock_ns =
do_div(secs, NSEC_PER_SEC);
profile_buffer->wall_clock_s = secs;
} else {
profile_buffer->wall_clock_s = time->utime.tv_sec;
profile_buffer->wall_clock_ns = time->utime.tv_nsec;
}
profile_buffer->gpu_ticks_queued = time->ticks;
kgsl_memdesc_unmap(&entry->memdesc);
}
}
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb,
struct adreno_submit_time *time)
{
struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
if (time != NULL)
if (time != NULL) {
adreno_get_submit_time(adreno_dev, rb, time);
/* Put the timevalues in the profiling buffer */
adreno_profile_submit_time(time);
}
adreno_ringbuffer_wptr(adreno_dev, rb);
}
@ -776,16 +823,12 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
int flags = KGSL_CMD_FLAGS_NONE;
int ret;
struct adreno_ringbuffer *rb;
struct kgsl_drawobj_profiling_buffer *profile_buffer = NULL;
unsigned int dwords = 0;
struct adreno_submit_time local;
struct kgsl_mem_entry *entry = cmdobj->profiling_buf_entry;
struct adreno_firmware *fw = ADRENO_FW(adreno_dev, ADRENO_FW_SQE);
bool set_ib1list_marker = false;
if (entry)
profile_buffer = kgsl_gpuaddr_to_vaddr(&entry->memdesc,
cmdobj->profiling_buffer_gpuaddr);
memset(&local, 0x0, sizeof(local));
context = drawobj->context;
drawctxt = ADRENO_CONTEXT(context);
@ -857,7 +900,8 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
dwords += (numibs * 30);
if (drawobj->flags & KGSL_DRAWOBJ_PROFILING &&
!adreno_is_a3xx(adreno_dev) && profile_buffer) {
!adreno_is_a3xx(adreno_dev) &&
(cmdobj->profiling_buf_entry != NULL)) {
user_profiling = true;
dwords += 6;
@ -877,6 +921,8 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
if (time == NULL)
time = &local;
time->drawobj = drawobj;
}
if (test_bit(CMDOBJ_PROFILE, &cmdobj->priv)) {
@ -1029,35 +1075,9 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
if (!ret) {
set_bit(KGSL_CONTEXT_PRIV_SUBMITTED, &context->priv);
cmdobj->global_ts = drawctxt->internal_timestamp;
/* Put the timevalues in the profiling buffer */
if (user_profiling) {
/*
* Return kernel clock time to the the client
* if requested
*/
if (drawobj->flags & KGSL_DRAWOBJ_PROFILING_KTIME) {
uint64_t secs = time->ktime;
profile_buffer->wall_clock_ns =
do_div(secs, NSEC_PER_SEC);
profile_buffer->wall_clock_s = secs;
} else {
profile_buffer->wall_clock_s =
time->utime.tv_sec;
profile_buffer->wall_clock_ns =
time->utime.tv_nsec;
}
profile_buffer->gpu_ticks_queued = time->ticks;
}
}
done:
/* Corresponding unmap to the memdesc map of profile_buffer */
if (entry)
kgsl_memdesc_unmap(&entry->memdesc);
trace_kgsl_issueibcmds(device, context->id, numibs, drawobj->timestamp,
drawobj->flags, ret, drawctxt->type);

@ -1,4 +1,4 @@
/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002,2007-2018, 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
@ -43,11 +43,13 @@ struct kgsl_device_private;
* @ticks: GPU ticks at submit time (from the 19.2Mhz timer)
* @ktime: local clock time (in nanoseconds)
* @utime: Wall clock time
* @drawobj: the object that we want to profile
*/
struct adreno_submit_time {
uint64_t ticks;
u64 ktime;
struct timespec utime;
struct kgsl_drawobj *drawobj;
};
/**

Loading…
Cancel
Save