^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // This file is provided under a dual BSD/GPLv2 license. When using or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) // redistributing this file, you may do so under either license.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Copyright(c) 2018 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) // Generic debug routines used to export DSP MMIO and memories to userspace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) // for firmware debugging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "sof-priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ops.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "probe.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * strsplit_u32 - Split string into sequence of u32 tokens
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * @buf: String to split into tokens.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * @delim: String containing delimiter characters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @tkns: Returned u32 sequence pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @num_tkns: Returned number of tokens obtained.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) strsplit_u32(char **buf, const char *delim, u32 **tkns, size_t *num_tkns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) char *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 *data, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) size_t count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) size_t cap = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *tkns = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *num_tkns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) data = kcalloc(cap, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) while ((s = strsep(buf, delim)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ret = kstrtouint(s, 0, data + count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (++count >= cap) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) cap *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) tmp = krealloc(data, cap * sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (!tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) data = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (!count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *tkns = kmemdup(data, count * sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (*tkns == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *num_tkns = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int tokenize_input(const char __user *from, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) loff_t *ppos, u32 **tkns, size_t *num_tkns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) buf = kmalloc(count + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ret = simple_write_to_buffer(buf, count, ppos, from, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (ret != count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ret = ret >= 0 ? -EIO : ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) buf[count] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ret = strsplit_u32((char **)&buf, ",", tkns, num_tkns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static ssize_t probe_points_read(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) char __user *to, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct snd_sof_dfsentry *dfse = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct snd_sof_dev *sdev = dfse->sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct sof_probe_point_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) size_t num_desc, len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev_warn(sdev->dev, "no extractor stream running\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ret = sof_ipc_probe_points_info(sdev, &desc, &num_desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) for (i = 0; i < num_desc; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) ret = snprintf(buf + len, PAGE_SIZE - len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) "Id: %#010x Purpose: %d Node id: %#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) desc[i].buffer_id, desc[i].purpose, desc[i].stream_tag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) goto free_desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) len += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ret = simple_read_from_buffer(to, count, ppos, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) free_desc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) kfree(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static ssize_t probe_points_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) const char __user *from, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct snd_sof_dfsentry *dfse = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct snd_sof_dev *sdev = dfse->sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct sof_probe_point_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) size_t num_tkns, bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u32 *tkns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev_warn(sdev->dev, "no extractor stream running\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ret = tokenize_input(from, count, ppos, &tkns, &num_tkns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) bytes = sizeof(*tkns) * num_tkns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!num_tkns || (bytes % sizeof(*desc))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) desc = (struct sof_probe_point_desc *)tkns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ret = sof_ipc_probe_points_add(sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) desc, bytes / sizeof(*desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) kfree(tkns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static const struct file_operations probe_points_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .read = probe_points_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .write = probe_points_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static ssize_t probe_points_remove_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) const char __user *from, size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct snd_sof_dfsentry *dfse = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct snd_sof_dev *sdev = dfse->sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) size_t num_tkns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) u32 *tkns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (sdev->extractor_stream_tag == SOF_PROBE_INVALID_NODE_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) dev_warn(sdev->dev, "no extractor stream running\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) ret = tokenize_input(from, count, ppos, &tkns, &num_tkns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (!num_tkns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) ret = sof_ipc_probe_points_remove(sdev, tkns, num_tkns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) kfree(tkns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static const struct file_operations probe_points_remove_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .write = probe_points_remove_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static int snd_sof_debugfs_probe_item(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) const char *name, mode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) const struct file_operations *fops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct snd_sof_dfsentry *dfse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (!dfse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) dfse->type = SOF_DFSENTRY_TYPE_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) dfse->sdev = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) debugfs_create_file(name, mode, sdev->debugfs_root, dfse, fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* add to dfsentry list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) list_add(&dfse->list, &sdev->dfsentry_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define MAX_IPC_FLOOD_DURATION_MS 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) #define MAX_IPC_FLOOD_COUNT 10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) #define IPC_FLOOD_TEST_RESULT_LEN 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static int sof_debug_ipc_flood_test(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct snd_sof_dfsentry *dfse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) bool flood_duration_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) unsigned long ipc_duration_ms,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) unsigned long ipc_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct sof_ipc_cmd_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct sof_ipc_reply reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) u64 min_response_time = U64_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ktime_t start, end, test_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) u64 avg_response_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) u64 max_response_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) u64 ipc_response_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /* configure test IPC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) hdr.cmd = SOF_IPC_GLB_TEST_MSG | SOF_IPC_TEST_IPC_FLOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) hdr.size = sizeof(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /* set test end time for duration flood test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if (flood_duration_test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) test_end = ktime_get_ns() + ipc_duration_ms * NSEC_PER_MSEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* send test IPC's */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) start = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) ret = sof_ipc_tx_message(sdev->ipc, hdr.cmd, &hdr, hdr.size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) &reply, sizeof(reply));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) end = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* compute min and max response times */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ipc_response_time = ktime_to_ns(ktime_sub(end, start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) min_response_time = min(min_response_time, ipc_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) max_response_time = max(max_response_time, ipc_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* sum up response times */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) avg_response_time += ipc_response_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* test complete? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (flood_duration_test) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (ktime_to_ns(end) >= test_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (i == ipc_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dev_err(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) "error: ipc flood test failed at %d iterations\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /* return if the first IPC fails */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* compute average response time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) do_div(avg_response_time, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* clear previous test output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) memset(dfse->cache_buf, 0, IPC_FLOOD_TEST_RESULT_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (flood_duration_test) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) dev_dbg(sdev->dev, "IPC Flood test duration: %lums\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) ipc_duration_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) snprintf(dfse->cache_buf, IPC_FLOOD_TEST_RESULT_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) "IPC Flood test duration: %lums\n", ipc_duration_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) dev_dbg(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) "IPC Flood count: %d, Avg response time: %lluns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) i, avg_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) dev_dbg(sdev->dev, "Max response time: %lluns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) max_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) dev_dbg(sdev->dev, "Min response time: %lluns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) min_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* format output string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) snprintf(dfse->cache_buf + strlen(dfse->cache_buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "IPC Flood count: %d\nAvg response time: %lluns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) i, avg_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) snprintf(dfse->cache_buf + strlen(dfse->cache_buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) IPC_FLOOD_TEST_RESULT_LEN - strlen(dfse->cache_buf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) "Max response time: %lluns\nMin response time: %lluns\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) max_response_time, min_response_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) struct snd_sof_dfsentry *dfse = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) struct snd_sof_dev *sdev = dfse->sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) unsigned long ipc_duration_ms = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) bool flood_duration_test = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) unsigned long ipc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) char *string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) string = kzalloc(count+1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (!string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) size = simple_write_to_buffer(string, count, ppos, buffer, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ret = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * write op is only supported for ipc_flood_count or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * ipc_flood_duration_ms debugfs entries atm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * ipc_flood_count floods the DSP with the number of IPC's specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * ipc_duration_ms test floods the DSP for the time specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * in the debugfs entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dentry = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (strcmp(dentry->d_name.name, "ipc_flood_count") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!strcmp(dentry->d_name.name, "ipc_flood_duration_ms"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) flood_duration_test = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* test completion criterion */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (flood_duration_test)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) ret = kstrtoul(string, 0, &ipc_duration_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret = kstrtoul(string, 0, &ipc_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* limit max duration/ipc count for flood test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (flood_duration_test) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (!ipc_duration_ms) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) ret = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* find the minimum. min() is not used to avoid warnings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (ipc_duration_ms > MAX_IPC_FLOOD_DURATION_MS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) ipc_duration_ms = MAX_IPC_FLOOD_DURATION_MS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!ipc_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ret = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* find the minimum. min() is not used to avoid warnings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (ipc_count > MAX_IPC_FLOOD_COUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ipc_count = MAX_IPC_FLOOD_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ret = pm_runtime_get_sync(sdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (ret < 0 && ret != -EACCES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dev_err_ratelimited(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) "error: debugfs write failed to resume %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pm_runtime_put_noidle(sdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* flood test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) ret = sof_debug_ipc_flood_test(sdev, dfse, flood_duration_test,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ipc_duration_ms, ipc_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) pm_runtime_mark_last_busy(sdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) err = pm_runtime_put_autosuspend(sdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) dev_err_ratelimited(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) "error: debugfs write failed to idle %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* return size if test is successful */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (ret >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ret = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) kfree(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct snd_sof_dfsentry *dfse = file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct snd_sof_dev *sdev = dfse->sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) loff_t pos = *ppos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) size_t size_ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int skip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) dentry = file->f_path.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if ((!strcmp(dentry->d_name.name, "ipc_flood_count") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) !strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dfse->cache_buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (*ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) count = strlen(dfse->cache_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) size_ret = copy_to_user(buffer, dfse->cache_buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (size_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) *ppos += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) size = dfse->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* validate position & count */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (pos < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (pos >= size || !count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* find the minimum. min() is not used since it adds sparse warnings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (count > size - pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) count = size - pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* align io read start to u32 multiple */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) pos = ALIGN_DOWN(pos, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* intermediate buffer size must be u32 multiple */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) size = ALIGN(count, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* if start position is unaligned, read extra u32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (unlikely(pos != *ppos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) skip = *ppos - pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (pos + size + 4 < dfse->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) size += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) buf = kzalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (dfse->type == SOF_DFSENTRY_TYPE_IOMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * If the DSP is active: copy from IO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * If the DSP is suspended:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * - Copy from IO if the memory is always accessible.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * - Otherwise, copy from cached buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (pm_runtime_active(sdev->dev) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) dfse->access_type == SOF_DEBUGFS_ACCESS_ALWAYS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) memcpy_fromio(buf, dfse->io_mem + pos, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) dev_info(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) "Copying cached debugfs data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) memcpy(buf, dfse->cache_buf + pos, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* if the DSP is in D3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!pm_runtime_active(sdev->dev) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) dfse->access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) dev_err(sdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) "error: debugfs entry cannot be read in DSP D3\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) memcpy_fromio(buf, dfse->io_mem + pos, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) memcpy(buf, ((u8 *)(dfse->buf) + pos), size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /* copy to userspace */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) size_ret = copy_to_user(buffer, buf + skip, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* update count & position if copy succeeded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (size_ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) *ppos = pos + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) static const struct file_operations sof_dfs_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) .read = sof_dfsentry_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) .llseek = default_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) .write = sof_dfsentry_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /* create FS entry for debug files that can expose DSP memories, registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int snd_sof_debugfs_io_item(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) void __iomem *base, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) enum sof_debugfs_access_type access_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct snd_sof_dfsentry *dfse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (!dfse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) dfse->type = SOF_DFSENTRY_TYPE_IOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) dfse->io_mem = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) dfse->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) dfse->sdev = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) dfse->access_type = access_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * allocate cache buffer that will be used to save the mem window
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) * contents prior to suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (access_type == SOF_DEBUGFS_ACCESS_D0_ONLY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) dfse->cache_buf = devm_kzalloc(sdev->dev, size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (!dfse->cache_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) debugfs_create_file(name, 0444, sdev->debugfs_root, dfse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) &sof_dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /* add to dfsentry list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) list_add(&dfse->list, &sdev->dfsentry_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) EXPORT_SYMBOL_GPL(snd_sof_debugfs_io_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* create FS entry for debug files to expose kernel memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) void *base, size_t size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) const char *name, mode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct snd_sof_dfsentry *dfse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) dfse = devm_kzalloc(sdev->dev, sizeof(*dfse), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!dfse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) dfse->type = SOF_DFSENTRY_TYPE_BUF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) dfse->buf = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) dfse->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) dfse->sdev = sdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * cache_buf is unused for SOF_DFSENTRY_TYPE_BUF debugfs entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * So, use it to save the results of the last IPC flood test.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) dfse->cache_buf = devm_kzalloc(sdev->dev, IPC_FLOOD_TEST_RESULT_LEN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!dfse->cache_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) debugfs_create_file(name, mode, sdev->debugfs_root, dfse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) &sof_dfs_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* add to dfsentry list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) list_add(&dfse->list, &sdev->dfsentry_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) EXPORT_SYMBOL_GPL(snd_sof_debugfs_buf_item);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) int snd_sof_dbg_init(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) const struct snd_sof_dsp_ops *ops = sof_ops(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) const struct snd_sof_debugfs_map *map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* use "sof" as top level debugFS dir */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) sdev->debugfs_root = debugfs_create_dir("sof", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* init dfsentry list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) INIT_LIST_HEAD(&sdev->dfsentry_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* create debugFS files for platform specific MMIO/DSP memories */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) for (i = 0; i < ops->debug_map_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) map = &ops->debug_map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) err = snd_sof_debugfs_io_item(sdev, sdev->bar[map->bar] +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) map->offset, map->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) map->name, map->access_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* errors are only due to memory allocation, not debugfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) err = snd_sof_debugfs_probe_item(sdev, "probe_points",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 0644, &probe_points_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) err = snd_sof_debugfs_probe_item(sdev, "probe_points_remove",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 0200, &probe_points_remove_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /* create read-write ipc_flood_count debugfs entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) err = snd_sof_debugfs_buf_item(sdev, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) "ipc_flood_count", 0666);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* errors are only due to memory allocation, not debugfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /* create read-write ipc_flood_duration_ms debugfs entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) err = snd_sof_debugfs_buf_item(sdev, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) "ipc_flood_duration_ms", 0666);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* errors are only due to memory allocation, not debugfs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) EXPORT_SYMBOL_GPL(snd_sof_dbg_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) void snd_sof_free_debug(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) debugfs_remove_recursive(sdev->debugfs_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) EXPORT_SYMBOL_GPL(snd_sof_free_debug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) (sof_core_debug & SOF_DBG_RETAIN_CTX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) /* should we prevent DSP entering D3 ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) dev_info(sdev->dev, "info: preventing DSP entering D3 state to preserve context\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) pm_runtime_get_noresume(sdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* dump vital information to the logs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) snd_sof_dsp_dbg_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) snd_sof_ipc_dump(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) snd_sof_trace_notify_for_error(sdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) EXPORT_SYMBOL(snd_sof_handle_fw_exception);