.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2013 Red Hat |
---|
3 | 4 | * Author: Rob Clark <robdclark@gmail.com> |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
7 | | - * the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | | - * |
---|
14 | | - * You should have received a copy of the GNU General Public License along with |
---|
15 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
---|
16 | 5 | */ |
---|
17 | 6 | |
---|
18 | 7 | /* For debugging crashes, userspace can: |
---|
.. | .. |
---|
40 | 29 | * or shader programs (if not emitted inline in cmdstream). |
---|
41 | 30 | */ |
---|
42 | 31 | |
---|
43 | | -#ifdef CONFIG_DEBUG_FS |
---|
44 | | - |
---|
45 | | -#include <linux/kfifo.h> |
---|
46 | | -#include <linux/debugfs.h> |
---|
47 | 32 | #include <linux/circ_buf.h> |
---|
| 33 | +#include <linux/debugfs.h> |
---|
| 34 | +#include <linux/kfifo.h> |
---|
| 35 | +#include <linux/uaccess.h> |
---|
48 | 36 | #include <linux/wait.h> |
---|
| 37 | + |
---|
| 38 | +#include <drm/drm_file.h> |
---|
49 | 39 | |
---|
50 | 40 | #include "msm_drv.h" |
---|
51 | 41 | #include "msm_gpu.h" |
---|
52 | 42 | #include "msm_gem.h" |
---|
53 | 43 | |
---|
54 | | -static bool rd_full = false; |
---|
| 44 | +bool rd_full = false; |
---|
55 | 45 | MODULE_PARM_DESC(rd_full, "If true, $debugfs/.../rd will snapshot all buffer contents"); |
---|
56 | 46 | module_param_named(rd_full, rd_full, bool, 0600); |
---|
| 47 | + |
---|
| 48 | +#ifdef CONFIG_DEBUG_FS |
---|
57 | 49 | |
---|
58 | 50 | enum rd_sect_type { |
---|
59 | 51 | RD_NONE, |
---|
.. | .. |
---|
199 | 191 | file->private_data = rd; |
---|
200 | 192 | rd->open = true; |
---|
201 | 193 | |
---|
| 194 | + /* Reset fifo to clear any previously unread data: */ |
---|
| 195 | + rd->fifo.head = rd->fifo.tail = 0; |
---|
| 196 | + |
---|
202 | 197 | /* the parsing tools need to know gpu-id to know which |
---|
203 | 198 | * register database to load. |
---|
204 | 199 | */ |
---|
.. | .. |
---|
244 | 239 | static struct msm_rd_state *rd_init(struct drm_minor *minor, const char *name) |
---|
245 | 240 | { |
---|
246 | 241 | struct msm_rd_state *rd; |
---|
247 | | - struct dentry *ent; |
---|
248 | | - int ret = 0; |
---|
249 | 242 | |
---|
250 | 243 | rd = kzalloc(sizeof(*rd), GFP_KERNEL); |
---|
251 | 244 | if (!rd) |
---|
.. | .. |
---|
258 | 251 | |
---|
259 | 252 | init_waitqueue_head(&rd->fifo_event); |
---|
260 | 253 | |
---|
261 | | - ent = debugfs_create_file(name, S_IFREG | S_IRUGO, |
---|
262 | | - minor->debugfs_root, rd, &rd_debugfs_fops); |
---|
263 | | - if (!ent) { |
---|
264 | | - DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/%s\n", |
---|
265 | | - minor->debugfs_root, name); |
---|
266 | | - ret = -ENOMEM; |
---|
267 | | - goto fail; |
---|
268 | | - } |
---|
| 254 | + debugfs_create_file(name, S_IFREG | S_IRUGO, minor->debugfs_root, rd, |
---|
| 255 | + &rd_debugfs_fops); |
---|
269 | 256 | |
---|
270 | 257 | return rd; |
---|
271 | | - |
---|
272 | | -fail: |
---|
273 | | - rd_cleanup(rd); |
---|
274 | | - return ERR_PTR(ret); |
---|
275 | 258 | } |
---|
276 | 259 | |
---|
277 | 260 | int msm_rd_debugfs_init(struct drm_minor *minor) |
---|
.. | .. |
---|
318 | 301 | |
---|
319 | 302 | static void snapshot_buf(struct msm_rd_state *rd, |
---|
320 | 303 | struct msm_gem_submit *submit, int idx, |
---|
321 | | - uint64_t iova, uint32_t size) |
---|
| 304 | + uint64_t iova, uint32_t size, bool full) |
---|
322 | 305 | { |
---|
323 | 306 | struct msm_gem_object *obj = submit->bos[idx].obj; |
---|
324 | 307 | unsigned offset = 0; |
---|
.. | .. |
---|
337 | 320 | */ |
---|
338 | 321 | rd_write_section(rd, RD_GPUADDR, |
---|
339 | 322 | (uint32_t[3]){ iova, size, iova >> 32 }, 12); |
---|
| 323 | + |
---|
| 324 | + if (!full) |
---|
| 325 | + return; |
---|
340 | 326 | |
---|
341 | 327 | /* But only dump the contents of buffers marked READ */ |
---|
342 | 328 | if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ)) |
---|
.. | .. |
---|
374 | 360 | va_list args; |
---|
375 | 361 | |
---|
376 | 362 | va_start(args, fmt); |
---|
377 | | - n = vsnprintf(msg, sizeof(msg), fmt, args); |
---|
| 363 | + n = vscnprintf(msg, sizeof(msg), fmt, args); |
---|
378 | 364 | va_end(args); |
---|
379 | 365 | |
---|
380 | 366 | rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); |
---|
.. | .. |
---|
383 | 369 | rcu_read_lock(); |
---|
384 | 370 | task = pid_task(submit->pid, PIDTYPE_PID); |
---|
385 | 371 | if (task) { |
---|
386 | | - n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u", |
---|
| 372 | + n = scnprintf(msg, sizeof(msg), "%.*s/%d: fence=%u", |
---|
387 | 373 | TASK_COMM_LEN, task->comm, |
---|
388 | 374 | pid_nr(submit->pid), submit->seqno); |
---|
389 | 375 | } else { |
---|
390 | | - n = snprintf(msg, sizeof(msg), "???/%d: fence=%u", |
---|
| 376 | + n = scnprintf(msg, sizeof(msg), "???/%d: fence=%u", |
---|
391 | 377 | pid_nr(submit->pid), submit->seqno); |
---|
392 | 378 | } |
---|
393 | 379 | rcu_read_unlock(); |
---|
394 | 380 | |
---|
395 | 381 | rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); |
---|
396 | 382 | |
---|
397 | | - for (i = 0; rd_full && i < submit->nr_bos; i++) |
---|
398 | | - snapshot_buf(rd, submit, i, 0, 0); |
---|
| 383 | + for (i = 0; i < submit->nr_bos; i++) |
---|
| 384 | + snapshot_buf(rd, submit, i, 0, 0, should_dump(submit, i)); |
---|
| 385 | + |
---|
| 386 | + for (i = 0; i < submit->nr_cmds; i++) { |
---|
| 387 | + uint32_t szd = submit->cmd[i].size; /* in dwords */ |
---|
| 388 | + |
---|
| 389 | + /* snapshot cmdstream bo's (if we haven't already): */ |
---|
| 390 | + if (!should_dump(submit, i)) { |
---|
| 391 | + snapshot_buf(rd, submit, submit->cmd[i].idx, |
---|
| 392 | + submit->cmd[i].iova, szd * 4, true); |
---|
| 393 | + } |
---|
| 394 | + } |
---|
399 | 395 | |
---|
400 | 396 | for (i = 0; i < submit->nr_cmds; i++) { |
---|
401 | 397 | uint64_t iova = submit->cmd[i].iova; |
---|
402 | 398 | uint32_t szd = submit->cmd[i].size; /* in dwords */ |
---|
403 | | - |
---|
404 | | - /* snapshot cmdstream bo's (if we haven't already): */ |
---|
405 | | - if (!rd_full) { |
---|
406 | | - snapshot_buf(rd, submit, submit->cmd[i].idx, |
---|
407 | | - submit->cmd[i].iova, szd * 4); |
---|
408 | | - } |
---|
409 | 399 | |
---|
410 | 400 | switch (submit->cmd[i].type) { |
---|
411 | 401 | case MSM_SUBMIT_CMD_IB_TARGET_BUF: |
---|