// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // // Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> // // Generic debug routines used to export DSP MMIO and memories to userspace // for firmware debugging. //
/* validate position & count */ if (pos < 0) return -EINVAL; if (pos >= size || !count) return0; /* find the minimum. min() is not used since it adds sparse warnings */ if (count > size - pos)
count = size - pos;
reply = kmalloc(SOF_IPC_MSG_MAX_SIZE, GFP_KERNEL); if (!reply) return -ENOMEM;
ret = pm_runtime_resume_and_get(sdev->dev); if (ret < 0 && ret != -EACCES) {
dev_err(sdev->dev, "error: enabling device failed: %d\n", ret); goto error;
}
ret = sof_ipc_tx_message(sdev->ipc, &msg, msg.size, reply, SOF_IPC_MSG_MAX_SIZE);
pm_runtime_put_autosuspend(sdev->dev); if (ret < 0 || reply->rhdr.error < 0) {
ret = min(ret, reply->rhdr.error);
dev_err(sdev->dev, "error: reading memory info failed, %d\n", ret); goto error;
}
if (struct_size(reply, elems, reply->num_elems) != reply->rhdr.hdr.size) {
dev_err(sdev->dev, "error: invalid memory info ipc struct size, %d\n",
reply->rhdr.hdr.size);
ret = -EINVAL; goto error;
}
for (i = 0, len = 0; i < reply->num_elems; i++) {
ret = scnprintf(buf + len, buff_size - len, "zone %d.%d used %#8x free %#8x\n",
reply->elems[i].zone, reply->elems[i].id,
reply->elems[i].used, reply->elems[i].free); if (ret < 0) goto error;
len += ret;
}
/* read memory info from FW only once for each file read */ if (!*ppos) {
dfse->buf_data_size = 0;
data_length = memory_info_update(sdev, dfse->buf, dfse->size); if (data_length < 0) return data_length;
dfse->buf_data_size = data_length;
}
/* allocate buffer memory only in first open run, to save memory when unused */ if (!dfse->buf) {
dfse->buf = devm_kmalloc(sdev->dev, PAGE_SIZE, GFP_KERNEL); if (!dfse->buf) return -ENOMEM;
dfse->size = PAGE_SIZE;
}
/* init dfsentry list */
INIT_LIST_HEAD(&sdev->dfsentry_list);
/* create debugFS files for platform specific MMIO/DSP memories */ for (i = 0; i < ops->debug_map_count; i++) {
map = &ops->debug_map[i];
err = snd_sof_debugfs_io_item(sdev, sdev->bar[map->bar] +
map->offset, map->size,
map->name, map->access_type); /* errors are only due to memory allocation, not debugfs */ if (err < 0) return err;
}
staticvoid snd_sof_ipc_dump(struct snd_sof_dev *sdev)
{ if (sof_ops(sdev)->ipc_dump && !sdev->ipc_dump_printed) {
dev_err(sdev->dev, "------------[ IPC dump start ]------------\n");
sof_ops(sdev)->ipc_dump(sdev);
dev_err(sdev->dev, "------------[ IPC dump end ]------------\n"); if (!sof_debug_check_flag(SOF_DBG_PRINT_ALL_DUMPS))
sdev->ipc_dump_printed = true;
}
}
void snd_sof_handle_fw_exception(struct snd_sof_dev *sdev, constchar *msg)
{ if ((IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_RETAIN_DSP_CONTEXT) ||
sof_debug_check_flag(SOF_DBG_RETAIN_CTX)) && !sdev->d3_prevented) { /* should we prevent DSP entering D3 ? */ if (!sdev->ipc_dump_printed)
dev_info(sdev->dev, "Attempting to prevent DSP from entering D3 state to preserve context\n");
if (pm_runtime_get_if_in_use(sdev->dev) == 1)
sdev->d3_prevented = true;
}
/* dump vital information to the logs */
snd_sof_ipc_dump(sdev);
snd_sof_dsp_dbg_dump(sdev, msg, SOF_DBG_DUMP_REGS | SOF_DBG_DUMP_MBOX);
sof_fw_trace_fw_crashed(sdev);
}
EXPORT_SYMBOL(snd_sof_handle_fw_exception);
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.