// Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
//
+#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/slab.h>
#include <sound/hdaudio_ext.h>
#include "avs.h"
#include "messages.h"
#include "registers.h"
+#include "trace.h"
#define AVS_IPC_TIMEOUT_MS 300
#define AVS_D0IX_DELAY_MS 300
{
struct avs_ipc *ipc = adev->ipc;
union avs_reply_msg msg = AVS_MSG(header);
+ u64 reg;
+
+ reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
+ trace_avs_ipc_reply_msg(header, reg);
ipc->rx.header = header;
/* Abort copying payload if request processing was unsuccessful. */
ipc->rx.size = msg.ext.large_config.data_off_size;
memcpy_fromio(ipc->rx.data, avs_uplink_addr(adev), ipc->rx.size);
+ trace_avs_msg_payload(ipc->rx.data, ipc->rx.size);
}
}
union avs_notify_msg msg = AVS_MSG(header);
size_t data_size = 0;
void *data = NULL;
+ u64 reg;
+
+ reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
+ trace_avs_ipc_notify_msg(header, reg);
/* Ignore spurious notifications until handshake is established. */
if (!adev->ipc->ready && msg.notify_msg_type != AVS_NOTIFY_FW_READY) {
return;
memcpy_fromio(data, avs_uplink_addr(adev), data_size);
+ trace_avs_msg_payload(data, data_size);
}
/* Perform notification-specific operations. */
reinit_completion(&ipc->busy_completion);
}
-static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx)
+static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool read_fwregs)
{
+ u64 reg = ULONG_MAX;
+
tx->header |= SKL_ADSP_HIPCI_BUSY;
+ if (read_fwregs)
+ reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
+
+ trace_avs_request(tx, reg);
if (tx->size)
memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size);
spin_lock(&ipc->rx_lock);
avs_ipc_msg_init(ipc, reply);
- avs_dsp_send_tx(adev, request);
+ avs_dsp_send_tx(adev, request, true);
spin_unlock(&ipc->rx_lock);
ret = avs_ipc_wait_busy_completion(ipc, timeout);
{
int ret;
+ trace_avs_d0ix("wake", wake_d0i0, request->header);
if (wake_d0i0) {
ret = avs_dsp_wake_d0i0(adev, request);
if (ret)
if (ret)
return ret;
+ trace_avs_d0ix("schedule", schedule_d0ix, request->header);
if (schedule_d0ix)
avs_dsp_schedule_d0ix(adev, request);
spin_lock(&ipc->rx_lock);
avs_ipc_msg_init(ipc, NULL);
- avs_dsp_send_tx(adev, request);
+ /*
+ * with hw still stalled, memory windows may not be
+ * configured properly so avoid accessing SRAM
+ */
+ avs_dsp_send_tx(adev, request, false);
spin_unlock(&ipc->rx_lock);
/* ROM messages must be sent before main core is unstalled */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM intel_avs
+
+#if !defined(_TRACE_INTEL_AVS_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_INTEL_AVS_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(avs_dsp_core_op,
+
+ TP_PROTO(unsigned int reg, unsigned int mask, const char *op, bool flag),
+
+ TP_ARGS(reg, mask, op, flag),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, reg )
+ __field(unsigned int, mask )
+ __string(op, op )
+ __field(bool, flag )
+ ),
+
+ TP_fast_assign(
+ __entry->reg = reg;
+ __entry->mask = mask;
+ __assign_str(op, op);
+ __entry->flag = flag;
+ ),
+
+ TP_printk("%s: %d, core mask: 0x%X, prev state: 0x%08X",
+ __get_str(op), __entry->flag, __entry->mask, __entry->reg)
+);
+
+#ifndef __TRACE_INTEL_AVS_TRACE_HELPER
+#define __TRACE_INTEL_AVS_TRACE_HELPER
+
+void trace_avs_msg_payload(const void *data, size_t size);
+
+#define trace_avs_request(msg, fwregs) \
+({ \
+ trace_avs_ipc_request_msg((msg)->header, fwregs); \
+ trace_avs_msg_payload((msg)->data, (msg)->size); \
+})
+
+#define trace_avs_reply(msg, fwregs) \
+({ \
+ trace_avs_ipc_reply_msg((msg)->header, fwregs); \
+ trace_avs_msg_payload((msg)->data, (msg)->size); \
+})
+
+#define trace_avs_notify(msg, fwregs) \
+({ \
+ trace_avs_ipc_notify_msg((msg)->header, fwregs); \
+ trace_avs_msg_payload((msg)->data, (msg)->size); \
+})
+#endif
+
+DECLARE_EVENT_CLASS(avs_ipc_msg_hdr,
+
+ TP_PROTO(u64 header, u64 fwregs),
+
+ TP_ARGS(header, fwregs),
+
+ TP_STRUCT__entry(
+ __field(u64, header)
+ __field(u64, fwregs)
+ ),
+
+ TP_fast_assign(
+ __entry->header = header;
+ __entry->fwregs = fwregs;
+ ),
+
+ TP_printk("primary: 0x%08X, extension: 0x%08X,\n"
+ "fwstatus: 0x%08X, fwerror: 0x%08X",
+ lower_32_bits(__entry->header), upper_32_bits(__entry->header),
+ lower_32_bits(__entry->fwregs), upper_32_bits(__entry->fwregs))
+);
+
+DEFINE_EVENT(avs_ipc_msg_hdr, avs_ipc_request_msg,
+ TP_PROTO(u64 header, u64 fwregs),
+ TP_ARGS(header, fwregs)
+);
+
+DEFINE_EVENT(avs_ipc_msg_hdr, avs_ipc_reply_msg,
+ TP_PROTO(u64 header, u64 fwregs),
+ TP_ARGS(header, fwregs)
+);
+
+DEFINE_EVENT(avs_ipc_msg_hdr, avs_ipc_notify_msg,
+ TP_PROTO(u64 header, u64 fwregs),
+ TP_ARGS(header, fwregs)
+);
+
+TRACE_EVENT_CONDITION(avs_ipc_msg_payload,
+
+ TP_PROTO(const u8 *data, size_t size, size_t offset, size_t total),
+
+ TP_ARGS(data, size, offset, total),
+
+ TP_CONDITION(data && size),
+
+ TP_STRUCT__entry(
+ __dynamic_array(u8, buf, size )
+ __field(size_t, offset )
+ __field(size_t, pos )
+ __field(size_t, total )
+ ),
+
+ TP_fast_assign(
+ memcpy(__get_dynamic_array(buf), data + offset, size);
+ __entry->offset = offset;
+ __entry->pos = offset + size;
+ __entry->total = total;
+ ),
+
+ TP_printk("range %zu-%zu out of %zu bytes%s",
+ __entry->offset, __entry->pos, __entry->total,
+ __print_hex_dump("", DUMP_PREFIX_NONE, 16, 4,
+ __get_dynamic_array(buf),
+ __get_dynamic_array_len(buf), false))
+);
+
+TRACE_EVENT(avs_d0ix,
+
+ TP_PROTO(const char *op, bool proceed, u64 header),
+
+ TP_ARGS(op, proceed, header),
+
+ TP_STRUCT__entry(
+ __string(op, op )
+ __field(bool, proceed )
+ __field(u64, header )
+ ),
+
+ TP_fast_assign(
+ __assign_str(op, op);
+ __entry->proceed = proceed;
+ __entry->header = header;
+ ),
+
+ TP_printk("%s%s for request: 0x%08X 0x%08X",
+ __entry->proceed ? "" : "ignore ", __get_str(op),
+ lower_32_bits(__entry->header), upper_32_bits(__entry->header))
+);
+
+#endif /* _TRACE_INTEL_AVS_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>