/* data immediately available */ if (core_data->host_read_ptr != core_data->dsp_write_ptr) returntrue;
/* wait for available trace data from FW */
init_waitqueue_entry(&wait, current);
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&core_data->trace_sleep, &wait);
if (!signal_pending(current)) { /* set timeout to max value, no error code */
schedule_timeout(MAX_SCHEDULE_TIMEOUT);
}
remove_wait_queue(&core_data->trace_sleep, &wait);
if (core_data->host_read_ptr != core_data->dsp_write_ptr) returntrue;
/* check pos and count */ if (lpos < 0) return -EINVAL; if (!count || count < sizeof(avail)) return 0;
/* get available count based on current host offset */ if (!sof_wait_mtrace_avail(core_data)) { /* No data available */
avail = 0; if (copy_to_user(buffer, &avail, sizeof(avail))) return -EFAULT;
return 0;
}
if (core_data->slot_offset == SOF_IPC4_INVALID_SLOT_OFFSET) return 0;
/* The log data buffer starts after the two pointer in the slot */
log_buffer_offset = core_data->slot_offset + (sizeof(u32) * 2); /* The log data size excludes the pointers */
log_buffer_size = SOF_IPC4_DEBUG_SLOT_SIZE - (sizeof(u32) * 2);
if (read_ptr < write_ptr) { /* Read data between read pointer and write pointer */
sof_mailbox_read(sdev, log_buffer_offset + read_ptr, log_buffer, avail);
} else { /* read from read pointer to end of the slot */
sof_mailbox_read(sdev, log_buffer_offset + read_ptr, log_buffer,
avail - write_ptr); /* read from slot start to write pointer */ if (write_ptr)
sof_mailbox_read(sdev, log_buffer_offset,
(u8 *)(log_buffer) + avail - write_ptr,
write_ptr);
}
/* first write the number of bytes we have gathered */
ret = copy_to_user(buffer, &avail, sizeof(avail)); if (ret) return -EFAULT;
/* Followed by the data itself */
ret = copy_to_user(buffer + sizeof(avail), log_buffer, avail); if (ret) return -EFAULT;
/* Update the host_read_ptr in the slot for this core */
read_ptr += avail; if (read_ptr >= log_buffer_size)
read_ptr -= log_buffer_size;
sof_mailbox_write(sdev, core_data->slot_offset, &read_ptr, sizeof(read_ptr));
/* Only update the host_read_ptr if mtrace is enabled */ if (priv->mtrace_state != SOF_MTRACE_DISABLED)
core_data->host_read_ptr = read_ptr;
/* * Ask for a new buffer from user space for the next chunk, not * streaming due to the heading number of bytes value.
*/
*ppos += count;
/* * To update Nth mask entry, write: * "N,0x1234" or "N,1234" to the debugfs file * The mask will be interpreted as hexadecimal number
*/
buf = memdup_user_nul(from, count); if (IS_ERR(buf)) return PTR_ERR(buf);
ret = sscanf(buf, "%u,0x%x", &id, &mask); if (ret != 2) {
ret = sscanf(buf, "%u,%x", &id, &mask); if (ret != 2) {
ret = -EINVAL; goto out;
}
}
if (id >= MAX_ALLOWED_LIBRARIES) {
ret = -EINVAL; goto out;
}
priv->state_info.logs_priorities_mask[id] = mask;
ret = count;
/* * local_clock() is used to align with dmesg, so both kernel and firmware logs have * the same base and a minor delta due to the IPC. system time is in us format but * local_clock() returns the time in ns, so convert to ns.
*/
system_time = div64_u64(local_clock(), NSEC_PER_USEC);
msg.data_size = sizeof(system_time);
msg.data_ptr = &system_time;
ret = iops->set_get_data(sdev, &msg, msg.data_size, true); if (ret) return ret;
/* * Each DSP core logs to a dedicated slot. * Parse the slot descriptors at debug_box offset to find the debug log slots * and map them to cores. * There are 15 slots and therefore 15 descriptors to check (MAX_MTRACE_SLOTS)
*/ staticvoid sof_mtrace_find_core_slots(struct snd_sof_dev *sdev)
{ struct sof_mtrace_priv *priv = sdev->fw_trace_data; struct sof_mtrace_core_data *core_data;
u32 slot_desc_type_offset, type, core; int i;
for (i = 0; i < SOF_IPC4_MAX_DEBUG_SLOTS; i++) { /* The type is the second u32 in the slot descriptor */
slot_desc_type_offset = sdev->debug_box.offset;
slot_desc_type_offset += SOF_IPC4_DEBUG_DESCRIPTOR_SIZE * i + sizeof(u32);
sof_mailbox_read(sdev, slot_desc_type_offset, &type, sizeof(type));
if ((type & SOF_MTRACE_SLOT_TYPE_MASK) == SOF_IPC4_DEBUG_SLOT_DEBUG_LOG) {
core = type & SOF_MTRACE_SLOT_CORE_MASK;
if (core >= sdev->num_cores) {
dev_dbg(sdev->dev, "core%u is invalid for slot%d\n",
core, i); continue;
}
core_data = &priv->cores[core]; /* * The area reserved for descriptors have the same size * as a slot. * In other words: slot0 starts at * debug_box + SOF_MTRACE_SLOT_SIZE offset
*/
core_data->slot_offset = sdev->debug_box.offset;
core_data->slot_offset += SOF_IPC4_DEBUG_SLOT_SIZE * (i + 1);
dev_dbg(sdev->dev, "slot%d is used for core%u\n", i, core); if (core_data->delayed_pos_update) {
sof_ipc4_mtrace_update_pos(sdev, core);
core_data->delayed_pos_update = false;
}
} elseif (type) {
dev_dbg(sdev->dev, "slot%d is not a log slot (%#x)\n", i, type);
}
}
}
staticint ipc4_mtrace_init(struct snd_sof_dev *sdev)
{ struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct sof_mtrace_priv *priv; int i, ret;
if (sdev->fw_trace_data) {
dev_err(sdev->dev, "fw_trace_data has been already allocated\n"); return -EBUSY;
}
ret = ipc4_mtrace_enable(sdev); if (ret) { /* * Mark firmware tracing as not supported and return 0 to not * block the whole audio stack
*/
sdev->fw_trace_is_supported = false;
dev_dbg(sdev->dev, "initialization failed, fw tracing is disabled\n"); return 0;
}
sof_mtrace_find_core_slots(sdev);
ret = mtrace_debugfs_create(sdev); if (ret)
ipc4_mtrace_disable(sdev);
/* Read out the dsp_write_ptr from the slot for this core */
sof_mailbox_read(sdev, core_data->slot_offset + sizeof(u32),
&core_data->dsp_write_ptr, 4);
core_data->dsp_write_ptr -= core_data->dsp_write_ptr % 4;
staticvoid ipc4_mtrace_fw_crashed(struct snd_sof_dev *sdev)
{ /* * The DSP might not be able to send SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS * messages anymore, so check the log buffer status on all * cores and process any pending messages.
*/
sof_ipc4_mtrace_update_pos_all_cores(sdev);
}
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.