ASoC: SOF: Introduce new firmware state: SOF_FW_BOOT_READY_OK
[linux-2.6-microblaze.git] / sound / soc / sof / debug.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 //
3 // This file is provided under a dual BSD/GPLv2 license.  When using or
4 // redistributing this file, you may do so under either license.
5 //
6 // Copyright(c) 2018 Intel Corporation. All rights reserved.
7 //
8 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9 //
10 // Generic debug routines used to export DSP MMIO and memories to userspace
11 // for firmware debugging.
12 //
13
14 #include <linux/debugfs.h>
15 #include <linux/io.h>
16 #include <linux/pm_runtime.h>
17 #include <sound/sof/ext_manifest.h>
18 #include <sound/sof/debug.h>
19 #include "sof-priv.h"
20 #include "ops.h"
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 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
238 #define MAX_IPC_FLOOD_DURATION_MS 1000
239 #define MAX_IPC_FLOOD_COUNT 10000
240 #define IPC_FLOOD_TEST_RESULT_LEN 512
241
242 static int sof_debug_ipc_flood_test(struct snd_sof_dev *sdev,
243                                     struct snd_sof_dfsentry *dfse,
244                                     bool flood_duration_test,
245                                     unsigned long ipc_duration_ms,
246                                     unsigned long ipc_count)
247 {
248         struct sof_ipc_cmd_hdr hdr;
249         struct sof_ipc_reply reply;
250         u64 min_response_time = U64_MAX;
251         ktime_t start, end, test_end;
252         u64 avg_response_time = 0;
253         u64 max_response_time = 0;
254         u64 ipc_response_time;
255         int i = 0;
256         int ret;
257
258         /* configure test IPC */
259         hdr.cmd = SOF_IPC_GLB_TEST_MSG | SOF_IPC_TEST_IPC_FLOOD;
260         hdr.size = sizeof(hdr);
261
262         /* set test end time for duration flood test */
263         if (flood_duration_test)
264                 test_end = ktime_get_ns() + ipc_duration_ms * NSEC_PER_MSEC;
265
266         /* send test IPC's */
267         while (1) {
268                 start = ktime_get();
269                 ret = sof_ipc_tx_message(sdev->ipc, hdr.cmd, &hdr, hdr.size,
270                                          &reply, sizeof(reply));
271                 end = ktime_get();
272
273                 if (ret < 0)
274                         break;
275
276                 /* compute min and max response times */
277                 ipc_response_time = ktime_to_ns(ktime_sub(end, start));
278                 min_response_time = min(min_response_time, ipc_response_time);
279                 max_response_time = max(max_response_time, ipc_response_time);
280
281                 /* sum up response times */
282                 avg_response_time += ipc_response_time;
283                 i++;
284
285                 /* test complete? */
286                 if (flood_duration_test) {
287                         if (ktime_to_ns(end) >= test_end)
288                                 break;
289                 } else {
290                         if (i == ipc_count)
291                                 break;
292                 }
293         }
294
295         if (ret < 0)
296                 dev_err(sdev->dev,
297                         "error: ipc flood test failed at %d iterations\n", i);
298
299         /* return if the first IPC fails */
300         if (!i)
301                 return ret;
302
303         /* compute average response time */
304         do_div(avg_response_time, i);
305
306         /* clear previous test output */
307         memset(dfse->cache_buf, 0, IPC_FLOOD_TEST_RESULT_LEN);
308
309         if (flood_duration_test) {
310                 dev_dbg(sdev->dev, "IPC Flood test duration: %lums\n",
311                         ipc_duration_ms);
312                 snprintf(dfse->cache_buf, IPC_FLOOD_TEST_RESULT_LEN,
313                          "IPC Flood test duration: %lums\n", ipc_duration_ms);
314         }
315
316         dev_dbg(sdev->dev,
317                 "IPC Flood count: %d, Avg response time: %lluns\n",
318                 i, avg_response_time);
319         dev_dbg(sdev->dev, "Max response time: %lluns\n",
320                 max_response_time);
321         dev_dbg(sdev->dev, "Min response time: %lluns\n",
322                 min_response_time);
323
324         /* format output string */
325         snprintf(dfse->cache_buf + strlen(dfse->cache_buf),
326                  IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf),
327                  "IPC Flood count: %d\nAvg response time: %lluns\n",
328                  i, avg_response_time);
329
330         snprintf(dfse->cache_buf + strlen(dfse->cache_buf),
331                  IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf),
332                  "Max response time: %lluns\nMin response time: %lluns\n",
333                  max_response_time, min_response_time);
334
335         return ret;
336 }
337 #endif
338
339 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR)
340 static ssize_t msg_inject_read(struct file *file, char __user *buffer,
341                                size_t count, loff_t *ppos)
342 {
343         struct snd_sof_dfsentry *dfse = file->private_data;
344         struct sof_ipc_reply *rhdr = dfse->msg_inject_rx;
345
346         if (!rhdr->hdr.size || !count || *ppos)
347                 return 0;
348
349         if (count > rhdr->hdr.size)
350                 count = rhdr->hdr.size;
351
352         if (copy_to_user(buffer, dfse->msg_inject_rx, count))
353                 return -EFAULT;
354
355         *ppos += count;
356         return count;
357 }
358
359 static ssize_t msg_inject_write(struct file *file, const char __user *buffer,
360                                 size_t count, loff_t *ppos)
361 {
362         struct snd_sof_dfsentry *dfse = file->private_data;
363         struct snd_sof_dev *sdev = dfse->sdev;
364         struct sof_ipc_cmd_hdr *hdr = dfse->msg_inject_tx;
365         size_t size;
366         int ret, err;
367
368         if (*ppos)
369                 return 0;
370
371         size = simple_write_to_buffer(dfse->msg_inject_tx, SOF_IPC_MSG_MAX_SIZE,
372                                       ppos, buffer, count);
373         if (size != count)
374                 return size > 0 ? -EFAULT : size;
375
376         ret = pm_runtime_get_sync(sdev->dev);
377         if (ret < 0 && ret != -EACCES) {
378                 dev_err_ratelimited(sdev->dev, "%s: DSP resume failed: %d\n",
379                                     __func__, ret);
380                 pm_runtime_put_noidle(sdev->dev);
381                 goto out;
382         }
383
384         /* send the message */
385         memset(dfse->msg_inject_rx, 0, SOF_IPC_MSG_MAX_SIZE);
386         ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, dfse->msg_inject_tx, count,
387                                  dfse->msg_inject_rx, SOF_IPC_MSG_MAX_SIZE);
388
389         pm_runtime_mark_last_busy(sdev->dev);
390         err = pm_runtime_put_autosuspend(sdev->dev);
391         if (err < 0)
392                 dev_err_ratelimited(sdev->dev, "%s: DSP idle failed: %d\n",
393                                     __func__, err);
394
395         /* return size if test is successful */
396         if (ret >= 0)
397                 ret = size;
398
399 out:
400         return ret;
401 }
402
403 static const struct file_operations msg_inject_fops = {
404         .open = simple_open,
405         .read = msg_inject_read,
406         .write = msg_inject_write,
407         .llseek = default_llseek,
408 };
409
410 static int snd_sof_debugfs_msg_inject_item(struct snd_sof_dev *sdev,
411                                            const char *name, mode_t mode,
412                                            const struct file_operations *fops)
413 {
414         struct snd_sof_dfsentry *dfse;
415
416         dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
417         if (!dfse)
418                 return -ENOMEM;
419
420         /* pre allocate the tx and rx buffers */
421         dfse->msg_inject_tx = devm_kzalloc(sdev->dev, SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL);
422         dfse->msg_inject_rx = devm_kzalloc(sdev->dev, SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL);
423         if (!dfse->msg_inject_tx || !dfse->msg_inject_rx)
424                 return -ENOMEM;
425
426         dfse->type = SOF_DFSENTRY_TYPE_BUF;
427         dfse->sdev = sdev;
428
429         debugfs_create_file(name, mode, sdev->debugfs_root, dfse, fops);
430         /* add to dfsentry list */
431         list_add(&dfse->list, &sdev->dfsentry_list);
432
433         return 0;
434 }
435 #endif
436
437 static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer,
438                                   size_t count, loff_t *ppos)
439 {
440 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
441         struct snd_sof_dfsentry *dfse = file->private_data;
442         struct snd_sof_dev *sdev = dfse->sdev;
443         unsigned long ipc_duration_ms = 0;
444         bool flood_duration_test = false;
445         unsigned long ipc_count = 0;
446         struct dentry *dentry;
447         int err;
448 #endif
449         size_t size;
450         char *string;
451         int ret;
452
453         string = kzalloc(count+1, GFP_KERNEL);
454         if (!string)
455                 return -ENOMEM;
456
457         size = simple_write_to_buffer(string, count, ppos, buffer, count);
458         ret = size;
459
460 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
461         /*
462          * write op is only supported for ipc_flood_count or
463          * ipc_flood_duration_ms debugfs entries atm.
464          * ipc_flood_count floods the DSP with the number of IPC's specified.
465          * ipc_duration_ms test floods the DSP for the time specified
466          * in the debugfs entry.
467          */
468         dentry = file->f_path.dentry;
469         if (strcmp(dentry->d_name.name, "ipc_flood_count") &&
470             strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) {
471                 ret = -EINVAL;
472                 goto out;
473         }
474
475         if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms"))
476                 flood_duration_test = true;
477
478         /* test completion criterion */
479         if (flood_duration_test)
480                 ret = kstrtoul(string, 0, &ipc_duration_ms);
481         else
482                 ret = kstrtoul(string, 0, &ipc_count);
483         if (ret < 0)
484                 goto out;
485
486         /* limit max duration/ipc count for flood test */
487         if (flood_duration_test) {
488                 if (!ipc_duration_ms) {
489                         ret = size;
490                         goto out;
491                 }
492
493                 /* find the minimum. min() is not used to avoid warnings */
494                 if (ipc_duration_ms > MAX_IPC_FLOOD_DURATION_MS)
495                         ipc_duration_ms = MAX_IPC_FLOOD_DURATION_MS;
496         } else {
497                 if (!ipc_count) {
498                         ret = size;
499                         goto out;
500                 }
501
502                 /* find the minimum. min() is not used to avoid warnings */
503                 if (ipc_count > MAX_IPC_FLOOD_COUNT)
504                         ipc_count = MAX_IPC_FLOOD_COUNT;
505         }
506
507         ret = pm_runtime_get_sync(sdev->dev);
508         if (ret < 0 && ret != -EACCES) {
509                 dev_err_ratelimited(sdev->dev,
510                                     "error: debugfs write failed to resume %d\n",
511                                     ret);
512                 pm_runtime_put_noidle(sdev->dev);
513                 goto out;
514         }
515
516         /* flood test */
517         ret = sof_debug_ipc_flood_test(sdev, dfse, flood_duration_test,
518                                        ipc_duration_ms, ipc_count);
519
520         pm_runtime_mark_last_busy(sdev->dev);
521         err = pm_runtime_put_autosuspend(sdev->dev);
522         if (err < 0)
523                 dev_err_ratelimited(sdev->dev,
524                                     "error: debugfs write failed to idle %d\n",
525                                     err);
526
527         /* return size if test is successful */
528         if (ret >= 0)
529                 ret = size;
530 out:
531 #endif
532         kfree(string);
533         return ret;
534 }
535
536 static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer,
537                                  size_t count, loff_t *ppos)
538 {
539         struct snd_sof_dfsentry *dfse = file->private_data;
540         struct snd_sof_dev *sdev = dfse->sdev;
541         loff_t pos = *ppos;
542         size_t size_ret;
543         int skip = 0;
544         int size;
545         u8 *buf;
546
547 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
548         struct dentry *dentry;
549
550         dentry = file->f_path.dentry;
551         if ((!strcmp(dentry->d_name.name, "ipc_flood_count") ||
552              !strcmp(dentry->d_name.name, "ipc_flood_duration_ms"))) {
553                 if (*ppos)
554                         return 0;
555
556                 count = strlen(dfse->cache_buf);
557                 size_ret = copy_to_user(buffer, dfse->cache_buf, count);
558                 if (size_ret)
559                         return -EFAULT;
560
561                 *ppos += count;
562                 return count;
563         }
564 #endif
565         size = dfse->size;
566
567         /* validate position & count */
568         if (pos < 0)
569                 return -EINVAL;
570         if (pos >= size || !count)
571                 return 0;
572         /* find the minimum. min() is not used since it adds sparse warnings */
573         if (count > size - pos)
574                 count = size - pos;
575
576         /* align io read start to u32 multiple */
577         pos = ALIGN_DOWN(pos, 4);
578
579         /* intermediate buffer size must be u32 multiple */
580         size = ALIGN(count, 4);
581
582         /* if start position is unaligned, read extra u32 */
583         if (unlikely(pos != *ppos)) {
584                 skip = *ppos - pos;
585                 if (pos + size + 4 < dfse->size)
586                         size += 4;
587         }
588
589         buf = kzalloc(size, GFP_KERNEL);
590         if (!buf)
591                 return -ENOMEM;
592
593         if (dfse->type == SOF_DFSENTRY_TYPE_IOMEM) {
594 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
595                 /*
596                  * If the DSP is active: copy from IO.
597                  * If the DSP is suspended:
598                  *      - Copy from IO if the memory is always accessible.
599                  *      - Otherwise, copy from cached buffer.
600                  */
601                 if (pm_runtime_active(sdev->dev) ||
602                     dfse->access_type == SOF_DEBUGFS_ACCESS_ALWAYS) {
603                         memcpy_fromio(buf, dfse->io_mem + pos, size);
604                 } else {
605                         dev_info(sdev->dev,
606                                  "Copying cached debugfs data\n");
607                         memcpy(buf, dfse->cache_buf + pos, size);
608                 }
609 #else
610                 /* if the DSP is in D3 */
611                 if (!pm_runtime_active(sdev->dev) &&
612                     dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) {
613                         dev_err(sdev->dev,
614                                 "error: debugfs entry cannot be read in DSP D3\n");
615                         kfree(buf);
616                         return -EINVAL;
617                 }
618
619                 memcpy_fromio(buf, dfse->io_mem + pos, size);
620 #endif
621         } else {
622                 memcpy(buf, ((u8 *)(dfse->buf) + pos), size);
623         }
624
625         /* copy to userspace */
626         size_ret = copy_to_user(buffer, buf + skip, count);
627
628         kfree(buf);
629
630         /* update count & position if copy succeeded */
631         if (size_ret)
632                 return -EFAULT;
633
634         *ppos = pos + count;
635
636         return count;
637 }
638
639 static const struct file_operations sof_dfs_fops = {
640         .open = simple_open,
641         .read = sof_dfsentry_read,
642         .llseek = default_llseek,
643         .write = sof_dfsentry_write,
644 };
645
646 /* create FS entry for debug files that can expose DSP memories, registers */
647 static int snd_sof_debugfs_io_item(struct snd_sof_dev *sdev,
648                                    void __iomem *base, size_t size,
649                                    const char *name,
650                                    enum sof_debugfs_access_type access_type)
651 {
652         struct snd_sof_dfsentry *dfse;
653
654         if (!sdev)
655                 return -EINVAL;
656
657         dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
658         if (!dfse)
659                 return -ENOMEM;
660
661         dfse->type = SOF_DFSENTRY_TYPE_IOMEM;
662         dfse->io_mem = base;
663         dfse->size = size;
664         dfse->sdev = sdev;
665         dfse->access_type = access_type;
666
667 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
668         /*
669          * allocate cache buffer that will be used to save the mem window
670          * contents prior to suspend
671          */
672         if (access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) {
673                 dfse->cache_buf = devm_kzalloc(sdev->dev, size, GFP_KERNEL);
674                 if (!dfse->cache_buf)
675                         return -ENOMEM;
676         }
677 #endif
678
679         debugfs_create_file(name, 0444, sdev->debugfs_root, dfse,
680                             &sof_dfs_fops);
681
682         /* add to dfsentry list */
683         list_add(&dfse->list, &sdev->dfsentry_list);
684
685         return 0;
686 }
687
688 int snd_sof_debugfs_add_region_item_iomem(struct snd_sof_dev *sdev,
689                                           enum snd_sof_fw_blk_type blk_type, u32 offset,
690                                           size_t size, const char *name,
691                                           enum sof_debugfs_access_type access_type)
692 {
693         int bar = snd_sof_dsp_get_bar_index(sdev, blk_type);
694
695         if (bar < 0)
696                 return bar;
697
698         return snd_sof_debugfs_io_item(sdev, sdev->bar[bar] + offset, size, name,
699                                        access_type);
700 }
701 EXPORT_SYMBOL_GPL(snd_sof_debugfs_add_region_item_iomem);
702
703 /* create FS entry for debug files to expose kernel memory */
704 int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev,
705                              void *base, size_t size,
706                              const char *name, mode_t mode)
707 {
708         struct snd_sof_dfsentry *dfse;
709
710         if (!sdev)
711                 return -EINVAL;
712
713         dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
714         if (!dfse)
715                 return -ENOMEM;
716
717         dfse->type = SOF_DFSENTRY_TYPE_BUF;
718         dfse->buf = base;
719         dfse->size = size;
720         dfse->sdev = sdev;
721
722 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
723         if (!strncmp(name, "ipc_flood", strlen("ipc_flood"))) {
724                 /*
725                  * cache_buf is unused for SOF_DFSENTRY_TYPE_BUF debugfs entries.
726                  * So, use it to save the results of the last IPC flood test.
727                  */
728                 dfse->cache_buf = devm_kzalloc(sdev->dev, IPC_FLOOD_TEST_RESULT_LEN,
729                                                GFP_KERNEL);
730                 if (!dfse->cache_buf)
731                         return -ENOMEM;
732         }
733 #endif
734
735         debugfs_create_file(name, mode, sdev->debugfs_root, dfse,
736                             &sof_dfs_fops);
737         /* add to dfsentry list */
738         list_add(&dfse->list, &sdev->dfsentry_list);
739
740         return 0;
741 }
742 EXPORT_SYMBOL_GPL(snd_sof_debugfs_buf_item);
743
744 static int memory_info_update(struct snd_sof_dev *sdev, char *buf, size_t buff_size)
745 {
746         struct sof_ipc_cmd_hdr msg = {
747                 .size = sizeof(struct sof_ipc_cmd_hdr),
748                 .cmd = SOF_IPC_GLB_DEBUG | SOF_IPC_DEBUG_MEM_USAGE,
749         };
750         struct sof_ipc_dbg_mem_usage *reply;
751         int len;
752         int ret;
753         int i;
754
755         reply = kmalloc(SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL);
756         if (!reply)
757                 return -ENOMEM;
758
759         ret = pm_runtime_get_sync(sdev->dev);
760         if (ret < 0 && ret != -EACCES) {
761                 pm_runtime_put_noidle(sdev->dev);
762                 dev_err(sdev->dev, "error: enabling device failed: %d\n", ret);
763                 goto error;
764         }
765
766         ret = sof_ipc_tx_message(sdev->ipc, msg.cmd, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE);
767         pm_runtime_mark_last_busy(sdev->dev);
768         pm_runtime_put_autosuspend(sdev->dev);
769         if (ret < 0 || reply->rhdr.error < 0) {
770                 ret = min(ret, reply->rhdr.error);
771                 dev_err(sdev->dev, "error: reading memory info failed, %d\n", ret);
772                 goto error;
773         }
774
775         if (struct_size(reply, elems, reply->num_elems) != reply->rhdr.hdr.size) {
776                 dev_err(sdev->dev, "error: invalid memory info ipc struct size, %d\n",
777                         reply->rhdr.hdr.size);
778                 ret = -EINVAL;
779                 goto error;
780         }
781
782         for (i = 0, len = 0; i < reply->num_elems; i++) {
783                 ret = snprintf(buf + len, buff_size - len, "zone %d.%d used %#8x free %#8x\n",
784                                reply->elems[i].zone, reply->elems[i].id,
785                                reply->elems[i].used, reply->elems[i].free);
786                 if (ret < 0)
787                         goto error;
788                 len += ret;
789         }
790
791         ret = len;
792 error:
793         kfree(reply);
794         return ret;
795 }
796
797 static ssize_t memory_info_read(struct file *file, char __user *to, size_t count, loff_t *ppos)
798 {
799         struct snd_sof_dfsentry *dfse = file->private_data;
800         struct snd_sof_dev *sdev = dfse->sdev;
801         int data_length;
802
803         /* read memory info from FW only once for each file read */
804         if (!*ppos) {
805                 dfse->buf_data_size = 0;
806                 data_length = memory_info_update(sdev, dfse->buf, dfse->size);
807                 if (data_length < 0)
808                         return data_length;
809                 dfse->buf_data_size = data_length;
810         }
811
812         return simple_read_from_buffer(to, count, ppos, dfse->buf, dfse->buf_data_size);
813 }
814
815 static int memory_info_open(struct inode *inode, struct file *file)
816 {
817         struct snd_sof_dfsentry *dfse = inode->i_private;
818         struct snd_sof_dev *sdev = dfse->sdev;
819
820         file->private_data = dfse;
821
822         /* allocate buffer memory only in first open run, to save memory when unused */
823         if (!dfse->buf) {
824                 dfse->buf = devm_kmalloc(sdev->dev, PAGE_SIZE, GFP_KERNEL);
825                 if (!dfse->buf)
826                         return -ENOMEM;
827                 dfse->size = PAGE_SIZE;
828         }
829
830         return 0;
831 }
832
833 static const struct file_operations memory_info_fops = {
834         .open = memory_info_open,
835         .read = memory_info_read,
836         .llseek = default_llseek,
837 };
838
839 int snd_sof_dbg_memory_info_init(struct snd_sof_dev *sdev)
840 {
841         struct snd_sof_dfsentry *dfse;
842
843         dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
844         if (!dfse)
845                 return -ENOMEM;
846
847         /* don't allocate buffer before first usage, to save memory when unused */
848         dfse->type = SOF_DFSENTRY_TYPE_BUF;
849         dfse->sdev = sdev;
850
851         debugfs_create_file("memory_info", 0444, sdev->debugfs_root, dfse, &memory_info_fops);
852
853         /* add to dfsentry list */
854         list_add(&dfse->list, &sdev->dfsentry_list);
855         return 0;
856 }
857 EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init);
858
859 int snd_sof_dbg_init(struct snd_sof_dev *sdev)
860 {
861         const struct snd_sof_dsp_ops *ops = sof_ops(sdev);
862         const struct snd_sof_debugfs_map *map;
863         int i;
864         int err;
865
866         /* use "sof" as top level debugFS dir */
867         sdev->debugfs_root = debugfs_create_dir("sof", NULL);
868
869         /* init dfsentry list */
870         INIT_LIST_HEAD(&sdev->dfsentry_list);
871
872         /* create debugFS files for platform specific MMIO/DSP memories */
873         for (i = 0; i < ops->debug_map_count; i++) {
874                 map = &ops->debug_map[i];
875
876                 err = snd_sof_debugfs_io_item(sdev, sdev->bar[map->bar] +
877                                               map->offset, map->size,
878                                               map->name, map->access_type);
879                 /* errors are only due to memory allocation, not debugfs */
880                 if (err < 0)
881                         return err;
882         }
883
884 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
885         err = snd_sof_debugfs_probe_item(sdev, "probe_points",
886                         0644, &probe_points_fops);
887         if (err < 0)
888                 return err;
889         err = snd_sof_debugfs_probe_item(sdev, "probe_points_remove",
890                         0200, &probe_points_remove_fops);
891         if (err < 0)
892                 return err;
893 #endif
894
895 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
896         /* create read-write ipc_flood_count debugfs entry */
897         err = snd_sof_debugfs_buf_item(sdev, NULL, 0,
898                                        "ipc_flood_count", 0666);
899
900         /* errors are only due to memory allocation, not debugfs */
901         if (err < 0)
902                 return err;
903
904         /* create read-write ipc_flood_duration_ms debugfs entry */
905         err = snd_sof_debugfs_buf_item(sdev, NULL, 0,
906                                        "ipc_flood_duration_ms", 0666);
907
908         /* errors are only due to memory allocation, not debugfs */
909         if (err < 0)
910                 return err;
911 #endif
912
913 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR)
914         err = snd_sof_debugfs_msg_inject_item(sdev, "ipc_msg_inject", 0644,
915                                               &msg_inject_fops);
916
917         /* errors are only due to memory allocation, not debugfs */
918         if (err < 0)
919                 return err;
920 #endif
921
922         return 0;
923 }
924 EXPORT_SYMBOL_GPL(snd_sof_dbg_init);
925
926 void snd_sof_free_debug(struct snd_sof_dev *sdev)
927 {
928         debugfs_remove_recursive(sdev->debugfs_root);
929 }
930 EXPORT_SYMBOL_GPL(snd_sof_free_debug);
931
932 static const struct soc_fw_state_info {
933         enum snd_sof_fw_state state;
934         const char *name;
935 } fw_state_dbg[] = {
936         {SOF_FW_BOOT_NOT_STARTED, "SOF_FW_BOOT_NOT_STARTED"},
937         {SOF_FW_BOOT_PREPARE, "SOF_FW_BOOT_PREPARE"},
938         {SOF_FW_BOOT_IN_PROGRESS, "SOF_FW_BOOT_IN_PROGRESS"},
939         {SOF_FW_BOOT_FAILED, "SOF_FW_BOOT_FAILED"},
940         {SOF_FW_BOOT_READY_FAILED, "SOF_FW_BOOT_READY_FAILED"},
941         {SOF_FW_BOOT_READY_OK, "SOF_FW_BOOT_READY_OK"},
942         {SOF_FW_BOOT_COMPLETE, "SOF_FW_BOOT_COMPLETE"},
943         {SOF_FW_CRASHED, "SOF_FW_CRASHED"},
944 };
945
946 static void snd_sof_dbg_print_fw_state(struct snd_sof_dev *sdev)
947 {
948         int i;
949
950         for (i = 0; i < ARRAY_SIZE(fw_state_dbg); i++) {
951                 if (sdev->fw_state == fw_state_dbg[i].state) {
952                         dev_err(sdev->dev, "fw_state: %s (%d)\n", fw_state_dbg[i].name, i);
953                         return;
954                 }
955         }
956
957         dev_err(sdev->dev, "fw_state: UNKNOWN (%d)\n", sdev->fw_state);
958 }
959
960 void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, const char *msg, u32 flags)
961 {
962         bool print_all = sof_debug_check_flag(SOF_DBG_PRINT_ALL_DUMPS);
963
964         if (flags & SOF_DBG_DUMP_OPTIONAL && !print_all)
965                 return;
966
967         if (sof_ops(sdev)->dbg_dump && !sdev->dbg_dump_printed) {
968                 dev_err(sdev->dev, "------------[ DSP dump start ]------------\n");
969                 if (msg)
970                         dev_err(sdev->dev, "%s\n", msg);
971                 snd_sof_dbg_print_fw_state(sdev);
972                 sof_ops(sdev)->dbg_dump(sdev, flags);
973                 dev_err(sdev->dev, "------------[ DSP dump end ]------------\n");
974                 if (!print_all)
975                         sdev->dbg_dump_printed = true;
976         } else if (msg) {
977                 dev_err(sdev->dev, "%s\n", msg);
978         }
979 }
980 EXPORT_SYMBOL(snd_sof_dsp_dbg_dump);
981
982 static void snd_sof_ipc_dump(struct snd_sof_dev *sdev)
983 {
984         if (sof_ops(sdev)->ipc_dump  && !sdev->ipc_dump_printed) {
985                 dev_err(sdev->dev, "------------[ IPC dump start ]------------\n");
986                 sof_ops(sdev)->ipc_dump(sdev);
987                 dev_err(sdev->dev, "------------[ IPC dump end ]------------\n");
988                 if (!sof_debug_check_flag(SOF_DBG_PRINT_ALL_DUMPS))
989                         sdev->ipc_dump_printed = true;
990         }
991 }
992
993 void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev)
994 {
995         if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT) ||
996             sof_debug_check_flag(SOF_DBG_RETAIN_CTX)) {
997                 /* should we prevent DSP entering D3 ? */
998                 if (!sdev->ipc_dump_printed)
999                         dev_info(sdev->dev,
1000                                  "preventing DSP entering D3 state to preserve context\n");
1001                 pm_runtime_get_noresume(sdev->dev);
1002         }
1003
1004         /* dump vital information to the logs */
1005         snd_sof_ipc_dump(sdev);
1006         snd_sof_dsp_dbg_dump(sdev, "Firmware exception",
1007                              SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
1008         snd_sof_trace_notify_for_error(sdev);
1009 }
1010 EXPORT_SYMBOL(snd_sof_handle_fw_exception);