blob: a5aa42f2452064e78fdc8b785c6aa8a76c8d4e16 [file] [log] [blame]
Duy Truonge833aca2013-02-12 13:35:08 -08001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jordan Crouse156cfbc2012-01-24 09:32:04 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Steve Mucklef132c6c2012-06-06 18:30:57 -070013#include <linux/export.h>
Jordan Crouse156cfbc2012-01-24 09:32:04 -070014#include <linux/time.h>
15#include <linux/sysfs.h>
16#include <linux/utsname.h>
17#include <linux/sched.h>
18#include <linux/idr.h>
19
20#include "kgsl.h"
21#include "kgsl_log.h"
22#include "kgsl_device.h"
23#include "kgsl_sharedmem.h"
24#include "kgsl_snapshot.h"
25
Jordan Crouse9610b6b2012-03-16 14:53:42 -060026/* Placeholder for the list of memory objects frozen after a hang */
27
28struct kgsl_snapshot_object {
29 unsigned int gpuaddr;
30 unsigned int ptbase;
31 unsigned int size;
Jordan Crouse233b2092012-04-18 09:31:09 -060032 unsigned int offset;
Jordan Crouse9610b6b2012-03-16 14:53:42 -060033 int type;
34 struct kgsl_mem_entry *entry;
35 struct list_head node;
36};
37
Jordan Crouse7c325702012-06-20 08:22:16 -060038struct snapshot_obj_itr {
39 void *buf; /* Buffer pointer to write to */
40 int pos; /* Current position in the sequence */
41 loff_t offset; /* file offset to start writing from */
42 size_t remain; /* Bytes remaining in buffer */
43 size_t write; /* Bytes written so far */
44};
45
46static void obj_itr_init(struct snapshot_obj_itr *itr, void *buf,
47 loff_t offset, size_t remain)
48{
49 itr->buf = buf;
50 itr->offset = offset;
51 itr->remain = remain;
52 itr->pos = 0;
53 itr->write = 0;
54}
55
56static int obj_itr_out(struct snapshot_obj_itr *itr, void *src, int size)
57{
58 if (itr->remain == 0)
59 return 0;
60
61 if ((itr->pos + size) <= itr->offset)
62 goto done;
63
64 /* Handle the case that offset is in the middle of the buffer */
65
66 if (itr->offset > itr->pos) {
67 src += (itr->offset - itr->pos);
68 size -= (itr->offset - itr->pos);
69
70 /* Advance pos to the offset start */
71 itr->pos = itr->offset;
72 }
73
74 if (size > itr->remain)
75 size = itr->remain;
76
77 memcpy(itr->buf, src, size);
78
79 itr->buf += size;
80 itr->write += size;
81 itr->remain -= size;
82
83done:
84 itr->pos += size;
85 return size;
86}
87
Jordan Crouse156cfbc2012-01-24 09:32:04 -070088/* idr_for_each function to count the number of contexts */
89
90static int snapshot_context_count(int id, void *ptr, void *data)
91{
92 int *count = data;
93 *count = *count + 1;
94
95 return 0;
96}
97
98/*
99 * To simplify the iterator loop use a global pointer instead of trying
100 * to pass around double star references to the snapshot data
101 */
102
103static void *_ctxtptr;
104
105static int snapshot_context_info(int id, void *ptr, void *data)
106{
107 struct kgsl_snapshot_linux_context *header = _ctxtptr;
108 struct kgsl_context *context = ptr;
109 struct kgsl_device *device = context->dev_priv->device;
110
111 header->id = id;
112
113 /* Future-proof for per-context timestamps - for now, just
114 * return the global timestamp for all contexts
115 */
116
Jeremy Gebben731dac52012-05-10 11:13:42 -0600117 header->timestamp_queued = kgsl_readtimestamp(device, context,
118 KGSL_TIMESTAMP_QUEUED);
119 header->timestamp_retired = kgsl_readtimestamp(device, context,
120 KGSL_TIMESTAMP_RETIRED);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700121
122 _ctxtptr += sizeof(struct kgsl_snapshot_linux_context);
123
124 return 0;
125}
126
127/* Snapshot the Linux specific information */
128static int snapshot_os(struct kgsl_device *device,
129 void *snapshot, int remain, void *priv)
130{
131 struct kgsl_snapshot_linux *header = snapshot;
132 struct kgsl_pwrctrl *pwr = &device->pwrctrl;
133 struct task_struct *task;
134 pid_t pid;
135 int hang = (int) priv;
136 int ctxtcount = 0;
137 int size = sizeof(*header);
138
139 /* Figure out how many active contexts there are - these will
140 * be appended on the end of the structure */
141
142 idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
143
144 size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
145
146 /* Make sure there is enough room for the data */
147 if (remain < size) {
148 SNAPSHOT_ERR_NOMEM(device, "OS");
149 return 0;
150 }
151
152 memset(header, 0, sizeof(*header));
153
154 header->osid = KGSL_SNAPSHOT_OS_LINUX;
155
156 header->state = hang ? SNAPSHOT_STATE_HUNG : SNAPSHOT_STATE_RUNNING;
157
158 /* Get the kernel build information */
159 strlcpy(header->release, utsname()->release, sizeof(header->release));
160 strlcpy(header->version, utsname()->version, sizeof(header->version));
161
162 /* Get the Unix time for the timestamp */
163 header->seconds = get_seconds();
164
165 /* Remember the power information */
166 header->power_flags = pwr->power_flags;
167 header->power_level = pwr->active_pwrlevel;
168 header->power_interval_timeout = pwr->interval_timeout;
169 header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]);
170 header->busclk = kgsl_get_clkrate(pwr->ebi1_clk);
171
172 /* Future proof for per-context timestamps */
173 header->current_context = -1;
174
175 /* Get the current PT base */
Shubhraprakash Das79447952012-04-26 18:12:23 -0600176 header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700177 /* And the PID for the task leader */
Shubhraprakash Das3cf33be2012-08-16 22:42:55 -0700178 pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
179 header->ptbase);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700180
181 task = find_task_by_vpid(pid);
182
183 if (task)
184 get_task_comm(header->comm, task);
185
186 header->ctxtcount = ctxtcount;
187
188 /* append information for each context */
189 _ctxtptr = snapshot + sizeof(*header);
190 idr_for_each(&device->context_idr, snapshot_context_info, NULL);
191
192 /* Return the size of the data segment */
193 return size;
194}
195/*
196 * kgsl_snapshot_dump_indexed_regs - helper function to dump indexed registers
197 * @device - the device to dump registers from
198 * @snapshot - pointer to the start of the region of memory for the snapshot
199 * @remain - a pointer to the number of bytes remaining in the snapshot
200 * @priv - A pointer to the kgsl_snapshot_indexed_registers data
201 *
202 * Given a indexed register cmd/data pair and a count, dump each indexed
203 * register
204 */
205
Jordan Crouse0c2761a2012-02-01 22:11:12 -0700206static int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700207 void *snapshot, int remain, void *priv)
208{
209 struct kgsl_snapshot_indexed_registers *iregs = priv;
210 struct kgsl_snapshot_indexed_regs *header = snapshot;
211 unsigned int *data = snapshot + sizeof(*header);
212 int i;
213
214 if (remain < (iregs->count * 4) + sizeof(*header)) {
215 SNAPSHOT_ERR_NOMEM(device, "INDEXED REGS");
216 return 0;
217 }
218
219 header->index_reg = iregs->index;
220 header->data_reg = iregs->data;
221 header->count = iregs->count;
222 header->start = iregs->start;
223
224 for (i = 0; i < iregs->count; i++) {
225 kgsl_regwrite(device, iregs->index, iregs->start + i);
226 kgsl_regread(device, iregs->data, &data[i]);
227 }
228
229 return (iregs->count * 4) + sizeof(*header);
230}
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700231
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600232#define GPU_OBJ_HEADER_SZ \
233 (sizeof(struct kgsl_snapshot_section_header) + \
234 sizeof(struct kgsl_snapshot_gpu_object))
235
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600236static int kgsl_snapshot_dump_object(struct kgsl_device *device,
Jordan Crouse7c325702012-06-20 08:22:16 -0600237 struct kgsl_snapshot_object *obj, struct snapshot_obj_itr *itr)
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600238{
Jordan Crouse7c325702012-06-20 08:22:16 -0600239 struct kgsl_snapshot_section_header sect;
240 struct kgsl_snapshot_gpu_object header;
241 int ret;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600242
Jordan Crouse7c325702012-06-20 08:22:16 -0600243 sect.magic = SNAPSHOT_SECTION_MAGIC;
244 sect.id = KGSL_SNAPSHOT_SECTION_GPU_OBJECT;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600245
Jordan Crouse7c325702012-06-20 08:22:16 -0600246 /*
247 * Header size is in dwords, object size is in bytes -
248 * round up if the object size isn't dword aligned
249 */
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600250
Jordan Crouse7c325702012-06-20 08:22:16 -0600251 sect.size = GPU_OBJ_HEADER_SZ + ALIGN(obj->size, 4);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600252
Jordan Crouse7c325702012-06-20 08:22:16 -0600253 ret = obj_itr_out(itr, &sect, sizeof(sect));
254 if (ret == 0)
255 return 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600256
Jordan Crouse7c325702012-06-20 08:22:16 -0600257 header.size = ALIGN(obj->size, 4) >> 2;
258 header.gpuaddr = obj->gpuaddr;
259 header.ptbase = obj->ptbase;
260 header.type = obj->type;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600261
Jordan Crouse7c325702012-06-20 08:22:16 -0600262 ret = obj_itr_out(itr, &header, sizeof(header));
263 if (ret == 0)
264 return 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600265
Jordan Crouse7c325702012-06-20 08:22:16 -0600266 ret = obj_itr_out(itr, obj->entry->memdesc.hostptr + obj->offset,
267 obj->size);
268 if (ret == 0)
269 return 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600270
Jordan Crouse7c325702012-06-20 08:22:16 -0600271 /* Pad the end to a dword boundary if we need to */
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600272
Jordan Crouse7c325702012-06-20 08:22:16 -0600273 if (obj->size % 4) {
274 unsigned int dummy = 0;
275 ret = obj_itr_out(itr, &dummy, obj->size % 4);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600276 }
277
278 return ret;
279}
280
281static void kgsl_snapshot_put_object(struct kgsl_device *device,
282 struct kgsl_snapshot_object *obj)
283{
284 list_del(&obj->node);
285
286 obj->entry->flags &= ~KGSL_MEM_ENTRY_FROZEN;
287 kgsl_mem_entry_put(obj->entry);
288
289 kfree(obj);
290}
291
Jordan Crouse21aaadf2012-09-11 16:38:15 -0600292/* ksgl_snapshot_have_object - Return 1 if the object has been processed
293 *@device - the device that is being snapshotted
294 * @ptbase - the pagetable base of the object to freeze
295 * @gpuaddr - The gpu address of the object to freeze
296 * @size - the size of the object (may not always be the size of the region)
297 *
298 * Return 1 if the object is already in the list - this can save us from
299 * having to parse the sme thing over again.
300*/
301int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase,
302 unsigned int gpuaddr, unsigned int size)
303{
304 struct kgsl_snapshot_object *obj;
305
306 list_for_each_entry(obj, &device->snapshot_obj_list, node) {
307 if (obj->ptbase != ptbase)
308 continue;
309
310 if ((gpuaddr >= obj->gpuaddr) &&
311 ((gpuaddr + size) <= (obj->gpuaddr + obj->size)))
312 return 1;
313 }
314
315 return 0;
316}
317
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600318/* kgsl_snapshot_get_object - Mark a GPU buffer to be frozen
319 * @device - the device that is being snapshotted
320 * @ptbase - the pagetable base of the object to freeze
321 * @gpuaddr - The gpu address of the object to freeze
322 * @size - the size of the object (may not always be the size of the region)
323 * @type - the type of object being saved (shader, vbo, etc)
324 *
325 * Mark and freeze a GPU buffer object. This will prevent it from being
326 * freed until it can be copied out as part of the snapshot dump. Returns the
327 * size of the object being frozen
328 */
329
330int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase,
331 unsigned int gpuaddr, unsigned int size, unsigned int type)
332{
333 struct kgsl_mem_entry *entry;
334 struct kgsl_snapshot_object *obj;
335 int offset;
336
Shubhraprakash Das3cf33be2012-08-16 22:42:55 -0700337 entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, size);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600338
339 if (entry == NULL) {
340 KGSL_DRV_ERR(device, "Unable to find GPU buffer %8.8X\n",
341 gpuaddr);
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700342 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600343 }
344
345 /* We can't freeze external memory, because we don't own it */
346 if (entry->memtype != KGSL_MEM_ENTRY_KERNEL) {
347 KGSL_DRV_ERR(device,
348 "Only internal GPU buffers can be frozen\n");
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700349 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600350 }
351
352 /*
353 * size indicates the number of bytes in the region to save. This might
354 * not always be the entire size of the region because some buffers are
355 * sub-allocated from a larger region. However, if size 0 was passed
356 * thats a flag that the caller wants to capture the entire buffer
357 */
358
359 if (size == 0) {
360 size = entry->memdesc.size;
361 offset = 0;
362
363 /* Adjust the gpuaddr to the start of the object */
364 gpuaddr = entry->memdesc.gpuaddr;
365 } else {
366 offset = gpuaddr - entry->memdesc.gpuaddr;
367 }
368
369 if (size + offset > entry->memdesc.size) {
370 KGSL_DRV_ERR(device, "Invalid size for GPU buffer %8.8X\n",
371 gpuaddr);
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700372 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600373 }
374
375 /* If the buffer is already on the list, skip it */
376 list_for_each_entry(obj, &device->snapshot_obj_list, node) {
377 if (obj->gpuaddr == gpuaddr && obj->ptbase == ptbase) {
378 /* If the size is different, use the new size */
379 if (obj->size != size)
380 obj->size = size;
381
382 return 0;
383 }
384 }
385
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600386 if (kgsl_memdesc_map(&entry->memdesc) == NULL) {
387 KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n",
388 gpuaddr);
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700389 return -EINVAL;
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600390 }
391
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600392 obj = kzalloc(sizeof(*obj), GFP_KERNEL);
393
394 if (obj == NULL) {
395 KGSL_DRV_ERR(device, "Unable to allocate memory\n");
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700396 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600397 }
398
399 /* Ref count the mem entry */
400 kgsl_mem_entry_get(entry);
401
402 obj->type = type;
403 obj->entry = entry;
404 obj->gpuaddr = gpuaddr;
405 obj->ptbase = ptbase;
406 obj->size = size;
Jordan Crouse233b2092012-04-18 09:31:09 -0600407 obj->offset = offset;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600408
409 list_add(&obj->node, &device->snapshot_obj_list);
410
411 /*
412 * Return the size of the entire mem entry that was frozen - this gets
413 * used for tracking how much memory is frozen for a hang. Also, mark
414 * the memory entry as frozen. If the entry was already marked as
415 * frozen, then another buffer already got to it. In that case, return
416 * 0 so it doesn't get counted twice
417 */
418
419 if (entry->flags & KGSL_MEM_ENTRY_FROZEN)
420 return 0;
421
422 entry->flags |= KGSL_MEM_ENTRY_FROZEN;
423
424 return entry->memdesc.size;
425}
426EXPORT_SYMBOL(kgsl_snapshot_get_object);
427
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700428/*
429 * kgsl_snapshot_dump_regs - helper function to dump device registers
430 * @device - the device to dump registers from
431 * @snapshot - pointer to the start of the region of memory for the snapshot
432 * @remain - a pointer to the number of bytes remaining in the snapshot
433 * @priv - A pointer to the kgsl_snapshot_registers data
434 *
435 * Given an array of register ranges pairs (start,end [inclusive]), dump the
436 * registers into a snapshot register section. The snapshot region stores a
437 * part of dwords for each register - the word address of the register, and
438 * the value.
439 */
440int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
441 int remain, void *priv)
442{
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600443 struct kgsl_snapshot_registers_list *list = priv;
444
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700445 struct kgsl_snapshot_regs *header = snapshot;
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600446 struct kgsl_snapshot_registers *regs;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700447 unsigned int *data = snapshot + sizeof(*header);
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600448 int count = 0, i, j, k;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700449
450 /* Figure out how many registers we are going to dump */
451
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600452 for (i = 0; i < list->count; i++) {
453 regs = &(list->registers[i]);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700454
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600455 for (j = 0; j < regs->count; j++) {
456 int start = regs->regs[j * 2];
457 int end = regs->regs[j * 2 + 1];
458
459 count += (end - start + 1);
460 }
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700461 }
462
463 if (remain < (count * 8) + sizeof(*header)) {
464 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
465 return 0;
466 }
467
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700468
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600469 for (i = 0; i < list->count; i++) {
470 regs = &(list->registers[i]);
471 for (j = 0; j < regs->count; j++) {
472 unsigned int start = regs->regs[j * 2];
473 unsigned int end = regs->regs[j * 2 + 1];
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700474
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600475 for (k = start; k <= end; k++) {
476 unsigned int val;
477
478 kgsl_regread(device, k, &val);
479 *data++ = k;
480 *data++ = val;
481 }
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700482 }
483 }
484
485 header->count = count;
486
487 /* Return the size of the section */
488 return (count * 8) + sizeof(*header);
489}
490EXPORT_SYMBOL(kgsl_snapshot_dump_regs);
491
Jordan Crouse0c2761a2012-02-01 22:11:12 -0700492void *kgsl_snapshot_indexed_registers(struct kgsl_device *device,
493 void *snapshot, int *remain,
494 unsigned int index, unsigned int data, unsigned int start,
495 unsigned int count)
496{
497 struct kgsl_snapshot_indexed_registers iregs;
498 iregs.index = index;
499 iregs.data = data;
500 iregs.start = start;
501 iregs.count = count;
502
503 return kgsl_snapshot_add_section(device,
504 KGSL_SNAPSHOT_SECTION_INDEXED_REGS, snapshot,
505 remain, kgsl_snapshot_dump_indexed_regs, &iregs);
506}
507EXPORT_SYMBOL(kgsl_snapshot_indexed_registers);
508
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700509/*
510 * kgsl_snapshot - construct a device snapshot
511 * @device - device to snapshot
512 * @hang - set to 1 if the snapshot was triggered following a hnag
513 * Given a device, construct a binary snapshot dump of the current device state
514 * and store it in the device snapshot memory.
515 */
516int kgsl_device_snapshot(struct kgsl_device *device, int hang)
517{
518 struct kgsl_snapshot_header *header = device->snapshot;
519 int remain = device->snapshot_maxsize - sizeof(*header);
520 void *snapshot;
Jordan Crouseaeebcc02013-02-14 14:11:44 -0700521 struct timespec boot;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700522
523 /*
524 * The first hang is always the one we are interested in. To
525 * avoid a subsequent hang blowing away the first, the snapshot
526 * is frozen until it is dumped via sysfs.
527 *
528 * Note that triggered snapshots are always taken regardless
529 * of the state and never frozen.
530 */
531
532 if (hang && device->snapshot_frozen == 1)
533 return 0;
534
535 if (device->snapshot == NULL) {
536 KGSL_DRV_ERR(device,
537 "snapshot: No snapshot memory available\n");
538 return -ENOMEM;
539 }
540
541 if (remain < sizeof(*header)) {
542 KGSL_DRV_ERR(device,
543 "snapshot: Not enough memory for the header\n");
544 return -ENOMEM;
545 }
546
547 header->magic = SNAPSHOT_MAGIC;
548
Jordan Crouse70829d32012-06-20 08:22:17 -0600549 header->gpuid = kgsl_gpuid(device, &header->chipid);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700550
551 /* Get a pointer to the first section (right after the header) */
552 snapshot = ((void *) device->snapshot) + sizeof(*header);
553
554 /* Build the Linux specific header */
555 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
556 snapshot, &remain, snapshot_os, (void *) hang);
557
558 /* Get the device specific sections */
559 if (device->ftbl->snapshot)
560 snapshot = device->ftbl->snapshot(device, snapshot, &remain,
561 hang);
562
Jordan Crouseaeebcc02013-02-14 14:11:44 -0700563 /*
564 * The timestamp is the seconds since boot so it is easier to match to
565 * the kernel log
566 */
567
568 getboottime(&boot);
569 device->snapshot_timestamp = get_seconds() - boot.tv_sec;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700570 device->snapshot_size = (int) (snapshot - device->snapshot);
571
572 /* Freeze the snapshot on a hang until it gets read */
573 device->snapshot_frozen = (hang) ? 1 : 0;
574
Tarun Karrad20d71a2013-01-25 15:38:57 -0800575 /* log buffer info to aid in ramdump fault tolerance */
Tarun Karra45a50d62013-01-28 21:47:37 -0800576 KGSL_DRV_ERR(device, "snapshot created at pa %lx size %d\n",
577 __pa(device->snapshot), device->snapshot_size);
Jeremy Gebben90812c82012-03-08 12:46:01 -0700578 if (hang)
579 sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700580 return 0;
581}
582EXPORT_SYMBOL(kgsl_device_snapshot);
583
584/* An attribute for showing snapshot details */
585struct kgsl_snapshot_attribute {
586 struct attribute attr;
587 ssize_t (*show)(struct kgsl_device *device, char *buf);
588 ssize_t (*store)(struct kgsl_device *device, const char *buf,
589 size_t count);
590};
591
592#define to_snapshot_attr(a) \
593container_of(a, struct kgsl_snapshot_attribute, attr)
594
595#define kobj_to_device(a) \
596container_of(a, struct kgsl_device, snapshot_kobj)
597
598/* Dump the sysfs binary data to the user */
599static ssize_t snapshot_show(struct file *filep, struct kobject *kobj,
600 struct bin_attribute *attr, char *buf, loff_t off,
601 size_t count)
602{
603 struct kgsl_device *device = kobj_to_device(kobj);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600604 struct kgsl_snapshot_object *obj, *tmp;
Jordan Crouse7c325702012-06-20 08:22:16 -0600605 struct kgsl_snapshot_section_header head;
606 struct snapshot_obj_itr itr;
607 int ret;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700608
609 if (device == NULL)
610 return 0;
611
612 /* Return nothing if we haven't taken a snapshot yet */
613 if (device->snapshot_timestamp == 0)
614 return 0;
615
616 /* Get the mutex to keep things from changing while we are dumping */
617 mutex_lock(&device->mutex);
618
Jordan Crouse7c325702012-06-20 08:22:16 -0600619 obj_itr_init(&itr, buf, off, count);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600620
Jordan Crouse7c325702012-06-20 08:22:16 -0600621 ret = obj_itr_out(&itr, device->snapshot, device->snapshot_size);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600622
Jordan Crouse7c325702012-06-20 08:22:16 -0600623 if (ret == 0)
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600624 goto done;
625
Jordan Crouse7c325702012-06-20 08:22:16 -0600626 list_for_each_entry(obj, &device->snapshot_obj_list, node)
627 kgsl_snapshot_dump_object(device, obj, &itr);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600628
Jordan Crouse7c325702012-06-20 08:22:16 -0600629 {
630 head.magic = SNAPSHOT_SECTION_MAGIC;
631 head.id = KGSL_SNAPSHOT_SECTION_END;
632 head.size = sizeof(head);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600633
Jordan Crouse7c325702012-06-20 08:22:16 -0600634 obj_itr_out(&itr, &head, sizeof(head));
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600635 }
636
Jordan Crouse7c325702012-06-20 08:22:16 -0600637 /*
638 * Make sure everything has been written out before destroying things.
639 * The best way to confirm this is to go all the way through without
640 * writing any bytes - so only release if we get this far and
641 * itr->write is 0
642 */
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600643
Jordan Crouse7c325702012-06-20 08:22:16 -0600644 if (itr.write == 0) {
645 list_for_each_entry_safe(obj, tmp, &device->snapshot_obj_list,
646 node)
647 kgsl_snapshot_put_object(device, obj);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600648
Jordan Crouse7c325702012-06-20 08:22:16 -0600649 if (device->snapshot_frozen)
650 KGSL_DRV_ERR(device, "Snapshot objects released\n");
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600651
Jordan Crouse7c325702012-06-20 08:22:16 -0600652 device->snapshot_frozen = 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600653 }
654
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600655done:
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700656 mutex_unlock(&device->mutex);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600657
Jordan Crouse7c325702012-06-20 08:22:16 -0600658 return itr.write;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700659}
660
661/* Show the timestamp of the last collected snapshot */
662static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
663{
Jordan Crouseaeebcc02013-02-14 14:11:44 -0700664 return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_timestamp);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700665}
666
667/* manually trigger a new snapshot to be collected */
668static ssize_t trigger_store(struct kgsl_device *device, const char *buf,
669 size_t count)
670{
671 if (device && count > 0) {
672 mutex_lock(&device->mutex);
673 kgsl_device_snapshot(device, 0);
674 mutex_unlock(&device->mutex);
675 }
676
677 return count;
678}
679
680static struct bin_attribute snapshot_attr = {
681 .attr.name = "dump",
682 .attr.mode = 0444,
683 .size = 0,
684 .read = snapshot_show
685};
686
687#define SNAPSHOT_ATTR(_name, _mode, _show, _store) \
688struct kgsl_snapshot_attribute attr_##_name = { \
689 .attr = { .name = __stringify(_name), .mode = _mode }, \
690 .show = _show, \
691 .store = _store, \
692}
693
694SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store);
695SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL);
696
697static void snapshot_sysfs_release(struct kobject *kobj)
698{
699}
700
701static ssize_t snapshot_sysfs_show(struct kobject *kobj,
702 struct attribute *attr, char *buf)
703{
704 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
705 struct kgsl_device *device = kobj_to_device(kobj);
706 ssize_t ret;
707
708 if (device && pattr->show)
709 ret = pattr->show(device, buf);
710 else
711 ret = -EIO;
712
713 return ret;
714}
715
716static ssize_t snapshot_sysfs_store(struct kobject *kobj,
717 struct attribute *attr, const char *buf, size_t count)
718{
719 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
720 struct kgsl_device *device = kobj_to_device(kobj);
721 ssize_t ret;
722
723 if (device && pattr->store)
724 ret = pattr->store(device, buf, count);
725 else
726 ret = -EIO;
727
728 return ret;
729}
730
731static const struct sysfs_ops snapshot_sysfs_ops = {
732 .show = snapshot_sysfs_show,
733 .store = snapshot_sysfs_store,
734};
735
736static struct kobj_type ktype_snapshot = {
737 .sysfs_ops = &snapshot_sysfs_ops,
738 .default_attrs = NULL,
739 .release = snapshot_sysfs_release,
740};
741
742/* kgsl_device_snapshot_init - Add resources for the device GPU snapshot
743 * @device - The device to initalize
744 *
745 * Allocate memory for a GPU snapshot for the specified device,
746 * and create the sysfs files to manage it
747 */
748
749int kgsl_device_snapshot_init(struct kgsl_device *device)
750{
751 int ret;
752
753 if (device->snapshot == NULL)
Jeremy Gebben9d15ae42012-02-29 16:50:27 -0700754 device->snapshot = kzalloc(KGSL_SNAPSHOT_MEMSIZE, GFP_KERNEL);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700755
756 if (device->snapshot == NULL)
757 return -ENOMEM;
758
759 device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE;
760 device->snapshot_timestamp = 0;
761
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600762 INIT_LIST_HEAD(&device->snapshot_obj_list);
763
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700764 ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
765 &device->dev->kobj, "snapshot");
766 if (ret)
767 goto done;
768
769 ret = sysfs_create_bin_file(&device->snapshot_kobj, &snapshot_attr);
770 if (ret)
771 goto done;
772
773 ret = sysfs_create_file(&device->snapshot_kobj, &attr_trigger.attr);
774 if (ret)
775 goto done;
776
777 ret = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr);
778
779done:
780 return ret;
781}
782EXPORT_SYMBOL(kgsl_device_snapshot_init);
783
784/* kgsl_device_snapshot_close - Take down snapshot memory for a device
785 * @device - Pointer to the kgsl_device
786 *
787 * Remove the sysfs files and free the memory allocated for the GPU
788 * snapshot
789 */
790
791void kgsl_device_snapshot_close(struct kgsl_device *device)
792{
793 sysfs_remove_bin_file(&device->snapshot_kobj, &snapshot_attr);
794 sysfs_remove_file(&device->snapshot_kobj, &attr_trigger.attr);
795 sysfs_remove_file(&device->snapshot_kobj, &attr_timestamp.attr);
796
797 kobject_put(&device->snapshot_kobj);
798
Jeremy Gebben9d15ae42012-02-29 16:50:27 -0700799 kfree(device->snapshot);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700800
801 device->snapshot = NULL;
802 device->snapshot_maxsize = 0;
803 device->snapshot_timestamp = 0;
804}
805EXPORT_SYMBOL(kgsl_device_snapshot_close);