forked from thesofproject/sof
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdebug_stream_slot.c
More file actions
168 lines (140 loc) · 5.18 KB
/
debug_stream_slot.c
File metadata and controls
168 lines (140 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2024 Intel Corporation.
#include <zephyr/logging/log.h>
#include <zephyr/spinlock.h>
#include <adsp_debug_window.h>
#include <adsp_memory.h>
#include <sof/common.h>
#include <rtos/string.h>
#include <user/debug_stream.h>
#include <user/debug_stream_slot.h>
#include <zephyr/kernel.h>
LOG_MODULE_REGISTER(debug_stream_slot);
struct cpu_mutex {
struct k_spinlock l;
} __aligned(CONFIG_DCACHE_LINE_SIZE);
/* CPU specific mutexes for each circular buffer */
static struct cpu_mutex cpu_mutex[CONFIG_MP_MAX_NUM_CPUS];
#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
static struct debug_stream_slot_hdr *dbg_stream_slot;
#else
static const int debug_stream_slot = CONFIG_SOF_DEBUG_STREAM_SLOT_NUMBER;
#endif
static struct debug_stream_slot_hdr *debug_stream_get_slot(void)
{
#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
if (!dbg_stream_slot) {
struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_DEBUG_STREAM, };
dbg_stream_slot = (struct debug_stream_slot_hdr *)
adsp_dw_request_slot(&slot_desc, NULL);
}
return dbg_stream_slot;
#else
return (struct debug_stream_slot_hdr *)ADSP_DW->slots[debug_stream_slot];
#endif
}
static
struct debug_stream_circular_buf *
debug_stream_get_circular_buffer(struct debug_stream_section_descriptor *desc, unsigned int core)
{
struct debug_stream_slot_hdr *hdr = debug_stream_get_slot();
if (hdr->hdr.magic != DEBUG_STREAM_IDENTIFIER) {
LOG_ERR("Debug stream slot not initialized.");
return NULL;
}
*desc = hdr->section_desc[core];
LOG_DBG("Section %u (desc %u %u %u)", core, desc->core_id, desc->buf_words, desc->offset);
return (struct debug_stream_circular_buf *) (((uint8_t *)hdr) + desc->offset);
}
int debug_stream_slot_send_record(struct debug_stream_record *rec)
{
struct debug_stream_section_descriptor desc = { 0 };
struct debug_stream_circular_buf *buf =
debug_stream_get_circular_buffer(&desc, arch_proc_id());
uint32_t record_size = rec->size_words;
uint32_t record_start, buf_remain;
k_spinlock_key_t key;
LOG_DBG("Sending record %u id %u len %u", rec->seqno, rec->id, rec->size_words);
if (!buf)
return -ENODEV;
if (rec->size_words >= desc.buf_words) {
LOG_ERR("Record too big %u >= %u (desc %u %u %u)", rec->size_words,
desc.buf_words, desc.core_id, desc.buf_words, desc.offset);
return -ENOMEM;
}
key = k_spin_lock(&cpu_mutex[arch_proc_id()].l);
rec->seqno = buf->next_seqno++;
rec->size_words = record_size + 1; /* +1 for size at the end of record */
record_start = buf->w_ptr;
buf->w_ptr = (record_start + record_size) % desc.buf_words;
buf_remain = desc.buf_words - record_start;
if (buf_remain < record_size) {
uint32_t rec_remain = record_size - buf_remain;
int ret;
ret = memcpy_s(&buf->data[record_start], buf_remain * sizeof(uint32_t),
rec, buf_remain * sizeof(uint32_t));
assert(!ret);
ret = memcpy_s(&buf->data[0], desc.buf_words * sizeof(uint32_t),
((uint32_t *) rec) + buf_remain, rec_remain * sizeof(uint32_t));
assert(!ret);
} else {
int ret;
ret = memcpy_s(&buf->data[record_start], buf_remain * sizeof(uint32_t),
rec, record_size * sizeof(uint32_t));
assert(!ret);
}
/* Write record size again after the record */
buf->data[buf->w_ptr] = record_size + 1;
buf->w_ptr = (buf->w_ptr + 1) % desc.buf_words;
k_spin_unlock(&cpu_mutex[arch_proc_id()].l, key);
LOG_DBG("Record %u id %u len %u sent", rec->seqno, rec->id, record_size);
return 0;
}
static int debug_stream_slot_init(void)
{
struct debug_stream_slot_hdr *hdr = debug_stream_get_slot();
size_t hdr_size = ALIGN_UP(offsetof(struct debug_stream_slot_hdr,
section_desc[CONFIG_MP_MAX_NUM_CPUS]),
CONFIG_DCACHE_LINE_SIZE);
size_t section_area_size = ADSP_DW_SLOT_SIZE - hdr_size;
size_t section_size = ALIGN_DOWN(section_area_size /
CONFIG_MP_MAX_NUM_CPUS,
CONFIG_DCACHE_LINE_SIZE);
size_t offset = hdr_size;
int i;
LOG_INF("%u sections of %u bytes, hdr %u, section area %u",
CONFIG_MP_MAX_NUM_CPUS, section_size, hdr_size,
section_area_size);
#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
if (!hdr)
return -ENOMEM;
#else
if (ADSP_DW->descs[debug_stream_slot].type != 0)
LOG_WRN("Slot %d was not free: %u", debug_stream_slot,
ADSP_DW->descs[debug_stream_slot].type);
ADSP_DW->descs[debug_stream_slot].type = ADSP_DW_SLOT_DEBUG_STREAM;
#endif
hdr->hdr.magic = DEBUG_STREAM_IDENTIFIER;
hdr->hdr.hdr_size = hdr_size;
hdr->total_size = hdr_size + CONFIG_MP_MAX_NUM_CPUS * section_size;
hdr->num_sections = CONFIG_MP_MAX_NUM_CPUS;
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
hdr->section_desc[i].core_id = i;
hdr->section_desc[i].buf_words =
(section_size - offsetof(struct debug_stream_circular_buf, data[0])) /
sizeof(uint32_t);
hdr->section_desc[i].offset = offset;
LOG_DBG("sections %u, size %u, offset %u", i, section_size, offset);
offset += section_size;
}
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
struct debug_stream_section_descriptor desc = { 0 };
struct debug_stream_circular_buf *buf = debug_stream_get_circular_buffer(&desc, i);
buf->next_seqno = 0;
buf->w_ptr = 0;
}
LOG_DBG("Debug stream slot initialized");
return 0;
}
SYS_INIT(debug_stream_slot_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);