blob: 72df148bc752098c1e7ed4312bc03584aa28d003 [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
142int kgsl_snapshot_dump_indexed_regs(struct kgsl_device *device,
143 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}
167EXPORT_SYMBOL(kgsl_snapshot_dump_indexed_regs);
168
169/*
170 * kgsl_snapshot_dump_regs - helper function to dump device registers
171 * @device - the device to dump registers from
172 * @snapshot - pointer to the start of the region of memory for the snapshot
173 * @remain - a pointer to the number of bytes remaining in the snapshot
174 * @priv - A pointer to the kgsl_snapshot_registers data
175 *
176 * Given an array of register ranges pairs (start,end [inclusive]), dump the
177 * registers into a snapshot register section. The snapshot region stores a
178 * part of dwords for each register - the word address of the register, and
179 * the value.
180 */
181int kgsl_snapshot_dump_regs(struct kgsl_device *device, void *snapshot,
182 int remain, void *priv)
183{
184 struct kgsl_snapshot_regs *header = snapshot;
185 struct kgsl_snapshot_registers *regs = priv;
186 unsigned int *data = snapshot + sizeof(*header);
187 int count = 0, i, j;
188
189 /* Figure out how many registers we are going to dump */
190
191 for (i = 0; i < regs->count; i++) {
192 int start = regs->regs[i * 2];
193 int end = regs->regs[i * 2 + 1];
194
195 count += (end - start + 1);
196 }
197
198 if (remain < (count * 8) + sizeof(*header)) {
199 SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
200 return 0;
201 }
202
203 for (i = 0; i < regs->count; i++) {
204 unsigned int start = regs->regs[i * 2];
205 unsigned int end = regs->regs[i * 2 + 1];
206
207 for (j = start; j <= end; j++) {
208 unsigned int val;
209
210 kgsl_regread(device, j, &val);
211 *data++ = j;
212 *data++ = val;
213 }
214 }
215
216 header->count = count;
217
218 /* Return the size of the section */
219 return (count * 8) + sizeof(*header);
220}
221EXPORT_SYMBOL(kgsl_snapshot_dump_regs);
222
223/*
224 * kgsl_snapshot - construct a device snapshot
225 * @device - device to snapshot
226 * @hang - set to 1 if the snapshot was triggered following a hnag
227 * Given a device, construct a binary snapshot dump of the current device state
228 * and store it in the device snapshot memory.
229 */
230int kgsl_device_snapshot(struct kgsl_device *device, int hang)
231{
232 struct kgsl_snapshot_header *header = device->snapshot;
233 int remain = device->snapshot_maxsize - sizeof(*header);
234 void *snapshot;
235
236 /*
237 * The first hang is always the one we are interested in. To
238 * avoid a subsequent hang blowing away the first, the snapshot
239 * is frozen until it is dumped via sysfs.
240 *
241 * Note that triggered snapshots are always taken regardless
242 * of the state and never frozen.
243 */
244
245 if (hang && device->snapshot_frozen == 1)
246 return 0;
247
248 if (device->snapshot == NULL) {
249 KGSL_DRV_ERR(device,
250 "snapshot: No snapshot memory available\n");
251 return -ENOMEM;
252 }
253
254 if (remain < sizeof(*header)) {
255 KGSL_DRV_ERR(device,
256 "snapshot: Not enough memory for the header\n");
257 return -ENOMEM;
258 }
259
260 header->magic = SNAPSHOT_MAGIC;
261
262 header->gpuid = kgsl_gpuid(device);
263
264 /* Get a pointer to the first section (right after the header) */
265 snapshot = ((void *) device->snapshot) + sizeof(*header);
266
267 /* Build the Linux specific header */
268 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
269 snapshot, &remain, snapshot_os, (void *) hang);
270
271 /* Get the device specific sections */
272 if (device->ftbl->snapshot)
273 snapshot = device->ftbl->snapshot(device, snapshot, &remain,
274 hang);
275
276 /* Add the empty end section to let the parser know we are done */
277 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_END,
278 snapshot, &remain, NULL, NULL);
279
280 device->snapshot_timestamp = get_seconds();
281 device->snapshot_size = (int) (snapshot - device->snapshot);
282
283 /* Freeze the snapshot on a hang until it gets read */
284 device->snapshot_frozen = (hang) ? 1 : 0;
285
286 return 0;
287}
288EXPORT_SYMBOL(kgsl_device_snapshot);
289
290/* An attribute for showing snapshot details */
291struct kgsl_snapshot_attribute {
292 struct attribute attr;
293 ssize_t (*show)(struct kgsl_device *device, char *buf);
294 ssize_t (*store)(struct kgsl_device *device, const char *buf,
295 size_t count);
296};
297
298#define to_snapshot_attr(a) \
299container_of(a, struct kgsl_snapshot_attribute, attr)
300
301#define kobj_to_device(a) \
302container_of(a, struct kgsl_device, snapshot_kobj)
303
304/* Dump the sysfs binary data to the user */
305static ssize_t snapshot_show(struct file *filep, struct kobject *kobj,
306 struct bin_attribute *attr, char *buf, loff_t off,
307 size_t count)
308{
309 struct kgsl_device *device = kobj_to_device(kobj);
310
311 if (device == NULL)
312 return 0;
313
314 /* Return nothing if we haven't taken a snapshot yet */
315 if (device->snapshot_timestamp == 0)
316 return 0;
317
318 /* Get the mutex to keep things from changing while we are dumping */
319 mutex_lock(&device->mutex);
320
321 /*
322 * Release the freeze on the snapshot the first time the buffer is read
323 */
324
325 device->snapshot_frozen = 0;
326
327 if (off >= device->snapshot_size) {
328 count = 0;
329 goto exit;
330 }
331
332 if (off + count > device->snapshot_size)
333 count = device->snapshot_size - off;
334
335 memcpy(buf, device->snapshot + off, count);
336
337exit:
338 mutex_unlock(&device->mutex);
339 return count;
340}
341
342/* Show the timestamp of the last collected snapshot */
343static ssize_t timestamp_show(struct kgsl_device *device, char *buf)
344{
345 return snprintf(buf, PAGE_SIZE, "%x\n", device->snapshot_timestamp);
346}
347
348/* manually trigger a new snapshot to be collected */
349static ssize_t trigger_store(struct kgsl_device *device, const char *buf,
350 size_t count)
351{
352 if (device && count > 0) {
353 mutex_lock(&device->mutex);
354 kgsl_device_snapshot(device, 0);
355 mutex_unlock(&device->mutex);
356 }
357
358 return count;
359}
360
361static struct bin_attribute snapshot_attr = {
362 .attr.name = "dump",
363 .attr.mode = 0444,
364 .size = 0,
365 .read = snapshot_show
366};
367
368#define SNAPSHOT_ATTR(_name, _mode, _show, _store) \
369struct kgsl_snapshot_attribute attr_##_name = { \
370 .attr = { .name = __stringify(_name), .mode = _mode }, \
371 .show = _show, \
372 .store = _store, \
373}
374
375SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store);
376SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL);
377
378static void snapshot_sysfs_release(struct kobject *kobj)
379{
380}
381
382static ssize_t snapshot_sysfs_show(struct kobject *kobj,
383 struct attribute *attr, char *buf)
384{
385 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
386 struct kgsl_device *device = kobj_to_device(kobj);
387 ssize_t ret;
388
389 if (device && pattr->show)
390 ret = pattr->show(device, buf);
391 else
392 ret = -EIO;
393
394 return ret;
395}
396
397static ssize_t snapshot_sysfs_store(struct kobject *kobj,
398 struct attribute *attr, const char *buf, size_t count)
399{
400 struct kgsl_snapshot_attribute *pattr = to_snapshot_attr(attr);
401 struct kgsl_device *device = kobj_to_device(kobj);
402 ssize_t ret;
403
404 if (device && pattr->store)
405 ret = pattr->store(device, buf, count);
406 else
407 ret = -EIO;
408
409 return ret;
410}
411
412static const struct sysfs_ops snapshot_sysfs_ops = {
413 .show = snapshot_sysfs_show,
414 .store = snapshot_sysfs_store,
415};
416
417static struct kobj_type ktype_snapshot = {
418 .sysfs_ops = &snapshot_sysfs_ops,
419 .default_attrs = NULL,
420 .release = snapshot_sysfs_release,
421};
422
423/* kgsl_device_snapshot_init - Add resources for the device GPU snapshot
424 * @device - The device to initalize
425 *
426 * Allocate memory for a GPU snapshot for the specified device,
427 * and create the sysfs files to manage it
428 */
429
430int kgsl_device_snapshot_init(struct kgsl_device *device)
431{
432 int ret;
433
434 if (device->snapshot == NULL)
435 device->snapshot = vmalloc(KGSL_SNAPSHOT_MEMSIZE);
436
437 if (device->snapshot == NULL)
438 return -ENOMEM;
439
440 device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE;
441 device->snapshot_timestamp = 0;
442
443 ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
444 &device->dev->kobj, "snapshot");
445 if (ret)
446 goto done;
447
448 ret = sysfs_create_bin_file(&device->snapshot_kobj, &snapshot_attr);
449 if (ret)
450 goto done;
451
452 ret = sysfs_create_file(&device->snapshot_kobj, &attr_trigger.attr);
453 if (ret)
454 goto done;
455
456 ret = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr);
457
458done:
459 return ret;
460}
461EXPORT_SYMBOL(kgsl_device_snapshot_init);
462
463/* kgsl_device_snapshot_close - Take down snapshot memory for a device
464 * @device - Pointer to the kgsl_device
465 *
466 * Remove the sysfs files and free the memory allocated for the GPU
467 * snapshot
468 */
469
470void kgsl_device_snapshot_close(struct kgsl_device *device)
471{
472 sysfs_remove_bin_file(&device->snapshot_kobj, &snapshot_attr);
473 sysfs_remove_file(&device->snapshot_kobj, &attr_trigger.attr);
474 sysfs_remove_file(&device->snapshot_kobj, &attr_timestamp.attr);
475
476 kobject_put(&device->snapshot_kobj);
477
478 vfree(device->snapshot);
479
480 device->snapshot = NULL;
481 device->snapshot_maxsize = 0;
482 device->snapshot_timestamp = 0;
483}
484EXPORT_SYMBOL(kgsl_device_snapshot_close);