1/*
2 * Copyright (C) 2013 Red Hat
3 * 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 */
17
18/* For debugging crashes, userspace can:
19 *
20 *   tail -f /sys/kernel/debug/dri/<minor>/rd > logfile.rd
21 *
22 * To log the cmdstream in a format that is understood by freedreno/cffdump
23 * utility.  By comparing the last successfully completed fence #, to the
24 * cmdstream for the next fence, you can narrow down which process and submit
25 * caused the gpu crash/lockup.
26 *
27 * This bypasses drm_debugfs_create_files() mainly because we need to use
28 * our own fops for a bit more control.  In particular, we don't want to
29 * do anything if userspace doesn't have the debugfs file open.
30 */
31
32#ifdef CONFIG_DEBUG_FS
33
34#include <linux/kfifo.h>
35#include <linux/debugfs.h>
36#include <linux/circ_buf.h>
37#include <linux/wait.h>
38
39#include "msm_drv.h"
40#include "msm_gpu.h"
41#include "msm_gem.h"
42
43enum rd_sect_type {
44	RD_NONE,
45	RD_TEST,       /* ascii text */
46	RD_CMD,        /* ascii text */
47	RD_GPUADDR,    /* u32 gpuaddr, u32 size */
48	RD_CONTEXT,    /* raw dump */
49	RD_CMDSTREAM,  /* raw dump */
50	RD_CMDSTREAM_ADDR, /* gpu addr of cmdstream */
51	RD_PARAM,      /* u32 param_type, u32 param_val, u32 bitlen */
52	RD_FLUSH,      /* empty, clear previous params */
53	RD_PROGRAM,    /* shader program, raw dump */
54	RD_VERT_SHADER,
55	RD_FRAG_SHADER,
56	RD_BUFFER_CONTENTS,
57	RD_GPU_ID,
58};
59
60#define BUF_SZ 512  /* should be power of 2 */
61
62/* space used: */
63#define circ_count(circ) \
64	(CIRC_CNT((circ)->head, (circ)->tail, BUF_SZ))
65#define circ_count_to_end(circ) \
66	(CIRC_CNT_TO_END((circ)->head, (circ)->tail, BUF_SZ))
67/* space available: */
68#define circ_space(circ) \
69	(CIRC_SPACE((circ)->head, (circ)->tail, BUF_SZ))
70#define circ_space_to_end(circ) \
71	(CIRC_SPACE_TO_END((circ)->head, (circ)->tail, BUF_SZ))
72
73struct msm_rd_state {
74	struct drm_device *dev;
75
76	bool open;
77
78	struct dentry *ent;
79	struct drm_info_node *node;
80
81	/* current submit to read out: */
82	struct msm_gem_submit *submit;
83
84	/* fifo access is synchronized on the producer side by
85	 * struct_mutex held by submit code (otherwise we could
86	 * end up w/ cmds logged in different order than they
87	 * were executed).  And read_lock synchronizes the reads
88	 */
89	struct mutex read_lock;
90
91	wait_queue_head_t fifo_event;
92	struct circ_buf fifo;
93
94	char buf[BUF_SZ];
95};
96
97static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
98{
99	struct circ_buf *fifo = &rd->fifo;
100	const char *ptr = buf;
101
102	while (sz > 0) {
103		char *fptr = &fifo->buf[fifo->head];
104		int n;
105
106		wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0);
107
108		n = min(sz, circ_space_to_end(&rd->fifo));
109		memcpy(fptr, ptr, n);
110
111		fifo->head = (fifo->head + n) & (BUF_SZ - 1);
112		sz  -= n;
113		ptr += n;
114
115		wake_up_all(&rd->fifo_event);
116	}
117}
118
119static void rd_write_section(struct msm_rd_state *rd,
120		enum rd_sect_type type, const void *buf, int sz)
121{
122	rd_write(rd, &type, 4);
123	rd_write(rd, &sz, 4);
124	rd_write(rd, buf, sz);
125}
126
127static ssize_t rd_read(struct file *file, char __user *buf,
128		size_t sz, loff_t *ppos)
129{
130	struct msm_rd_state *rd = file->private_data;
131	struct circ_buf *fifo = &rd->fifo;
132	const char *fptr = &fifo->buf[fifo->tail];
133	int n = 0, ret = 0;
134
135	mutex_lock(&rd->read_lock);
136
137	ret = wait_event_interruptible(rd->fifo_event,
138			circ_count(&rd->fifo) > 0);
139	if (ret)
140		goto out;
141
142	n = min_t(int, sz, circ_count_to_end(&rd->fifo));
143	ret = copy_to_user(buf, fptr, n);
144	if (ret)
145		goto out;
146
147	fifo->tail = (fifo->tail + n) & (BUF_SZ - 1);
148	*ppos += n;
149
150	wake_up_all(&rd->fifo_event);
151
152out:
153	mutex_unlock(&rd->read_lock);
154	if (ret)
155		return ret;
156	return n;
157}
158
159static int rd_open(struct inode *inode, struct file *file)
160{
161	struct msm_rd_state *rd = inode->i_private;
162	struct drm_device *dev = rd->dev;
163	struct msm_drm_private *priv = dev->dev_private;
164	struct msm_gpu *gpu = priv->gpu;
165	uint64_t val;
166	uint32_t gpu_id;
167	int ret = 0;
168
169	mutex_lock(&dev->struct_mutex);
170
171	if (rd->open || !gpu) {
172		ret = -EBUSY;
173		goto out;
174	}
175
176	file->private_data = rd;
177	rd->open = true;
178
179	/* the parsing tools need to know gpu-id to know which
180	 * register database to load.
181	 */
182	gpu->funcs->get_param(gpu, MSM_PARAM_GPU_ID, &val);
183	gpu_id = val;
184
185	rd_write_section(rd, RD_GPU_ID, &gpu_id, sizeof(gpu_id));
186
187out:
188	mutex_unlock(&dev->struct_mutex);
189	return ret;
190}
191
192static int rd_release(struct inode *inode, struct file *file)
193{
194	struct msm_rd_state *rd = inode->i_private;
195	rd->open = false;
196	return 0;
197}
198
199
200static const struct file_operations rd_debugfs_fops = {
201	.owner = THIS_MODULE,
202	.open = rd_open,
203	.read = rd_read,
204	.llseek = no_llseek,
205	.release = rd_release,
206};
207
208int msm_rd_debugfs_init(struct drm_minor *minor)
209{
210	struct msm_drm_private *priv = minor->dev->dev_private;
211	struct msm_rd_state *rd;
212
213	/* only create on first minor: */
214	if (priv->rd)
215		return 0;
216
217	rd = kzalloc(sizeof(*rd), GFP_KERNEL);
218	if (!rd)
219		return -ENOMEM;
220
221	rd->dev = minor->dev;
222	rd->fifo.buf = rd->buf;
223
224	mutex_init(&rd->read_lock);
225	priv->rd = rd;
226
227	init_waitqueue_head(&rd->fifo_event);
228
229	rd->node = kzalloc(sizeof(*rd->node), GFP_KERNEL);
230	if (!rd->node)
231		goto fail;
232
233	rd->ent = debugfs_create_file("rd", S_IFREG | S_IRUGO,
234			minor->debugfs_root, rd, &rd_debugfs_fops);
235	if (!rd->ent) {
236		DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/rd\n",
237				minor->debugfs_root->d_name.name);
238		goto fail;
239	}
240
241	rd->node->minor = minor;
242	rd->node->dent  = rd->ent;
243	rd->node->info_ent = NULL;
244
245	mutex_lock(&minor->debugfs_lock);
246	list_add(&rd->node->list, &minor->debugfs_list);
247	mutex_unlock(&minor->debugfs_lock);
248
249	return 0;
250
251fail:
252	msm_rd_debugfs_cleanup(minor);
253	return -1;
254}
255
256void msm_rd_debugfs_cleanup(struct drm_minor *minor)
257{
258	struct msm_drm_private *priv = minor->dev->dev_private;
259	struct msm_rd_state *rd = priv->rd;
260
261	if (!rd)
262		return;
263
264	priv->rd = NULL;
265
266	debugfs_remove(rd->ent);
267
268	if (rd->node) {
269		mutex_lock(&minor->debugfs_lock);
270		list_del(&rd->node->list);
271		mutex_unlock(&minor->debugfs_lock);
272		kfree(rd->node);
273	}
274
275	mutex_destroy(&rd->read_lock);
276
277	kfree(rd);
278}
279
280/* called under struct_mutex */
281void msm_rd_dump_submit(struct msm_gem_submit *submit)
282{
283	struct drm_device *dev = submit->dev;
284	struct msm_drm_private *priv = dev->dev_private;
285	struct msm_rd_state *rd = priv->rd;
286	char msg[128];
287	int i, n;
288
289	if (!rd->open)
290		return;
291
292	/* writing into fifo is serialized by caller, and
293	 * rd->read_lock is used to serialize the reads
294	 */
295	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
296
297	n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
298			TASK_COMM_LEN, current->comm, task_pid_nr(current),
299			submit->fence);
300
301	rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
302
303	/* could be nice to have an option (module-param?) to snapshot
304	 * all the bo's associated with the submit.  Handy to see vtx
305	 * buffers, etc.  For now just the cmdstream bo's is enough.
306	 */
307
308	for (i = 0; i < submit->nr_cmds; i++) {
309		uint32_t idx  = submit->cmd[i].idx;
310		uint32_t iova = submit->cmd[i].iova;
311		uint32_t szd  = submit->cmd[i].size; /* in dwords */
312		struct msm_gem_object *obj = submit->bos[idx].obj;
313		const char *buf = msm_gem_vaddr_locked(&obj->base);
314
315		buf += iova - submit->bos[idx].iova;
316
317		rd_write_section(rd, RD_GPUADDR,
318				(uint32_t[2]){ iova, szd * 4 }, 8);
319		rd_write_section(rd, RD_BUFFER_CONTENTS,
320				buf, szd * 4);
321
322		switch (submit->cmd[i].type) {
323		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
324			/* ignore IB-targets, we've logged the buffer, the
325			 * parser tool will follow the IB based on the logged
326			 * buffer/gpuaddr, so nothing more to do.
327			 */
328			break;
329		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
330		case MSM_SUBMIT_CMD_BUF:
331			rd_write_section(rd, RD_CMDSTREAM_ADDR,
332					(uint32_t[2]){ iova, szd }, 8);
333			break;
334		}
335	}
336}
337#endif
338