1 /*
2  * Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  */
14 #include <linux/debugfs.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/uaccess.h>
17 
18 #include <soc/tegra/bpmp.h>
19 #include <soc/tegra/bpmp-abi.h>
20 
21 struct seqbuf {
22 	char *buf;
23 	size_t pos;
24 	size_t size;
25 };
26 
27 static void seqbuf_init(struct seqbuf *seqbuf, void *buf, size_t size)
28 {
29 	seqbuf->buf = buf;
30 	seqbuf->size = size;
31 	seqbuf->pos = 0;
32 }
33 
34 static size_t seqbuf_avail(struct seqbuf *seqbuf)
35 {
36 	return seqbuf->pos < seqbuf->size ? seqbuf->size - seqbuf->pos : 0;
37 }
38 
39 static size_t seqbuf_status(struct seqbuf *seqbuf)
40 {
41 	return seqbuf->pos <= seqbuf->size ? 0 : -EOVERFLOW;
42 }
43 
44 static int seqbuf_eof(struct seqbuf *seqbuf)
45 {
46 	return seqbuf->pos >= seqbuf->size;
47 }
48 
49 static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte)
50 {
51 	nbyte = min(nbyte, seqbuf_avail(seqbuf));
52 	memcpy(buf, seqbuf->buf + seqbuf->pos, nbyte);
53 	seqbuf->pos += nbyte;
54 	return seqbuf_status(seqbuf);
55 }
56 
57 static int seqbuf_read_u32(struct seqbuf *seqbuf, uint32_t *v)
58 {
59 	int err;
60 
61 	err = seqbuf_read(seqbuf, v, 4);
62 	*v = le32_to_cpu(*v);
63 	return err;
64 }
65 
66 static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str)
67 {
68 	*str = seqbuf->buf + seqbuf->pos;
69 	seqbuf->pos += strnlen(*str, seqbuf_avail(seqbuf));
70 	seqbuf->pos++;
71 	return seqbuf_status(seqbuf);
72 }
73 
74 static void seqbuf_seek(struct seqbuf *seqbuf, ssize_t offset)
75 {
76 	seqbuf->pos += offset;
77 }
78 
79 /* map filename in Linux debugfs to corresponding entry in BPMP */
80 static const char *get_filename(struct tegra_bpmp *bpmp,
81 				const struct file *file, char *buf, int size)
82 {
83 	char root_path_buf[512];
84 	const char *root_path;
85 	const char *filename;
86 	size_t root_len;
87 
88 	root_path = dentry_path(bpmp->debugfs_mirror, root_path_buf,
89 				sizeof(root_path_buf));
90 	if (IS_ERR(root_path))
91 		return NULL;
92 
93 	root_len = strlen(root_path);
94 
95 	filename = dentry_path(file->f_path.dentry, buf, size);
96 	if (IS_ERR(filename))
97 		return NULL;
98 
99 	if (strlen(filename) < root_len ||
100 			strncmp(filename, root_path, root_len))
101 		return NULL;
102 
103 	filename += root_len;
104 
105 	return filename;
106 }
107 
108 static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
109 			    dma_addr_t name, size_t sz_name,
110 			    dma_addr_t data, size_t sz_data,
111 			    size_t *nbytes)
112 {
113 	struct mrq_debugfs_request req = {
114 		.cmd = cpu_to_le32(CMD_DEBUGFS_READ),
115 		.fop = {
116 			.fnameaddr = cpu_to_le32((uint32_t)name),
117 			.fnamelen = cpu_to_le32((uint32_t)sz_name),
118 			.dataaddr = cpu_to_le32((uint32_t)data),
119 			.datalen = cpu_to_le32((uint32_t)sz_data),
120 		},
121 	};
122 	struct mrq_debugfs_response resp;
123 	struct tegra_bpmp_message msg = {
124 		.mrq = MRQ_DEBUGFS,
125 		.tx = {
126 			.data = &req,
127 			.size = sizeof(req),
128 		},
129 		.rx = {
130 			.data = &resp,
131 			.size = sizeof(resp),
132 		},
133 	};
134 	int err;
135 
136 	err = tegra_bpmp_transfer(bpmp, &msg);
137 	if (err < 0)
138 		return err;
139 
140 	*nbytes = (size_t)resp.fop.nbytes;
141 
142 	return 0;
143 }
144 
145 static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
146 			     dma_addr_t name, size_t sz_name,
147 			     dma_addr_t data, size_t sz_data)
148 {
149 	const struct mrq_debugfs_request req = {
150 		.cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
151 		.fop = {
152 			.fnameaddr = cpu_to_le32((uint32_t)name),
153 			.fnamelen = cpu_to_le32((uint32_t)sz_name),
154 			.dataaddr = cpu_to_le32((uint32_t)data),
155 			.datalen = cpu_to_le32((uint32_t)sz_data),
156 		},
157 	};
158 	struct tegra_bpmp_message msg = {
159 		.mrq = MRQ_DEBUGFS,
160 		.tx = {
161 			.data = &req,
162 			.size = sizeof(req),
163 		},
164 	};
165 
166 	return tegra_bpmp_transfer(bpmp, &msg);
167 }
168 
169 static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
170 			       size_t size, size_t *nbytes)
171 {
172 	const struct mrq_debugfs_request req = {
173 		.cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
174 		.dumpdir = {
175 			.dataaddr = cpu_to_le32((uint32_t)addr),
176 			.datalen = cpu_to_le32((uint32_t)size),
177 		},
178 	};
179 	struct mrq_debugfs_response resp;
180 	struct tegra_bpmp_message msg = {
181 		.mrq = MRQ_DEBUGFS,
182 		.tx = {
183 			.data = &req,
184 			.size = sizeof(req),
185 		},
186 		.rx = {
187 			.data = &resp,
188 			.size = sizeof(resp),
189 		},
190 	};
191 	int err;
192 
193 	err = tegra_bpmp_transfer(bpmp, &msg);
194 	if (err < 0)
195 		return err;
196 
197 	*nbytes = (size_t)resp.dumpdir.nbytes;
198 
199 	return 0;
200 }
201 
202 static int debugfs_show(struct seq_file *m, void *p)
203 {
204 	struct file *file = m->private;
205 	struct inode *inode = file_inode(file);
206 	struct tegra_bpmp *bpmp = inode->i_private;
207 	const size_t datasize = m->size;
208 	const size_t namesize = SZ_256;
209 	void *datavirt, *namevirt;
210 	dma_addr_t dataphys, namephys;
211 	char buf[256];
212 	const char *filename;
213 	size_t len, nbytes;
214 	int ret;
215 
216 	filename = get_filename(bpmp, file, buf, sizeof(buf));
217 	if (!filename)
218 		return -ENOENT;
219 
220 	namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
221 				      GFP_KERNEL | GFP_DMA32);
222 	if (!namevirt)
223 		return -ENOMEM;
224 
225 	datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
226 				      GFP_KERNEL | GFP_DMA32);
227 	if (!datavirt) {
228 		ret = -ENOMEM;
229 		goto free_namebuf;
230 	}
231 
232 	len = strlen(filename);
233 	strncpy(namevirt, filename, namesize);
234 
235 	ret = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize,
236 			       &nbytes);
237 
238 	if (!ret)
239 		seq_write(m, datavirt, nbytes);
240 
241 	dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
242 free_namebuf:
243 	dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
244 
245 	return ret;
246 }
247 
248 static int debugfs_open(struct inode *inode, struct file *file)
249 {
250 	return single_open_size(file, debugfs_show, file, SZ_128K);
251 }
252 
253 static ssize_t debugfs_store(struct file *file, const char __user *buf,
254 		size_t count, loff_t *f_pos)
255 {
256 	struct inode *inode = file_inode(file);
257 	struct tegra_bpmp *bpmp = inode->i_private;
258 	const size_t datasize = count;
259 	const size_t namesize = SZ_256;
260 	void *datavirt, *namevirt;
261 	dma_addr_t dataphys, namephys;
262 	char fnamebuf[256];
263 	const char *filename;
264 	size_t len;
265 	int ret;
266 
267 	filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
268 	if (!filename)
269 		return -ENOENT;
270 
271 	namevirt = dma_alloc_coherent(bpmp->dev, namesize, &namephys,
272 				      GFP_KERNEL | GFP_DMA32);
273 	if (!namevirt)
274 		return -ENOMEM;
275 
276 	datavirt = dma_alloc_coherent(bpmp->dev, datasize, &dataphys,
277 				      GFP_KERNEL | GFP_DMA32);
278 	if (!datavirt) {
279 		ret = -ENOMEM;
280 		goto free_namebuf;
281 	}
282 
283 	len = strlen(filename);
284 	strncpy(namevirt, filename, namesize);
285 
286 	if (copy_from_user(datavirt, buf, count)) {
287 		ret = -EFAULT;
288 		goto free_databuf;
289 	}
290 
291 	ret = mrq_debugfs_write(bpmp, namephys, len, dataphys,
292 				count);
293 
294 free_databuf:
295 	dma_free_coherent(bpmp->dev, datasize, datavirt, dataphys);
296 free_namebuf:
297 	dma_free_coherent(bpmp->dev, namesize, namevirt, namephys);
298 
299 	return ret ?: count;
300 }
301 
302 static const struct file_operations debugfs_fops = {
303 	.open		= debugfs_open,
304 	.read		= seq_read,
305 	.llseek		= seq_lseek,
306 	.write		= debugfs_store,
307 	.release	= single_release,
308 };
309 
310 static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
311 			     struct dentry *parent, uint32_t depth)
312 {
313 	int err;
314 	uint32_t d, t;
315 	const char *name;
316 	struct dentry *dentry;
317 
318 	while (!seqbuf_eof(seqbuf)) {
319 		err = seqbuf_read_u32(seqbuf, &d);
320 		if (err < 0)
321 			return err;
322 
323 		if (d < depth) {
324 			seqbuf_seek(seqbuf, -4);
325 			/* go up a level */
326 			return 0;
327 		} else if (d != depth) {
328 			/* malformed data received from BPMP */
329 			return -EIO;
330 		}
331 
332 		err = seqbuf_read_u32(seqbuf, &t);
333 		if (err < 0)
334 			return err;
335 		err = seqbuf_read_str(seqbuf, &name);
336 		if (err < 0)
337 			return err;
338 
339 		if (t & DEBUGFS_S_ISDIR) {
340 			dentry = debugfs_create_dir(name, parent);
341 			if (!dentry)
342 				return -ENOMEM;
343 			err = bpmp_populate_dir(bpmp, seqbuf, dentry, depth+1);
344 			if (err < 0)
345 				return err;
346 		} else {
347 			umode_t mode;
348 
349 			mode = t & DEBUGFS_S_IRUSR ? S_IRUSR : 0;
350 			mode |= t & DEBUGFS_S_IWUSR ? S_IWUSR : 0;
351 			dentry = debugfs_create_file(name, mode,
352 						     parent, bpmp,
353 						     &debugfs_fops);
354 			if (!dentry)
355 				return -ENOMEM;
356 		}
357 	}
358 
359 	return 0;
360 }
361 
362 static int create_debugfs_mirror(struct tegra_bpmp *bpmp, void *buf,
363 				 size_t bufsize, struct dentry *root)
364 {
365 	struct seqbuf seqbuf;
366 	int err;
367 
368 	bpmp->debugfs_mirror = debugfs_create_dir("debug", root);
369 	if (!bpmp->debugfs_mirror)
370 		return -ENOMEM;
371 
372 	seqbuf_init(&seqbuf, buf, bufsize);
373 	err = bpmp_populate_dir(bpmp, &seqbuf, bpmp->debugfs_mirror, 0);
374 	if (err < 0) {
375 		debugfs_remove_recursive(bpmp->debugfs_mirror);
376 		bpmp->debugfs_mirror = NULL;
377 	}
378 
379 	return err;
380 }
381 
382 int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
383 {
384 	dma_addr_t phys;
385 	void *virt;
386 	const size_t sz = SZ_256K;
387 	size_t nbytes;
388 	int ret;
389 	struct dentry *root;
390 
391 	if (!tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
392 		return 0;
393 
394 	root = debugfs_create_dir("bpmp", NULL);
395 	if (!root)
396 		return -ENOMEM;
397 
398 	virt = dma_alloc_coherent(bpmp->dev, sz, &phys,
399 				  GFP_KERNEL | GFP_DMA32);
400 	if (!virt) {
401 		ret = -ENOMEM;
402 		goto out;
403 	}
404 
405 	ret = mrq_debugfs_dumpdir(bpmp, phys, sz, &nbytes);
406 	if (ret < 0)
407 		goto free;
408 
409 	ret = create_debugfs_mirror(bpmp, virt, nbytes, root);
410 free:
411 	dma_free_coherent(bpmp->dev, sz, virt, phys);
412 out:
413 	if (ret < 0)
414 		debugfs_remove(root);
415 
416 	return ret;
417 }
418