|
19 | 19 | #include "sof-priv.h" |
20 | 20 | #include "ops.h" |
21 | 21 |
|
22 | | -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) |
23 | | -#include "sof-probes.h" |
24 | | - |
25 | | -/** |
26 | | - * strsplit_u32 - Split string into sequence of u32 tokens |
27 | | - * @buf: String to split into tokens. |
28 | | - * @delim: String containing delimiter characters. |
29 | | - * @tkns: Returned u32 sequence pointer. |
30 | | - * @num_tkns: Returned number of tokens obtained. |
31 | | - */ |
32 | | -static int |
33 | | -strsplit_u32(char **buf, const char *delim, u32 **tkns, size_t *num_tkns) |
34 | | -{ |
35 | | - char *s; |
36 | | - u32 *data, *tmp; |
37 | | - size_t count = 0; |
38 | | - size_t cap = 32; |
39 | | - int ret = 0; |
40 | | - |
41 | | - *tkns = NULL; |
42 | | - *num_tkns = 0; |
43 | | - data = kcalloc(cap, sizeof(*data), GFP_KERNEL); |
44 | | - if (!data) |
45 | | - return -ENOMEM; |
46 | | - |
47 | | - while ((s = strsep(buf, delim)) != NULL) { |
48 | | - ret = kstrtouint(s, 0, data + count); |
49 | | - if (ret) |
50 | | - goto exit; |
51 | | - if (++count >= cap) { |
52 | | - cap *= 2; |
53 | | - tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL); |
54 | | - if (!tmp) { |
55 | | - ret = -ENOMEM; |
56 | | - goto exit; |
57 | | - } |
58 | | - data = tmp; |
59 | | - } |
60 | | - } |
61 | | - |
62 | | - if (!count) |
63 | | - goto exit; |
64 | | - *tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL); |
65 | | - if (*tkns == NULL) { |
66 | | - ret = -ENOMEM; |
67 | | - goto exit; |
68 | | - } |
69 | | - *num_tkns = count; |
70 | | - |
71 | | -exit: |
72 | | - kfree(data); |
73 | | - return ret; |
74 | | -} |
75 | | - |
76 | | -static int tokenize_input(const char __user *from, size_t count, |
77 | | - loff_t *ppos, u32 **tkns, size_t *num_tkns) |
78 | | -{ |
79 | | - char *buf; |
80 | | - int ret; |
81 | | - |
82 | | - buf = kmalloc(count + 1, GFP_KERNEL); |
83 | | - if (!buf) |
84 | | - return -ENOMEM; |
85 | | - |
86 | | - ret = simple_write_to_buffer(buf, count, ppos, from, count); |
87 | | - if (ret != count) { |
88 | | - ret = ret >= 0 ? -EIO : ret; |
89 | | - goto exit; |
90 | | - } |
91 | | - |
92 | | - buf[count] = '\0'; |
93 | | - ret = strsplit_u32((char **)&buf, ",", tkns, num_tkns); |
94 | | -exit: |
95 | | - kfree(buf); |
96 | | - return ret; |
97 | | -} |
98 | | - |
99 | | -static ssize_t probe_points_read(struct file *file, |
100 | | - char __user *to, size_t count, loff_t *ppos) |
101 | | -{ |
102 | | - struct snd_sof_dfsentry *dfse = file->private_data; |
103 | | - struct snd_sof_dev *sdev = dfse->sdev; |
104 | | - struct sof_probe_point_desc *desc; |
105 | | - size_t num_desc, len = 0; |
106 | | - char *buf; |
107 | | - int i, ret; |
108 | | - |
109 | | - if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { |
110 | | - dev_warn(sdev->dev, "no extractor stream running\n"); |
111 | | - return -ENOENT; |
112 | | - } |
113 | | - |
114 | | - buf = kzalloc(PAGE_SIZE, GFP_KERNEL); |
115 | | - if (!buf) |
116 | | - return -ENOMEM; |
117 | | - |
118 | | - ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc); |
119 | | - if (ret < 0) |
120 | | - goto exit; |
121 | | - |
122 | | - for (i = 0; i < num_desc; i++) { |
123 | | - ret = snprintf(buf + len, PAGE_SIZE - len, |
124 | | - "Id: %#010x Purpose: %d Node id: %#x\n", |
125 | | - desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag); |
126 | | - if (ret < 0) |
127 | | - goto free_desc; |
128 | | - len += ret; |
129 | | - } |
130 | | - |
131 | | - ret = simple_read_from_buffer(to, count, ppos, buf, len); |
132 | | -free_desc: |
133 | | - kfree(desc); |
134 | | -exit: |
135 | | - kfree(buf); |
136 | | - return ret; |
137 | | -} |
138 | | - |
139 | | -static ssize_t probe_points_write(struct file *file, |
140 | | - const char __user *from, size_t count, loff_t *ppos) |
141 | | -{ |
142 | | - struct snd_sof_dfsentry *dfse = file->private_data; |
143 | | - struct snd_sof_dev *sdev = dfse->sdev; |
144 | | - struct sof_probe_point_desc *desc; |
145 | | - size_t num_tkns, bytes; |
146 | | - u32 *tkns; |
147 | | - int ret; |
148 | | - |
149 | | - if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { |
150 | | - dev_warn(sdev->dev, "no extractor stream running\n"); |
151 | | - return -ENOENT; |
152 | | - } |
153 | | - |
154 | | - ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); |
155 | | - if (ret < 0) |
156 | | - return ret; |
157 | | - bytes = sizeof(*tkns) * num_tkns; |
158 | | - if (!num_tkns || (bytes % sizeof(*desc))) { |
159 | | - ret = -EINVAL; |
160 | | - goto exit; |
161 | | - } |
162 | | - |
163 | | - desc = (struct sof_probe_point_desc *)tkns; |
164 | | - ret = sof_ipc_probe_points_add(sdev, |
165 | | - desc, bytes / sizeof(*desc)); |
166 | | - if (!ret) |
167 | | - ret = count; |
168 | | -exit: |
169 | | - kfree(tkns); |
170 | | - return ret; |
171 | | -} |
172 | | - |
173 | | -static const struct file_operations probe_points_fops = { |
174 | | - .open = simple_open, |
175 | | - .read = probe_points_read, |
176 | | - .write = probe_points_write, |
177 | | - .llseek = default_llseek, |
178 | | -}; |
179 | | - |
180 | | -static ssize_t probe_points_remove_write(struct file *file, |
181 | | - const char __user *from, size_t count, loff_t *ppos) |
182 | | -{ |
183 | | - struct snd_sof_dfsentry *dfse = file->private_data; |
184 | | - struct snd_sof_dev *sdev = dfse->sdev; |
185 | | - size_t num_tkns; |
186 | | - u32 *tkns; |
187 | | - int ret; |
188 | | - |
189 | | - if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) { |
190 | | - dev_warn(sdev->dev, "no extractor stream running\n"); |
191 | | - return -ENOENT; |
192 | | - } |
193 | | - |
194 | | - ret = tokenize_input(from, count, ppos, &tkns, &num_tkns); |
195 | | - if (ret < 0) |
196 | | - return ret; |
197 | | - if (!num_tkns) { |
198 | | - ret = -EINVAL; |
199 | | - goto exit; |
200 | | - } |
201 | | - |
202 | | - ret = sof_ipc_probe_points_remove(sdev, tkns, num_tkns); |
203 | | - if (!ret) |
204 | | - ret = count; |
205 | | -exit: |
206 | | - kfree(tkns); |
207 | | - return ret; |
208 | | -} |
209 | | - |
210 | | -static const struct file_operations probe_points_remove_fops = { |
211 | | - .open = simple_open, |
212 | | - .write = probe_points_remove_write, |
213 | | - .llseek = default_llseek, |
214 | | -}; |
215 | | - |
216 | | -static int snd_sof_debugfs_probe_item(struct snd_sof_dev *sdev, |
217 | | - const char *name, mode_t mode, |
218 | | - const struct file_operations *fops) |
219 | | -{ |
220 | | - struct snd_sof_dfsentry *dfse; |
221 | | - |
222 | | - dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL); |
223 | | - if (!dfse) |
224 | | - return -ENOMEM; |
225 | | - |
226 | | - dfse->type = SOF_DFSENTRY_TYPE_BUF; |
227 | | - dfse->sdev = sdev; |
228 | | - |
229 | | - debugfs_create_file(name, mode, sdev->debugfs_root, dfse, fops); |
230 | | - /* add to dfsentry list */ |
231 | | - list_add(&dfse->list, &sdev->dfsentry_list); |
232 | | - |
233 | | - return 0; |
234 | | -} |
235 | | -#endif |
236 | | - |
237 | 22 | static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, |
238 | 23 | size_t count, loff_t *ppos) |
239 | 24 | { |
@@ -569,17 +354,6 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) |
569 | 354 | return err; |
570 | 355 | } |
571 | 356 |
|
572 | | -#if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES) |
573 | | - err = snd_sof_debugfs_probe_item(sdev, "probe_points", |
574 | | - 0644, &probe_points_fops); |
575 | | - if (err < 0) |
576 | | - return err; |
577 | | - err = snd_sof_debugfs_probe_item(sdev, "probe_points_remove", |
578 | | - 0200, &probe_points_remove_fops); |
579 | | - if (err < 0) |
580 | | - return err; |
581 | | -#endif |
582 | | - |
583 | 357 | return 0; |
584 | 358 | } |
585 | 359 | EXPORT_SYMBOL_GPL(snd_sof_dbg_init); |
|
0 commit comments