blob: e20029453c45346da9067acc82d5eda363813031 [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
Jordan Crouse67db48d2013-05-28 17:04:17 -0600142 rcu_read_lock();
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700143 idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
Jordan Crouse67db48d2013-05-28 17:04:17 -0600144 rcu_read_unlock();
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700145
146 size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
147
148 /* Make sure there is enough room for the data */
149 if (remain < size) {
150 SNAPSHOT_ERR_NOMEM(device, "OS");
151 return 0;
152 }
153
154 memset(header, 0, sizeof(*header));
155
156 header->osid = KGSL_SNAPSHOT_OS_LINUX;
157
158 header->state = hang ? SNAPSHOT_STATE_HUNG : SNAPSHOT_STATE_RUNNING;
159
160 /* Get the kernel build information */
161 strlcpy(header->release, utsname()->release, sizeof(header->release));
162 strlcpy(header->version, utsname()->version, sizeof(header->version));
163
164 /* Get the Unix time for the timestamp */
165 header->seconds = get_seconds();
166
167 /* Remember the power information */
168 header->power_flags = pwr->power_flags;
169 header->power_level = pwr->active_pwrlevel;
170 header->power_interval_timeout = pwr->interval_timeout;
171 header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]);
172 header->busclk = kgsl_get_clkrate(pwr->ebi1_clk);
173
174 /* Future proof for per-context timestamps */
175 header->current_context = -1;
176
177 /* Get the current PT base */
Shubhraprakash Das79447952012-04-26 18:12:23 -0600178 header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700179 /* And the PID for the task leader */
Shubhraprakash Das3cf33be2012-08-16 22:42:55 -0700180 pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
181 header->ptbase);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700182
183 task = find_task_by_vpid(pid);
184
185 if (task)
186 get_task_comm(header->comm, task);
187
188 header->ctxtcount = ctxtcount;
189
190 /* append information for each context */
191 _ctxtptr = snapshot + sizeof(*header);
Jordan Crouse67db48d2013-05-28 17:04:17 -0600192 rcu_read_lock();
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700193 idr_for_each(&device->context_idr, snapshot_context_info, NULL);
Jordan Crouse67db48d2013-05-28 17:04:17 -0600194 rcu_read_unlock();
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700195 /* Return the size of the data segment */
196 return size;
197}
198/*
199 * kgsl_snapshot_dump_indexed_regs - helper function to dump indexed registers
200 * @device - the device to dump registers from
201 * @snapshot - pointer to the start of the region of memory for the snapshot
202 * @remain - a pointer to the number of bytes remaining in the snapshot
203 * @priv - A pointer to the kgsl_snapshot_indexed_registers data
204 *
205 * Given a indexed register cmd/data pair and a count, dump each indexed
206 * register
207 */
208
Jordan Crouse0c2761a2012-02-01 22:11:12 -0700209static int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700210 void *snapshot, int remain, void *priv)
211{
212 struct kgsl_snapshot_indexed_registers *iregs = priv;
213 struct kgsl_snapshot_indexed_regs *header = snapshot;
214 unsigned int *data = snapshot + sizeof(*header);
215 int i;
216
217 if (remain < (iregs->count * 4) + sizeof(*header)) {
218 SNAPSHOT_ERR_NOMEM(device, "INDEXED REGS");
219 return 0;
220 }
221
222 header->index_reg = iregs->index;
223 header->data_reg = iregs->data;
224 header->count = iregs->count;
225 header->start = iregs->start;
226
227 for (i = 0; i < iregs->count; i++) {
228 kgsl_regwrite(device, iregs->index, iregs->start + i);
229 kgsl_regread(device, iregs->data, &data[i]);
230 }
231
232 return (iregs->count * 4) + sizeof(*header);
233}
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700234
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600235#define GPU_OBJ_HEADER_SZ \
236 (sizeof(struct kgsl_snapshot_section_header) + \
237 sizeof(struct kgsl_snapshot_gpu_object))
238
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600239static int kgsl_snapshot_dump_object(struct kgsl_device *device,
Jordan Crouse7c325702012-06-20 08:22:16 -0600240 struct kgsl_snapshot_object *obj, struct snapshot_obj_itr *itr)
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600241{
Jordan Crouse7c325702012-06-20 08:22:16 -0600242 struct kgsl_snapshot_section_header sect;
243 struct kgsl_snapshot_gpu_object header;
244 int ret;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600245
Jordan Crouse7c325702012-06-20 08:22:16 -0600246 sect.magic = SNAPSHOT_SECTION_MAGIC;
247 sect.id = KGSL_SNAPSHOT_SECTION_GPU_OBJECT;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600248
Jordan Crouse7c325702012-06-20 08:22:16 -0600249 /*
250 * Header size is in dwords, object size is in bytes -
251 * round up if the object size isn't dword aligned
252 */
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600253
Jordan Crouse7c325702012-06-20 08:22:16 -0600254 sect.size = GPU_OBJ_HEADER_SZ + ALIGN(obj->size, 4);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600255
Jordan Crouse7c325702012-06-20 08:22:16 -0600256 ret = obj_itr_out(itr, &sect, sizeof(sect));
257 if (ret == 0)
258 return 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600259
Jordan Crouse7c325702012-06-20 08:22:16 -0600260 header.size = ALIGN(obj->size, 4) >> 2;
261 header.gpuaddr = obj->gpuaddr;
262 header.ptbase = obj->ptbase;
263 header.type = obj->type;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600264
Jordan Crouse7c325702012-06-20 08:22:16 -0600265 ret = obj_itr_out(itr, &header, sizeof(header));
266 if (ret == 0)
267 return 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600268
Jordan Crouse7c325702012-06-20 08:22:16 -0600269 ret = obj_itr_out(itr, obj->entry->memdesc.hostptr + obj->offset,
270 obj->size);
271 if (ret == 0)
272 return 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600273
Jordan Crouse7c325702012-06-20 08:22:16 -0600274 /* Pad the end to a dword boundary if we need to */
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600275
Jordan Crouse7c325702012-06-20 08:22:16 -0600276 if (obj->size % 4) {
277 unsigned int dummy = 0;
278 ret = obj_itr_out(itr, &dummy, obj->size % 4);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600279 }
280
281 return ret;
282}
283
284static void kgsl_snapshot_put_object(struct kgsl_device *device,
285 struct kgsl_snapshot_object *obj)
286{
287 list_del(&obj->node);
288
289 obj->entry->flags &= ~KGSL_MEM_ENTRY_FROZEN;
290 kgsl_mem_entry_put(obj->entry);
291
292 kfree(obj);
293}
294
Jordan Crouse21aaadf2012-09-11 16:38:15 -0600295/* ksgl_snapshot_have_object - Return 1 if the object has been processed
296 *@device - the device that is being snapshotted
297 * @ptbase - the pagetable base of the object to freeze
298 * @gpuaddr - The gpu address of the object to freeze
299 * @size - the size of the object (may not always be the size of the region)
300 *
301 * Return 1 if the object is already in the list - this can save us from
302 * having to parse the sme thing over again.
303*/
304int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase,
305 unsigned int gpuaddr, unsigned int size)
306{
307 struct kgsl_snapshot_object *obj;
308
309 list_for_each_entry(obj, &device->snapshot_obj_list, node) {
310 if (obj->ptbase != ptbase)
311 continue;
312
313 if ((gpuaddr >= obj->gpuaddr) &&
314 ((gpuaddr + size) <= (obj->gpuaddr + obj->size)))
315 return 1;
316 }
317
318 return 0;
319}
320
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600321/* kgsl_snapshot_get_object - Mark a GPU buffer to be frozen
322 * @device - the device that is being snapshotted
323 * @ptbase - the pagetable base of the object to freeze
324 * @gpuaddr - The gpu address of the object to freeze
325 * @size - the size of the object (may not always be the size of the region)
326 * @type - the type of object being saved (shader, vbo, etc)
327 *
328 * Mark and freeze a GPU buffer object. This will prevent it from being
329 * freed until it can be copied out as part of the snapshot dump. Returns the
330 * size of the object being frozen
331 */
332
333int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase,
334 unsigned int gpuaddr, unsigned int size, unsigned int type)
335{
336 struct kgsl_mem_entry *entry;
337 struct kgsl_snapshot_object *obj;
338 int offset;
339
Shubhraprakash Das3cf33be2012-08-16 22:42:55 -0700340 entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, size);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600341
342 if (entry == NULL) {
343 KGSL_DRV_ERR(device, "Unable to find GPU buffer %8.8X\n",
344 gpuaddr);
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700345 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600346 }
347
348 /* We can't freeze external memory, because we don't own it */
349 if (entry->memtype != KGSL_MEM_ENTRY_KERNEL) {
350 KGSL_DRV_ERR(device,
351 "Only internal GPU buffers can be frozen\n");
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700352 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600353 }
354
355 /*
356 * size indicates the number of bytes in the region to save. This might
357 * not always be the entire size of the region because some buffers are
358 * sub-allocated from a larger region. However, if size 0 was passed
359 * thats a flag that the caller wants to capture the entire buffer
360 */
361
362 if (size == 0) {
363 size = entry->memdesc.size;
364 offset = 0;
365
366 /* Adjust the gpuaddr to the start of the object */
367 gpuaddr = entry->memdesc.gpuaddr;
368 } else {
369 offset = gpuaddr - entry->memdesc.gpuaddr;
370 }
371
372 if (size + offset > entry->memdesc.size) {
373 KGSL_DRV_ERR(device, "Invalid size for GPU buffer %8.8X\n",
374 gpuaddr);
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700375 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600376 }
377
378 /* If the buffer is already on the list, skip it */
379 list_for_each_entry(obj, &device->snapshot_obj_list, node) {
380 if (obj->gpuaddr == gpuaddr && obj->ptbase == ptbase) {
381 /* If the size is different, use the new size */
382 if (obj->size != size)
383 obj->size = size;
384
385 return 0;
386 }
387 }
388
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600389 if (kgsl_memdesc_map(&entry->memdesc) == NULL) {
390 KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n",
391 gpuaddr);
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700392 return -EINVAL;
Jordan Crouse17d6d8b2012-04-18 09:31:09 -0600393 }
394
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600395 obj = kzalloc(sizeof(*obj), GFP_KERNEL);
396
397 if (obj == NULL) {
398 KGSL_DRV_ERR(device, "Unable to allocate memory\n");
Jordan Crouse2cf6ec92013-02-14 14:46:11 -0700399 return -EINVAL;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600400 }
401
402 /* Ref count the mem entry */
403 kgsl_mem_entry_get(entry);
404
405 obj->type = type;
406 obj->entry = entry;
407 obj->gpuaddr = gpuaddr;
408 obj->ptbase = ptbase;
409 obj->size = size;
Jordan Crouse233b2092012-04-18 09:31:09 -0600410 obj->offset = offset;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600411
412 list_add(&obj->node, &device->snapshot_obj_list);
413
414 /*
415 * Return the size of the entire mem entry that was frozen - this gets
416 * used for tracking how much memory is frozen for a hang. Also, mark
417 * the memory entry as frozen. If the entry was already marked as
418 * frozen, then another buffer already got to it. In that case, return
419 * 0 so it doesn't get counted twice
420 */
421
422 if (entry->flags & KGSL_MEM_ENTRY_FROZEN)
423 return 0;
424
425 entry->flags |= KGSL_MEM_ENTRY_FROZEN;
426
427 return entry->memdesc.size;
428}
429EXPORT_SYMBOL(kgsl_snapshot_get_object);
430
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700431/*
432 * kgsl_snapshot_dump_regs - helper function to dump device registers
433 * @device - the device to dump registers from
434 * @snapshot - pointer to the start of the region of memory for the snapshot
435 * @remain - a pointer to the number of bytes remaining in the snapshot
436 * @priv - A pointer to the kgsl_snapshot_registers data
437 *
438 * Given an array of register ranges pairs (start,end [inclusive]), dump the
439 * registers into a snapshot register section. The snapshot region stores a
440 * part of dwords for each register - the word address of the register, and
441 * the value.
442 */
443int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
444 int remain, void *priv)
445{
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600446 struct kgsl_snapshot_registers_list *list = priv;
447
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700448 struct kgsl_snapshot_regs *header = snapshot;
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600449 struct kgsl_snapshot_registers *regs;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700450 unsigned int *data = snapshot + sizeof(*header);
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600451 int count = 0, i, j, k;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700452
453 /* Figure out how many registers we are going to dump */
454
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600455 for (i = 0; i < list->count; i++) {
456 regs = &(list->registers[i]);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700457
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600458 for (j = 0; j < regs->count; j++) {
459 int start = regs->regs[j * 2];
460 int end = regs->regs[j * 2 + 1];
461
462 count += (end - start + 1);
463 }
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700464 }
465
466 if (remain < (count * 8) + sizeof(*header)) {
467 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
468 return 0;
469 }
470
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700471
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600472 for (i = 0; i < list->count; i++) {
473 regs = &(list->registers[i]);
474 for (j = 0; j < regs->count; j++) {
475 unsigned int start = regs->regs[j * 2];
476 unsigned int end = regs->regs[j * 2 + 1];
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700477
Jordan Crouseea4f8b82012-08-14 14:38:46 -0600478 for (k = start; k <= end; k++) {
479 unsigned int val;
480
481 kgsl_regread(device, k, &val);
482 *data++ = k;
483 *data++ = val;
484 }
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700485 }
486 }
487
488 header->count = count;
489
490 /* Return the size of the section */
491 return (count * 8) + sizeof(*header);
492}
493EXPORT_SYMBOL(kgsl_snapshot_dump_regs);
494
Jordan Crouse0c2761a2012-02-01 22:11:12 -0700495void *kgsl_snapshot_indexed_registers(struct kgsl_device *device,
496 void *snapshot, int *remain,
497 unsigned int index, unsigned int data, unsigned int start,
498 unsigned int count)
499{
500 struct kgsl_snapshot_indexed_registers iregs;
501 iregs.index = index;
502 iregs.data = data;
503 iregs.start = start;
504 iregs.count = count;
505
506 return kgsl_snapshot_add_section(device,
507 KGSL_SNAPSHOT_SECTION_INDEXED_REGS, snapshot,
508 remain, kgsl_snapshot_dump_indexed_regs, &iregs);
509}
510EXPORT_SYMBOL(kgsl_snapshot_indexed_registers);
511
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700512/*
513 * kgsl_snapshot - construct a device snapshot
514 * @device - device to snapshot
515 * @hang - set to 1 if the snapshot was triggered following a hnag
516 * Given a device, construct a binary snapshot dump of the current device state
517 * and store it in the device snapshot memory.
518 */
519int kgsl_device_snapshot(struct kgsl_device *device, int hang)
520{
521 struct kgsl_snapshot_header *header = device->snapshot;
522 int remain = device->snapshot_maxsize - sizeof(*header);
523 void *snapshot;
Jordan Crouseaeebcc02013-02-14 14:11:44 -0700524 struct timespec boot;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700525
526 /*
527 * The first hang is always the one we are interested in. To
528 * avoid a subsequent hang blowing away the first, the snapshot
529 * is frozen until it is dumped via sysfs.
530 *
531 * Note that triggered snapshots are always taken regardless
532 * of the state and never frozen.
533 */
534
535 if (hang && device->snapshot_frozen == 1)
536 return 0;
537
538 if (device->snapshot == NULL) {
539 KGSL_DRV_ERR(device,
540 "snapshot: No snapshot memory available\n");
541 return -ENOMEM;
542 }
543
544 if (remain < sizeof(*header)) {
545 KGSL_DRV_ERR(device,
546 "snapshot: Not enough memory for the header\n");
547 return -ENOMEM;
548 }
549
550 header->magic = SNAPSHOT_MAGIC;
551
Jordan Crouse70829d32012-06-20 08:22:17 -0600552 header->gpuid = kgsl_gpuid(device, &header->chipid);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700553
554 /* Get a pointer to the first section (right after the header) */
555 snapshot = ((void *) device->snapshot) + sizeof(*header);
556
557 /* Build the Linux specific header */
558 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
559 snapshot, &remain, snapshot_os, (void *) hang);
560
561 /* Get the device specific sections */
562 if (device->ftbl->snapshot)
563 snapshot = device->ftbl->snapshot(device, snapshot, &remain,
564 hang);
565
Jordan Crouseaeebcc02013-02-14 14:11:44 -0700566 /*
567 * The timestamp is the seconds since boot so it is easier to match to
568 * the kernel log
569 */
570
571 getboottime(&boot);
572 device->snapshot_timestamp = get_seconds() - boot.tv_sec;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700573 device->snapshot_size = (int) (snapshot - device->snapshot);
574
575 /* Freeze the snapshot on a hang until it gets read */
576 device->snapshot_frozen = (hang) ? 1 : 0;
577
Tarun Karrad20d71a2013-01-25 15:38:57 -0800578 /* log buffer info to aid in ramdump fault tolerance */
Tarun Karra45a50d62013-01-28 21:47:37 -0800579 KGSL_DRV_ERR(device, "snapshot created at pa %lx size %d\n",
580 __pa(device->snapshot), device->snapshot_size);
Jeremy Gebben90812c82012-03-08 12:46:01 -0700581 if (hang)
582 sysfs_notify(&device->snapshot_kobj, NULL, "timestamp");
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700583 return 0;
584}
585EXPORT_SYMBOL(kgsl_device_snapshot);
586
587/* An attribute for showing snapshot details */
588struct kgsl_snapshot_attribute {
589 struct attribute attr;
590 ssize_t (*show)(struct kgsl_device *device, char *buf);
591 ssize_t (*store)(struct kgsl_device *device, const char *buf,
592 size_t count);
593};
594
595#define to_snapshot_attr(a) \
596container_of(a, struct kgsl_snapshot_attribute, attr)
597
598#define kobj_to_device(a) \
599container_of(a, struct kgsl_device, snapshot_kobj)
600
601/* Dump the sysfs binary data to the user */
602static ssize_t snapshot_show(struct file *filep, struct kobject *kobj,
603 struct bin_attribute *attr, char *buf, loff_t off,
604 size_t count)
605{
606 struct kgsl_device *device = kobj_to_device(kobj);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600607 struct kgsl_snapshot_object *obj, *tmp;
Jordan Crouse7c325702012-06-20 08:22:16 -0600608 struct kgsl_snapshot_section_header head;
609 struct snapshot_obj_itr itr;
610 int ret;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700611
612 if (device == NULL)
613 return 0;
614
615 /* Return nothing if we haven't taken a snapshot yet */
616 if (device->snapshot_timestamp == 0)
617 return 0;
618
619 /* Get the mutex to keep things from changing while we are dumping */
620 mutex_lock(&device->mutex);
621
Jordan Crouse7c325702012-06-20 08:22:16 -0600622 obj_itr_init(&itr, buf, off, count);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600623
Jordan Crouse7c325702012-06-20 08:22:16 -0600624 ret = obj_itr_out(&itr, device->snapshot, device->snapshot_size);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600625
Jordan Crouse7c325702012-06-20 08:22:16 -0600626 if (ret == 0)
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600627 goto done;
628
Jordan Crouse7c325702012-06-20 08:22:16 -0600629 list_for_each_entry(obj, &device->snapshot_obj_list, node)
630 kgsl_snapshot_dump_object(device, obj, &itr);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600631
Jordan Crouse7c325702012-06-20 08:22:16 -0600632 {
633 head.magic = SNAPSHOT_SECTION_MAGIC;
634 head.id = KGSL_SNAPSHOT_SECTION_END;
635 head.size = sizeof(head);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600636
Jordan Crouse7c325702012-06-20 08:22:16 -0600637 obj_itr_out(&itr, &head, sizeof(head));
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600638 }
639
Jordan Crouse7c325702012-06-20 08:22:16 -0600640 /*
641 * Make sure everything has been written out before destroying things.
642 * The best way to confirm this is to go all the way through without
643 * writing any bytes - so only release if we get this far and
644 * itr->write is 0
645 */
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600646
Jordan Crouse7c325702012-06-20 08:22:16 -0600647 if (itr.write == 0) {
648 list_for_each_entry_safe(obj, tmp, &device->snapshot_obj_list,
649 node)
650 kgsl_snapshot_put_object(device, obj);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600651
Jordan Crouse7c325702012-06-20 08:22:16 -0600652 if (device->snapshot_frozen)
653 KGSL_DRV_ERR(device, "Snapshot objects released\n");
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600654
Jordan Crouse7c325702012-06-20 08:22:16 -0600655 device->snapshot_frozen = 0;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600656 }
657
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600658done:
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700659 mutex_unlock(&device->mutex);
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600660
Jordan Crouse7c325702012-06-20 08:22:16 -0600661 return itr.write;
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700662}
663
664/* Show the timestamp of the last collected snapshot */
665static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
666{
Jordan Crouseaeebcc02013-02-14 14:11:44 -0700667 return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_timestamp);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700668}
669
670/* manually trigger a new snapshot to be collected */
671static ssize_t trigger_store(struct kgsl_device *device, const char *buf,
672 size_t count)
673{
674 if (device && count > 0) {
675 mutex_lock(&device->mutex);
676 kgsl_device_snapshot(device, 0);
677 mutex_unlock(&device->mutex);
678 }
679
680 return count;
681}
682
683static struct bin_attribute snapshot_attr = {
684 .attr.name = "dump",
685 .attr.mode = 0444,
686 .size = 0,
687 .read = snapshot_show
688};
689
690#define SNAPSHOT_ATTR(_name, _mode, _show, _store) \
691struct kgsl_snapshot_attribute attr_##_name = { \
692 .attr = { .name = __stringify(_name), .mode = _mode }, \
693 .show = _show, \
694 .store = _store, \
695}
696
697SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store);
698SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL);
699
700static void snapshot_sysfs_release(struct kobject *kobj)
701{
702}
703
704static ssize_t snapshot_sysfs_show(struct kobject *kobj,
705 struct attribute *attr, char *buf)
706{
707 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
708 struct kgsl_device *device = kobj_to_device(kobj);
709 ssize_t ret;
710
711 if (device && pattr->show)
712 ret = pattr->show(device, buf);
713 else
714 ret = -EIO;
715
716 return ret;
717}
718
719static ssize_t snapshot_sysfs_store(struct kobject *kobj,
720 struct attribute *attr, const char *buf, size_t count)
721{
722 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
723 struct kgsl_device *device = kobj_to_device(kobj);
724 ssize_t ret;
725
726 if (device && pattr->store)
727 ret = pattr->store(device, buf, count);
728 else
729 ret = -EIO;
730
731 return ret;
732}
733
734static const struct sysfs_ops snapshot_sysfs_ops = {
735 .show = snapshot_sysfs_show,
736 .store = snapshot_sysfs_store,
737};
738
739static struct kobj_type ktype_snapshot = {
740 .sysfs_ops = &snapshot_sysfs_ops,
741 .default_attrs = NULL,
742 .release = snapshot_sysfs_release,
743};
744
745/* kgsl_device_snapshot_init - Add resources for the device GPU snapshot
746 * @device - The device to initalize
747 *
748 * Allocate memory for a GPU snapshot for the specified device,
749 * and create the sysfs files to manage it
750 */
751
752int kgsl_device_snapshot_init(struct kgsl_device *device)
753{
754 int ret;
755
756 if (device->snapshot == NULL)
Jeremy Gebben9d15ae42012-02-29 16:50:27 -0700757 device->snapshot = kzalloc(KGSL_SNAPSHOT_MEMSIZE, GFP_KERNEL);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700758
759 if (device->snapshot == NULL)
760 return -ENOMEM;
761
762 device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE;
763 device->snapshot_timestamp = 0;
764
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600765 INIT_LIST_HEAD(&device->snapshot_obj_list);
766
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700767 ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
768 &device->dev->kobj, "snapshot");
769 if (ret)
770 goto done;
771
772 ret = sysfs_create_bin_file(&device->snapshot_kobj, &snapshot_attr);
773 if (ret)
774 goto done;
775
776 ret = sysfs_create_file(&device->snapshot_kobj, &attr_trigger.attr);
777 if (ret)
778 goto done;
779
780 ret = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr);
781
782done:
783 return ret;
784}
785EXPORT_SYMBOL(kgsl_device_snapshot_init);
786
787/* kgsl_device_snapshot_close - Take down snapshot memory for a device
788 * @device - Pointer to the kgsl_device
789 *
790 * Remove the sysfs files and free the memory allocated for the GPU
791 * snapshot
792 */
793
794void kgsl_device_snapshot_close(struct kgsl_device *device)
795{
796 sysfs_remove_bin_file(&device->snapshot_kobj, &snapshot_attr);
797 sysfs_remove_file(&device->snapshot_kobj, &attr_trigger.attr);
798 sysfs_remove_file(&device->snapshot_kobj, &attr_timestamp.attr);
799
800 kobject_put(&device->snapshot_kobj);
801
Jeremy Gebben9d15ae42012-02-29 16:50:27 -0700802 kfree(device->snapshot);
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700803
804 device->snapshot = NULL;
805 device->snapshot_maxsize = 0;
806 device->snapshot_timestamp = 0;
807}
808EXPORT_SYMBOL(kgsl_device_snapshot_close);