Merge "msm: kgsl: Revisit the GPU snapshot dumping"

This commit is contained in:
Linux Build Service Account 2016-09-29 11:20:49 -07:00 committed by Gerrit - the friendly Code Review server
commit be6bc701ce
4 changed files with 172 additions and 67 deletions

View file

@ -108,7 +108,7 @@ static void push_object(int type,
} }
/* /*
* Return a 1 if the specified object is already on the list of buffers * Returns index of the specified object is already on the list of buffers
* to be dumped * to be dumped
*/ */
@ -120,10 +120,9 @@ static int find_object(int type, uint64_t gpuaddr,
for (index = 0; index < objbufptr; index++) { for (index = 0; index < objbufptr; index++) {
if (objbuf[index].gpuaddr == gpuaddr && if (objbuf[index].gpuaddr == gpuaddr &&
objbuf[index].entry->priv == process) objbuf[index].entry->priv == process)
return 1; return index;
} }
return -ENOENT;
return 0;
} }
/* /*
@ -196,8 +195,6 @@ static inline void parse_ib(struct kgsl_device *device,
struct kgsl_process_private *process, struct kgsl_process_private *process,
uint64_t gpuaddr, uint64_t dwords) uint64_t gpuaddr, uint64_t dwords)
{ {
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
uint64_t ib1base;
struct adreno_ib_object_list *ib_obj_list; struct adreno_ib_object_list *ib_obj_list;
/* /*
@ -205,11 +202,7 @@ static inline void parse_ib(struct kgsl_device *device,
* then push it into the static blob otherwise put it in the dynamic * then push it into the static blob otherwise put it in the dynamic
* list * list
*/ */
if (gpuaddr == snapshot->ib1base) {
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
ADRENO_REG_CP_IB1_BASE_HI, &ib1base);
if (gpuaddr == ib1base) {
push_object(SNAPSHOT_OBJ_TYPE_IB, process, push_object(SNAPSHOT_OBJ_TYPE_IB, process,
gpuaddr, dwords); gpuaddr, dwords);
return; return;
@ -295,17 +288,12 @@ static void snapshot_rb_ibs(struct kgsl_device *device,
{ {
struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
unsigned int rptr, *rbptr; unsigned int rptr, *rbptr;
uint64_t ibbase;
int index, i; int index, i;
int parse_ibs = 0, ib_parse_start; int parse_ibs = 0, ib_parse_start;
/* Get the current read pointers for the RB */ /* Get the current read pointers for the RB */
adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr); adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr);
/* Address of the last processed IB */
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
ADRENO_REG_CP_IB1_BASE_HI, &ibbase);
/* /*
* Figure out the window of ringbuffer data to dump. First we need to * Figure out the window of ringbuffer data to dump. First we need to
* find where the last processed IB ws submitted. Start walking back * find where the last processed IB ws submitted. Start walking back
@ -333,14 +321,14 @@ static void snapshot_rb_ibs(struct kgsl_device *device,
if (adreno_cmd_is_ib(adreno_dev, rbptr[index])) { if (adreno_cmd_is_ib(adreno_dev, rbptr[index])) {
if (ADRENO_LEGACY_PM4(adreno_dev)) { if (ADRENO_LEGACY_PM4(adreno_dev)) {
if (rbptr[index + 1] == ibbase) if (rbptr[index + 1] == snapshot->ib1base)
break; break;
} else { } else {
uint64_t ibaddr; uint64_t ibaddr;
ibaddr = rbptr[index + 2]; ibaddr = rbptr[index + 2];
ibaddr = ibaddr << 32 | rbptr[index + 1]; ibaddr = ibaddr << 32 | rbptr[index + 1];
if (ibaddr == ibbase) if (ibaddr == snapshot->ib1base)
break; break;
} }
} }
@ -564,6 +552,67 @@ struct snapshot_ib_meta {
uint64_t ib2size; uint64_t ib2size;
}; };
void kgsl_snapshot_add_active_ib_obj_list(struct kgsl_device *device,
struct kgsl_snapshot *snapshot)
{
struct adreno_ib_object_list *ib_obj_list;
int index = -ENOENT;
if (!snapshot->ib1dumped)
index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base,
snapshot->process);
/* only do this for IB1 because the IB2's are part of IB1 objects */
if ((index != -ENOENT) &&
(snapshot->ib1base == objbuf[index].gpuaddr)) {
if (-E2BIG == adreno_ib_create_object_list(device,
objbuf[index].entry->priv,
objbuf[index].gpuaddr,
objbuf[index].size >> 2,
&ib_obj_list))
ib_max_objs = 1;
if (ib_obj_list) {
/* freeze the IB objects in the IB */
snapshot_freeze_obj_list(snapshot,
objbuf[index].entry->priv,
ib_obj_list, snapshot->ib2base);
adreno_ib_destroy_obj_list(ib_obj_list);
}
} else {
/* Get the IB2 index from parsed object */
index = find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base,
snapshot->process);
if (index != -ENOENT)
parse_ib(device, snapshot, snapshot->process,
snapshot->ib2base, objbuf[index].size >> 2);
}
}
/*
* active_ib_is_parsed() - Checks if active ib is already parsed
* @gpuaddr: Active IB base address at the time of fault
* @size: Active IB size
* @process: The process to which the IB belongs
*
* Function returns true if the active is already is parsed
* else false
*/
static bool active_ib_is_parsed(uint64_t gpuaddr, uint64_t size,
struct kgsl_process_private *process)
{
int index;
/* go through the static list for gpuaddr is in list or not */
for (index = 0; index < objbufptr; index++) {
if ((objbuf[index].gpuaddr <= gpuaddr) &&
((objbuf[index].gpuaddr +
(objbuf[index].size)) >=
(gpuaddr + size)) &&
(objbuf[index].entry->priv == process))
return true;
}
return false;
}
/* Snapshot the memory for an indirect buffer */ /* Snapshot the memory for an indirect buffer */
static size_t snapshot_ib(struct kgsl_device *device, u8 *buf, static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
size_t remain, void *priv) size_t remain, void *priv)
@ -596,13 +645,11 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
return 0; return 0;
} }
if (remain < (obj->size + sizeof(*header))) {
KGSL_CORE_ERR("snapshot: Not enough memory for the ib\n");
return 0;
}
/* only do this for IB1 because the IB2's are part of IB1 objects */ /* only do this for IB1 because the IB2's are part of IB1 objects */
if (meta->ib1base == obj->gpuaddr) { if (meta->ib1base == obj->gpuaddr) {
snapshot->ib1dumped = active_ib_is_parsed(obj->gpuaddr,
obj->size, obj->entry->priv);
if (-E2BIG == adreno_ib_create_object_list(device, if (-E2BIG == adreno_ib_create_object_list(device,
obj->entry->priv, obj->entry->priv,
obj->gpuaddr, obj->size >> 2, obj->gpuaddr, obj->size >> 2,
@ -617,6 +664,11 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
} }
} }
if (meta->ib2base == obj->gpuaddr)
snapshot->ib2dumped = active_ib_is_parsed(obj->gpuaddr,
obj->size, obj->entry->priv);
/* Write the sub-header for the section */ /* Write the sub-header for the section */
header->gpuaddr = obj->gpuaddr; header->gpuaddr = obj->gpuaddr;
header->ptbase = header->ptbase =
@ -632,9 +684,7 @@ static size_t snapshot_ib(struct kgsl_device *device, u8 *buf,
/* Dump another item on the current pending list */ /* Dump another item on the current pending list */
static void dump_object(struct kgsl_device *device, int obj, static void dump_object(struct kgsl_device *device, int obj,
struct kgsl_snapshot *snapshot, struct kgsl_snapshot *snapshot)
uint64_t ib1base, uint64_t ib1size,
uint64_t ib2base, uint64_t ib2size)
{ {
struct snapshot_ib_meta meta; struct snapshot_ib_meta meta;
@ -642,10 +692,10 @@ static void dump_object(struct kgsl_device *device, int obj,
case SNAPSHOT_OBJ_TYPE_IB: case SNAPSHOT_OBJ_TYPE_IB:
meta.snapshot = snapshot; meta.snapshot = snapshot;
meta.obj = &objbuf[obj]; meta.obj = &objbuf[obj];
meta.ib1base = ib1base; meta.ib1base = snapshot->ib1base;
meta.ib1size = ib1size; meta.ib1size = snapshot->ib1size;
meta.ib2base = ib2base; meta.ib2base = snapshot->ib2base;
meta.ib2size = ib2size; meta.ib2size = snapshot->ib2size;
kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB_V2, kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB_V2,
snapshot, snapshot_ib, &meta); snapshot, snapshot_ib, &meta);
@ -792,8 +842,6 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
struct kgsl_context *context) struct kgsl_context *context)
{ {
unsigned int i; unsigned int i;
uint64_t ib1base, ib2base;
unsigned int ib1size, ib2size;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
@ -806,6 +854,16 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
setup_fault_process(device, snapshot, setup_fault_process(device, snapshot,
context ? context->proc_priv : NULL); context ? context->proc_priv : NULL);
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
ADRENO_REG_CP_IB1_BASE_HI, &snapshot->ib1base);
adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ, &snapshot->ib1size);
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB2_BASE,
ADRENO_REG_CP_IB2_BASE_HI, &snapshot->ib2base);
adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ, &snapshot->ib2size);
snapshot->ib1dumped = false;
snapshot->ib2dumped = false;
adreno_snapshot_ringbuffer(device, snapshot, adreno_dev->cur_rb); adreno_snapshot_ringbuffer(device, snapshot, adreno_dev->cur_rb);
/* Dump the prev ringbuffer */ /* Dump the prev ringbuffer */
@ -818,13 +876,6 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
adreno_snapshot_ringbuffer(device, snapshot, adreno_snapshot_ringbuffer(device, snapshot,
adreno_dev->next_rb); adreno_dev->next_rb);
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB1_BASE,
ADRENO_REG_CP_IB1_BASE_HI, &ib1base);
adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ, &ib1size);
adreno_readreg64(adreno_dev, ADRENO_REG_CP_IB2_BASE,
ADRENO_REG_CP_IB2_BASE_HI, &ib2base);
adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ, &ib2size);
/* Add GPU specific sections - registers mainly, but other stuff too */ /* Add GPU specific sections - registers mainly, but other stuff too */
if (gpudev->snapshot) if (gpudev->snapshot)
gpudev->snapshot(adreno_dev, snapshot); gpudev->snapshot(adreno_dev, snapshot);
@ -858,13 +909,13 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* figure how often this really happens. * figure how often this really happens.
*/ */
if (!find_object(SNAPSHOT_OBJ_TYPE_IB, ib1base, if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib1base,
snapshot->process) && ib1size) { snapshot->process) && snapshot->ib1size) {
push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process, push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process,
ib1base, ib1size); snapshot->ib1base, snapshot->ib1size);
KGSL_CORE_ERR( KGSL_CORE_ERR(
"CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n", "CP_IB1_BASE not found in the ringbuffer.Dumping %x dwords of the buffer.\n",
ib1size); snapshot->ib1size);
} }
/* /*
@ -875,10 +926,10 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* correct size. * correct size.
*/ */
if (!find_object(SNAPSHOT_OBJ_TYPE_IB, ib2base, if (-ENOENT == find_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->ib2base,
snapshot->process) && ib2size) { snapshot->process)) {
push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process, push_object(SNAPSHOT_OBJ_TYPE_IB, snapshot->process,
ib2base, ib2size); snapshot->ib2base, snapshot->ib2size);
} }
/* /*
@ -886,8 +937,15 @@ void adreno_snapshot(struct kgsl_device *device, struct kgsl_snapshot *snapshot,
* are parsed, more objects might be found, and objbufptr will increase * are parsed, more objects might be found, and objbufptr will increase
*/ */
for (i = 0; i < objbufptr; i++) for (i = 0; i < objbufptr; i++)
dump_object(device, i, snapshot, ib1base, ib1size, dump_object(device, i, snapshot);
ib2base, ib2size);
/*
* Incase snapshot static blob is running out of memory, Add Active IB1
* and IB2 entries to obj_list so that active ib's can be dumped to
* snapshot dynamic blob.
*/
if (!snapshot->ib1dumped || !snapshot->ib2dumped)
kgsl_snapshot_add_active_ib_obj_list(device, snapshot);
if (ib_max_objs) if (ib_max_objs)
KGSL_CORE_ERR("Max objects found in IB\n"); KGSL_CORE_ERR("Max objects found in IB\n");

