blob: de39ee435af528d9d8f8910d344df58658d7bd40 [file] [log] [blame]
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
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
13#include <linux/vmalloc.h>
14#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
26/* idr_for_each function to count the number of contexts */
27
28static int snapshot_context_count(int id, void *ptr, void *data)
29{
30 int *count = data;
31 *count = *count + 1;
32
33 return 0;
34}
35
36/*
37 * To simplify the iterator loop use a global pointer instead of trying
38 * to pass around double star references to the snapshot data
39 */
40
41static void *_ctxtptr;
42
43static int snapshot_context_info(int id, void *ptr, void *data)
44{
45 struct kgsl_snapshot_linux_context *header = _ctxtptr;
46 struct kgsl_context *context = ptr;
47 struct kgsl_device *device = context->dev_priv->device;
48
49 header->id = id;
50
51 /* Future-proof for per-context timestamps - for now, just
52 * return the global timestamp for all contexts
53 */
54
55 header->timestamp_queued = -1;
56 header->timestamp_retired = device->ftbl->readtimestamp(device,
57 KGSL_TIMESTAMP_RETIRED);
58
59 _ctxtptr += sizeof(struct kgsl_snapshot_linux_context);
60
61 return 0;
62}
63
64/* Snapshot the Linux specific information */
65static int snapshot_os(struct kgsl_device *device,
66 void *snapshot, int remain, void *priv)
67{
68 struct kgsl_snapshot_linux *header = snapshot;
69 struct kgsl_pwrctrl *pwr = &device->pwrctrl;
70 struct task_struct *task;
71 pid_t pid;
72 int hang = (int) priv;
73 int ctxtcount = 0;
74 int size = sizeof(*header);
75
76 /* Figure out how many active contexts there are - these will
77 * be appended on the end of the structure */
78
79 idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
80
81 size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
82
83 /* Make sure there is enough room for the data */
84 if (remain < size) {
85 SNAPSHOT_ERR_NOMEM(device, "OS");
86 return 0;
87 }
88
89 memset(header, 0, sizeof(*header));
90
91 header->osid = KGSL_SNAPSHOT_OS_LINUX;
92
93 header->state = hang ? SNAPSHOT_STATE_HUNG : SNAPSHOT_STATE_RUNNING;
94
95 /* Get the kernel build information */
96 strlcpy(header->release, utsname()->release, sizeof(header->release));
97 strlcpy(header->version, utsname()->version, sizeof(header->version));
98
99 /* Get the Unix time for the timestamp */
100 header->seconds = get_seconds();
101
102 /* Remember the power information */
103 header->power_flags = pwr->power_flags;
104 header->power_level = pwr->active_pwrlevel;
105 header->power_interval_timeout = pwr->interval_timeout;
106 header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]);
107 header->busclk = kgsl_get_clkrate(pwr->ebi1_clk);
108
109 /* Future proof for per-context timestamps */
110 header->current_context = -1;
111
112 /* Get the current PT base */
113 header->ptbase = kgsl_mmu_get_current_ptbase(device);
114 /* And the PID for the task leader */
115 pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase);
116
117 task = find_task_by_vpid(pid);
118
119 if (task)
120 get_task_comm(header->comm, task);
121
122 header->ctxtcount = ctxtcount;
123
124 /* append information for each context */
125 _ctxtptr = snapshot + sizeof(*header);
126 idr_for_each(&device->context_idr, snapshot_context_info, NULL);
127
128 /* Return the size of the data segment */
129 return size;
130}
131/*
132 * kgsl_snapshot_dump_indexed_regs - helper function to dump indexed registers
133 * @device - the device to dump registers from
134 * @snapshot - pointer to the start of the region of memory for the snapshot
135 * @remain - a pointer to the number of bytes remaining in the snapshot
136 * @priv - A pointer to the kgsl_snapshot_indexed_registers data
137 *
138 * Given a indexed register cmd/data pair and a count, dump each indexed
139 * register
140 */
141
Jordan Crouse0c2761a2012-02-01 22:11:12 -0700142static int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700143 void *snapshot, int remain, void *priv)
144{
145 struct kgsl_snapshot_indexed_registers *iregs = priv;
146 struct kgsl_snapshot_indexed_regs *header = snapshot;
147 unsigned int *data = snapshot + sizeof(*header);
148 int i;
149
150 if (remain < (iregs->count * 4) + sizeof(*header)) {
151 SNAPSHOT_ERR_NOMEM(device, "INDEXED REGS");
152 return 0;
153 }
154
155 header->index_reg = iregs->index;
156 header->data_reg = iregs->data;
157 header->count = iregs->count;
158 header->start = iregs->start;
159
160 for (i = 0; i < iregs->count; i++) {
161 kgsl_regwrite(device, iregs->index, iregs->start + i);
162 kgsl_regread(device, iregs->data, &data[i]);
163 }
164
165 return (iregs->count * 4) + sizeof(*header);
166}
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700167
168/*
169 * kgsl_snapshot_dump_regs - helper function to dump device registers
170 * @device - the device to dump registers from
171 * @snapshot - pointer to the start of the region of memory for the snapshot
172 * @remain - a pointer to the number of bytes remaining in the snapshot
173 * @priv - A pointer to the kgsl_snapshot_registers data
174 *
175 * Given an array of register ranges pairs (start,end [inclusive]), dump the
176 * registers into a snapshot register section. The snapshot region stores a
177 * part of dwords for each register - the word address of the register, and
178 * the value.
179 */
180int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
181 int remain, void *priv)
182{
183 struct kgsl_snapshot_regs *header = snapshot;
184 struct kgsl_snapshot_registers *regs = priv;
185 unsigned int *data = snapshot + sizeof(*header);
186 int count = 0, i, j;
187
188 /* Figure out how many registers we are going to dump */
189
190 for (i = 0; i < regs->count; i++) {
191 int start = regs->regs[i * 2];
192 int end = regs->regs[i * 2 + 1];
193
194 count += (end - start + 1);
195 }
196
197 if (remain < (count * 8) + sizeof(*header)) {
198 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
199 return 0;
200 }
201
202 for (i = 0; i < regs->count; i++) {
203 unsigned int start = regs->regs[i * 2];
204 unsigned int end = regs->regs[i * 2 + 1];
205
206 for (j = start; j <= end; j++) {
207 unsigned int val;
208
209 kgsl_regread(device, j, &val);
210 *data++ = j;
211 *data++ = val;
212 }
213 }
214
215 header->count = count;
216
217 /* Return the size of the section */
218 return (count * 8) + sizeof(*header);
219}
220EXPORT_SYMBOL(kgsl_snapshot_dump_regs);
221
Jordan Crouse0c2761a2012-02-01 22:11:12 -0700222void *kgsl_snapshot_indexed_registers(struct kgsl_device *device,
223 void *snapshot, int *remain,
224 unsigned int index, unsigned int data, unsigned int start,
225 unsigned int count)
226{
227 struct kgsl_snapshot_indexed_registers iregs;
228 iregs.index = index;
229 iregs.data = data;
230 iregs.start = start;
231 iregs.count = count;
232
233 return kgsl_snapshot_add_section(device,
234 KGSL_SNAPSHOT_SECTION_INDEXED_REGS, snapshot,
235 remain, kgsl_snapshot_dump_indexed_regs, &iregs);
236}
237EXPORT_SYMBOL(kgsl_snapshot_indexed_registers);
238
Jordan Crouse156cfbc2012-01-24 09:32:04 -0700239/*
240 * kgsl_snapshot - construct a device snapshot
241 * @device - device to snapshot
242 * @hang - set to 1 if the snapshot was triggered following a hnag
243 * Given a device, construct a binary snapshot dump of the current device state
244 * and store it in the device snapshot memory.
245 */
246int kgsl_device_snapshot(struct kgsl_device *device, int hang)
247{
248 struct kgsl_snapshot_header *header = device->snapshot;
249 int remain = device->snapshot_maxsize - sizeof(*header);
250 void *snapshot;
251
252 /*
253 * The first hang is always the one we are interested in. To
254 * avoid a subsequent hang blowing away the first, the snapshot
255 * is frozen until it is dumped via sysfs.
256 *
257 * Note that triggered snapshots are always taken regardless
258 * of the state and never frozen.
259 */
260
261 if (hang && device->snapshot_frozen == 1)
262 return 0;
263
264 if (device->snapshot == NULL) {
265 KGSL_DRV_ERR(device,
266 "snapshot: No snapshot memory available\n");
267 return -ENOMEM;
268 }
269
270 if (remain < sizeof(*header)) {
271 KGSL_DRV_ERR(device,
272 "snapshot: Not enough memory for the header\n");
273 return -ENOMEM;
274 }
275
276 header->magic = SNAPSHOT_MAGIC;
277
278 header->gpuid = kgsl_gpuid(device);
279
280 /* Get a pointer to the first section (right after the header) */
281 snapshot = ((void *) device->snapshot) + sizeof(*header);
282
283 /* Build the Linux specific header */
284 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
285 snapshot, &remain, snapshot_os, (void *) hang);
286
287 /* Get the device specific sections */
288 if (device->ftbl->snapshot)
289 snapshot = device->ftbl->snapshot(device, snapshot, &remain,
290 hang);
291
292 /* Add the empty end section to let the parser know we are done */
293 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_END,
294 snapshot, &remain, NULL, NULL);
295
296 device->snapshot_timestamp = get_seconds();
297 device->snapshot_size = (int) (snapshot - device->snapshot);
298
299 /* Freeze the snapshot on a hang until it gets read */
300 device->snapshot_frozen = (hang) ? 1 : 0;
301
302 return 0;
303}
304EXPORT_SYMBOL(kgsl_device_snapshot);
305
306/* An attribute for showing snapshot details */
307struct kgsl_snapshot_attribute {
308 struct attribute attr;
309 ssize_t (*show)(struct kgsl_device *device, char *buf);
310 ssize_t (*store)(struct kgsl_device *device, const char *buf,
311 size_t count);
312};
313
314#define to_snapshot_attr(a) \
315container_of(a, struct kgsl_snapshot_attribute, attr)
316
317#define kobj_to_device(a) \
318container_of(a, struct kgsl_device, snapshot_kobj)
319
320/* Dump the sysfs binary data to the user */
321static ssize_t snapshot_show(struct file *filep, struct kobject *kobj,
322 struct bin_attribute *attr, char *buf, loff_t off,
323 size_t count)
324{
325 struct kgsl_device *device = kobj_to_device(kobj);
326
327 if (device == NULL)
328 return 0;
329
330 /* Return nothing if we haven't taken a snapshot yet */
331 if (device->snapshot_timestamp == 0)
332 return 0;
333
334 /* Get the mutex to keep things from changing while we are dumping */
335 mutex_lock(&device->mutex);
336
337 /*
338 * Release the freeze on the snapshot the first time the buffer is read
339 */
340
341 device->snapshot_frozen = 0;
342
343 if (off >= device->snapshot_size) {
344 count = 0;
345 goto exit;
346 }
347
348 if (off + count > device->snapshot_size)
349 count = device->snapshot_size - off;
350
351 memcpy(buf, device->snapshot + off, count);
352
353exit:
354 mutex_unlock(&device->mutex);
355 return count;
356}
357
358/* Show the timestamp of the last collected snapshot */
359static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
360{
361 return snprintf(buf, PAGE_SIZE, "%x\n", device->snapshot_timestamp);
362}
363
364/* manually trigger a new snapshot to be collected */
365static ssize_t trigger_store(struct kgsl_device *device, const char *buf,
366 size_t count)
367{
368 if (device && count > 0) {
369 mutex_lock(&device->mutex);
370 kgsl_device_snapshot(device, 0);
371 mutex_unlock(&device->mutex);
372 }
373
374 return count;
375}
376
377static struct bin_attribute snapshot_attr = {
378 .attr.name = "dump",
379 .attr.mode = 0444,
380 .size = 0,
381 .read = snapshot_show
382};
383
384#define SNAPSHOT_ATTR(_name, _mode, _show, _store) \
385struct kgsl_snapshot_attribute attr_##_name = { \
386 .attr = { .name = __stringify(_name), .mode = _mode }, \
387 .show = _show, \
388 .store = _store, \
389}
390
391SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store);
392SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL);
393
394static void snapshot_sysfs_release(struct kobject *kobj)
395{
396}
397
398static ssize_t snapshot_sysfs_show(struct kobject *kobj,
399 struct attribute *attr, char *buf)
400{
401 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
402 struct kgsl_device *device = kobj_to_device(kobj);
403 ssize_t ret;
404
405 if (device && pattr->show)
406 ret = pattr->show(device, buf);
407 else
408 ret = -EIO;
409
410 return ret;
411}
412
413static ssize_t snapshot_sysfs_store(struct kobject *kobj,
414 struct attribute *attr, const char *buf, size_t count)
415{
416 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
417 struct kgsl_device *device = kobj_to_device(kobj);
418 ssize_t ret;
419
420 if (device && pattr->store)
421 ret = pattr->store(device, buf, count);
422 else
423 ret = -EIO;
424
425 return ret;
426}
427
428static const struct sysfs_ops snapshot_sysfs_ops = {
429 .show = snapshot_sysfs_show,
430 .store = snapshot_sysfs_store,
431};
432
433static struct kobj_type ktype_snapshot = {
434 .sysfs_ops = &snapshot_sysfs_ops,
435 .default_attrs = NULL,
436 .release = snapshot_sysfs_release,
437};
438
439/* kgsl_device_snapshot_init - Add resources for the device GPU snapshot
440 * @device - The device to initalize
441 *
442 * Allocate memory for a GPU snapshot for the specified device,
443 * and create the sysfs files to manage it
444 */
445
446int kgsl_device_snapshot_init(struct kgsl_device *device)
447{
448 int ret;
449
450 if (device->snapshot == NULL)
451 device->snapshot = vmalloc(KGSL_SNAPSHOT_MEMSIZE);
452
453 if (device->snapshot == NULL)
454 return -ENOMEM;
455
456 device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE;
457 device->snapshot_timestamp = 0;
458
459 ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
460 &device->dev->kobj, "snapshot");
461 if (ret)
462 goto done;
463
464 ret = sysfs_create_bin_file(&device->snapshot_kobj, &snapshot_attr);
465 if (ret)
466 goto done;
467
468 ret = sysfs_create_file(&device->snapshot_kobj, &attr_trigger.attr);
469 if (ret)
470 goto done;
471
472 ret = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr);
473
474done:
475 return ret;
476}
477EXPORT_SYMBOL(kgsl_device_snapshot_init);
478
479/* kgsl_device_snapshot_close - Take down snapshot memory for a device
480 * @device - Pointer to the kgsl_device
481 *
482 * Remove the sysfs files and free the memory allocated for the GPU
483 * snapshot
484 */
485
486void kgsl_device_snapshot_close(struct kgsl_device *device)
487{
488 sysfs_remove_bin_file(&device->snapshot_kobj, &snapshot_attr);
489 sysfs_remove_file(&device->snapshot_kobj, &attr_trigger.attr);
490 sysfs_remove_file(&device->snapshot_kobj, &attr_timestamp.attr);
491
492 kobject_put(&device->snapshot_kobj);
493
494 vfree(device->snapshot);
495
496 device->snapshot = NULL;
497 device->snapshot_maxsize = 0;
498 device->snapshot_timestamp = 0;
499}
500EXPORT_SYMBOL(kgsl_device_snapshot_close);