xref: /linux/drivers/accel/amdxdna/amdxdna_debugfs.c (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2026, Advanced Micro Devices, Inc.
4  */
5 
6 #include "amdxdna_cbuf.h"
7 #include "amdxdna_debugfs.h"
8 
9 #include <drm/drm_file.h>
10 #include <linux/debugfs.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/seq_file.h>
13 #include <linux/string.h>
14 #include <linux/uaccess.h>
15 
16 #define _DBGFS_FOPS(_open, _release, _write) \
17 { \
18 	.owner = THIS_MODULE, \
19 	.open = _open, \
20 	.read = seq_read, \
21 	.llseek = seq_lseek, \
22 	.release = _release, \
23 	.write = _write, \
24 }
25 
26 #define AMDXDNA_DBGFS_FOPS(_name, _show, _write) \
27 	static int amdxdna_dbgfs_##_name##_open(struct inode *inode, struct file *file) \
28 	{ \
29 		return single_open(file, _show, inode->i_private); \
30 	} \
31 	static int amdxdna_dbgfs_##_name##_release(struct inode *inode, struct file *file) \
32 	{ \
33 		return single_release(inode, file); \
34 	} \
35 	static const struct file_operations amdxdna_fops_##_name = \
36 		_DBGFS_FOPS(amdxdna_dbgfs_##_name##_open, amdxdna_dbgfs_##_name##_release, _write)
37 
38 #define AMDXDNA_DBGFS_FILE(_name, _mode) { #_name, &amdxdna_fops_##_name, _mode }
39 
40 #define file_to_xdna(file) (((struct seq_file *)(file)->private_data)->private)
41 
42 static ssize_t amdxdna_carveout_write(struct file *file, const char __user *buf,
43 				      size_t count, loff_t *ppos)
44 {
45 	struct amdxdna_dev *xdna = file_to_xdna(file);
46 	char kbuf[128];
47 	u64 size, addr;
48 	char *sep;
49 	int ret;
50 
51 	if (count == 0 || count >= sizeof(kbuf))
52 		return -EINVAL;
53 
54 	if (copy_from_user(kbuf, buf, count))
55 		return -EFAULT;
56 	kbuf[count] = '\0';
57 	strim(kbuf);
58 	XDNA_DBG(xdna, "Trying to set carveout to %s", kbuf);
59 
60 	sep = strchr(kbuf, '@');
61 	if (!sep)
62 		return -EINVAL;
63 	*sep = '\0';
64 	sep++;
65 
66 	ret = kstrtou64(kbuf, 0, &size);
67 	if (ret)
68 		return ret;
69 
70 	ret = kstrtou64(sep, 0, &addr);
71 	if (ret)
72 		return ret;
73 
74 	/* Sanity check the addr and size. */
75 	if (!size)
76 		return -EINVAL;
77 	if (!IS_ALIGNED(addr, PAGE_SIZE) || !IS_ALIGNED(size, PAGE_SIZE))
78 		return -EINVAL;
79 
80 	guard(mutex)(&xdna->dev_lock);
81 
82 	ret = amdxdna_carveout_init(xdna, addr, size);
83 	if (ret)
84 		return ret;
85 
86 	return count;
87 }
88 
89 static int amdxdna_carveout_show(struct seq_file *m, void *unused)
90 {
91 	struct amdxdna_dev *xdna = m->private;
92 	u64 addr, size;
93 
94 	guard(mutex)(&xdna->dev_lock);
95 	amdxdna_get_carveout_conf(xdna, &addr, &size);
96 	seq_printf(m, "0x%llx@0x%llx\n", size, addr);
97 	return 0;
98 }
99 
100 /*
101  * Input/output format: <carveout_size>@<carveout_address>
102  */
103 AMDXDNA_DBGFS_FOPS(carveout, amdxdna_carveout_show, amdxdna_carveout_write);
104 
105 static const struct {
106 	const char *name;
107 	const struct file_operations *fops;
108 	umode_t mode;
109 } amdxdna_dbgfs_files[] = {
110 	AMDXDNA_DBGFS_FILE(carveout, 0600),
111 };
112 
113 void amdxdna_debugfs_init(struct amdxdna_dev *xdna)
114 {
115 	struct drm_minor *minor = xdna->ddev.accel;
116 	int i;
117 
118 	/*
119 	 * It should be okay that debugfs fails to init.
120 	 * We rely on DRM framework to finish debugfs.
121 	 */
122 	for (i = 0; i < ARRAY_SIZE(amdxdna_dbgfs_files); i++) {
123 		debugfs_create_file(amdxdna_dbgfs_files[i].name,
124 				    amdxdna_dbgfs_files[i].mode,
125 				    minor->debugfs_root,
126 				    xdna,
127 				    amdxdna_dbgfs_files[i].fops);
128 	}
129 }
130