View file

@ -422,6 +422,12 @@ struct kgsl_device_private {
/** /**
* struct kgsl_snapshot - details for a specific snapshot instance * struct kgsl_snapshot - details for a specific snapshot instance
* @ib1base: Active IB1 base address at the time of fault
* @ib2base: Active IB2 base address at the time of fault
* @ib1size: Number of DWORDS pending in IB1 at the time of fault
* @ib2size: Number of DWORDS pending in IB2 at the time of fault
* @ib1dumped: Active IB1 dump status to sansphot binary
* @ib2dumped: Active IB2 dump status to sansphot binary
* @start: Pointer to the start of the static snapshot region * @start: Pointer to the start of the static snapshot region
* @size: Size of the current snapshot instance * @size: Size of the current snapshot instance
* @ptr: Pointer to the next block of memory to write to during snapshotting * @ptr: Pointer to the next block of memory to write to during snapshotting
@ -437,6 +443,12 @@ struct kgsl_device_private {
* @sysfs_read: An atomic for concurrent snapshot reads via syfs. * @sysfs_read: An atomic for concurrent snapshot reads via syfs.
*/ */
struct kgsl_snapshot { struct kgsl_snapshot {
uint64_t ib1base;
uint64_t ib2base;
unsigned int ib1size;
unsigned int ib2size;
bool ib1dumped;
bool ib2dumped;
u8 *start; u8 *start;
size_t size; size_t size;
u8 *ptr; u8 *ptr;

View file

@ -100,8 +100,8 @@ static u8 *_ctxtptr;
static int snapshot_context_info(int id, void *ptr, void *data) static int snapshot_context_info(int id, void *ptr, void *data)
{ {
struct kgsl_snapshot_linux_context *header = struct kgsl_snapshot_linux_context_v2 *header =
(struct kgsl_snapshot_linux_context *)_ctxtptr; (struct kgsl_snapshot_linux_context_v2 *)_ctxtptr;
struct kgsl_context *context = ptr; struct kgsl_context *context = ptr;
struct kgsl_device *device; struct kgsl_device *device;
@ -115,10 +115,12 @@ static int snapshot_context_info(int id, void *ptr, void *data)
kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_QUEUED, kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_QUEUED,
&header->timestamp_queued); &header->timestamp_queued);
kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_CONSUMED,
&header->timestamp_consumed);
kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED, kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED,
&header->timestamp_retired); &header->timestamp_retired);
_ctxtptr += sizeof(struct kgsl_snapshot_linux_context); _ctxtptr += sizeof(struct kgsl_snapshot_linux_context_v2);
return 0; return 0;
} }
@ -127,11 +129,11 @@ static int snapshot_context_info(int id, void *ptr, void *data)
static size_t snapshot_os(struct kgsl_device *device, static size_t snapshot_os(struct kgsl_device *device,
u8 *buf, size_t remain, void *priv) u8 *buf, size_t remain, void *priv)
{ {
struct kgsl_snapshot_linux *header = (struct kgsl_snapshot_linux *)buf; struct kgsl_snapshot_linux_v2 *header =
(struct kgsl_snapshot_linux_v2 *)buf;
struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int ctxtcount = 0; int ctxtcount = 0;
size_t size = sizeof(*header); size_t size = sizeof(*header);
u64 temp_ptbase;
struct kgsl_context *context; struct kgsl_context *context;
/* Figure out how many active contexts there are - these will /* Figure out how many active contexts there are - these will
@ -141,7 +143,7 @@ static size_t snapshot_os(struct kgsl_device *device,
idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount); idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
read_unlock(&device->context_lock); read_unlock(&device->context_lock);
size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context); size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context_v2);
/* Make sure there is enough room for the data */ /* Make sure there is enough room for the data */
if (remain < size) { if (remain < size) {
@ -151,9 +153,7 @@ static size_t snapshot_os(struct kgsl_device *device,
memset(header, 0, sizeof(*header)); memset(header, 0, sizeof(*header));
header->osid = KGSL_SNAPSHOT_OS_LINUX; header->osid = KGSL_SNAPSHOT_OS_LINUX_V3;
header->state = SNAPSHOT_STATE_HUNG;
/* Get the kernel build information */ /* Get the kernel build information */
strlcpy(header->release, utsname()->release, sizeof(header->release)); strlcpy(header->release, utsname()->release, sizeof(header->release));
@ -178,9 +178,8 @@ static size_t snapshot_os(struct kgsl_device *device,
context = kgsl_context_get(device, header->current_context); context = kgsl_context_get(device, header->current_context);
/* Get the current PT base */ /* Get the current PT base */
temp_ptbase = kgsl_mmu_get_current_ttbr0(&device->mmu); header->ptbase = kgsl_mmu_get_current_ttbr0(&device->mmu);
/* Truncate to 32 bits in case LPAE is used */
header->ptbase = (__u32)temp_ptbase;
/* And the PID for the task leader */ /* And the PID for the task leader */
if (context) { if (context) {
header->pid = context->tid; header->pid = context->tid;
@ -982,7 +981,8 @@ int kgsl_snapshot_add_ib_obj_list(struct kgsl_snapshot *snapshot,
return 0; return 0;
} }
static size_t _mempool_add_object(u8 *data, struct kgsl_snapshot_object *obj) static size_t _mempool_add_object(struct kgsl_snapshot *snapshot, u8 *data,
struct kgsl_snapshot_object *obj)
{ {
struct kgsl_snapshot_section_header *section = struct kgsl_snapshot_section_header *section =
(struct kgsl_snapshot_section_header *)data; (struct kgsl_snapshot_section_header *)data;
@ -1008,6 +1008,14 @@ static size_t _mempool_add_object(u8 *data, struct kgsl_snapshot_object *obj)
kgsl_mmu_pagetable_get_ttbr0(obj->entry->priv->pagetable); kgsl_mmu_pagetable_get_ttbr0(obj->entry->priv->pagetable);
header->type = obj->type; header->type = obj->type;
if (kgsl_addr_range_overlap(obj->gpuaddr, obj->size,
snapshot->ib1base, snapshot->ib1size))
snapshot->ib1dumped = true;
if (kgsl_addr_range_overlap(obj->gpuaddr, obj->size,
snapshot->ib2base, snapshot->ib2size))
snapshot->ib2dumped = true;
memcpy(dest, obj->entry->memdesc.hostptr + obj->offset, size); memcpy(dest, obj->entry->memdesc.hostptr + obj->offset, size);
kgsl_memdesc_unmap(&obj->entry->memdesc); kgsl_memdesc_unmap(&obj->entry->memdesc);
@ -1049,7 +1057,7 @@ void kgsl_snapshot_save_frozen_objs(struct work_struct *work)
/* even if vmalloc fails, make sure we clean up the obj_list */ /* even if vmalloc fails, make sure we clean up the obj_list */
list_for_each_entry_safe(obj, tmp, &snapshot->obj_list, node) { list_for_each_entry_safe(obj, tmp, &snapshot->obj_list, node) {
if (snapshot->mempool) { if (snapshot->mempool) {
size_t ret = _mempool_add_object(ptr, obj); size_t ret = _mempool_add_object(snapshot, ptr, obj);
ptr += ret; ptr += ret;
snapshot->mempool_size += ret; snapshot->mempool_size += ret;
} }
@ -1064,6 +1072,13 @@ done:
kgsl_process_private_put(snapshot->process); kgsl_process_private_put(snapshot->process);
snapshot->process = NULL; snapshot->process = NULL;
if (snapshot->ib1base && !snapshot->ib1dumped)
pr_warn("kgsl: snapshot: Active IB1:%016llx not dumped\n",
snapshot->ib1base);
else if (snapshot->ib2base && !snapshot->ib2dumped)
pr_warn("kgsl: snapshot: Active IB2:%016llx not dumped\n",
snapshot->ib2base);
complete_all(&snapshot->dump_gate); complete_all(&snapshot->dump_gate);
return; return;
} }

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -63,12 +63,9 @@ struct kgsl_snapshot_section_header {
/* OS sub-section header */ /* OS sub-section header */
#define KGSL_SNAPSHOT_OS_LINUX 0x0001 #define KGSL_SNAPSHOT_OS_LINUX 0x0001
#define KGSL_SNAPSHOT_OS_LINUX_V3 0x00000202
/* Linux OS specific information */ /* Linux OS specific information */
#define SNAPSHOT_STATE_HUNG 0
#define SNAPSHOT_STATE_RUNNING 1
struct kgsl_snapshot_linux { struct kgsl_snapshot_linux {
int osid; /* subsection OS identifier */ int osid; /* subsection OS identifier */
int state; /* 1 if the thread is running, 0 for hung */ int state; /* 1 if the thread is running, 0 for hung */
@ -87,6 +84,23 @@ struct kgsl_snapshot_linux {
unsigned char comm[16]; /* Name of the process that owns the PT */ unsigned char comm[16]; /* Name of the process that owns the PT */
} __packed; } __packed;
struct kgsl_snapshot_linux_v2 {
int osid; /* subsection OS identifier */
__u32 seconds; /* Unix timestamp for the snapshot */
__u32 power_flags; /* Current power flags */
__u32 power_level; /* Current power level */
__u32 power_interval_timeout; /* Power interval timeout */
__u32 grpclk; /* Current GP clock value */
__u32 busclk; /* Current busclk value */
__u64 ptbase; /* Current ptbase */
__u32 pid; /* PID of the process that owns the PT */
__u32 current_context; /* ID of the current context */
__u32 ctxtcount; /* Number of contexts appended to section */
unsigned char release[32]; /* kernel release */
unsigned char version[32]; /* kernel version */
unsigned char comm[16]; /* Name of the process that owns the PT */
} __packed;
/* /*
* This structure contains a record of an active context. * This structure contains a record of an active context.
* These are appended one after another in the OS section below * These are appended one after another in the OS section below
@ -99,6 +113,12 @@ struct kgsl_snapshot_linux_context {
__u32 timestamp_retired; /* The last timestamp retired by HW */ __u32 timestamp_retired; /* The last timestamp retired by HW */
}; };
struct kgsl_snapshot_linux_context_v2 {
__u32 id; /* The context ID */
__u32 timestamp_queued; /* The last queued timestamp */
__u32 timestamp_consumed; /* The last timestamp consumed by HW */
__u32 timestamp_retired; /* The last timestamp retired by HW */
};
/* Ringbuffer sub-section header */ /* Ringbuffer sub-section header */
struct kgsl_snapshot_rb { struct kgsl_snapshot_rb {
int start; /* dword at the start of the dump */ int start; /* dword at the start of the dump */