Skip to content

Commit 1cecf5d

Browse files
author
Jyri Sarha
committed
logging: probe: Add buffer to collect logs before probes DMA is up
Allocate a 4kb buffer to collect the logs arriving before probes DMA is up. Send the contents of the buffer when the callback indicating that DMA is running is set and free the buffer. Busy wait the DMA progress in case the buffer does not fit into the DMA buffer at once. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
1 parent c24ba76 commit 1cecf5d

File tree

1 file changed

+77
-2
lines changed

1 file changed

+77
-2
lines changed

src/logging/log_backend_probe.c

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
#include <sof/lib/notifier.h>
1515
#include <sof/probe/probe.h>
1616

17+
#ifdef PROBE_LOG_DEBUG
18+
#include <stdio.h>
19+
#endif
20+
1721
/*
1822
* A lock is needed as log_process() and log_panic() have no internal locks
1923
* to prevent concurrency. Meaning if log_process is called after
@@ -33,10 +37,81 @@ static uint8_t log_buf[LOG_BUF_SIZE];
3337

3438
static probe_logging_hook_t probe_hook;
3539

40+
static void log_push(uint8_t *data, size_t length)
41+
{
42+
int pos = 0;
43+
44+
do {
45+
int ret = probe_hook(data + pos, length - pos);
46+
47+
if (ret < 0)
48+
break;
49+
pos += ret;
50+
} while (pos < length);
51+
}
52+
53+
#define PRE_BUFFER_SIZE 4096
54+
static struct probe_pre_buffer {
55+
uint8_t *buf;
56+
uint32_t wpos;
57+
uint32_t len;
58+
} prebuf;
59+
60+
static void pre_buffer_drain(void)
61+
{
62+
#ifdef PROBE_LOG_DEBUG
63+
/* NOTE: The debug code only works with ascii/text log output */
64+
uint64_t stamp = sof_cycle_get_64();
65+
char msg[80];
66+
int mlen;
67+
68+
mlen = snprintf(msg, sizeof(msg), "[Drain %u bytes of pre buffered logs]\n", prebuf.wpos);
69+
if (prebuf.len > prebuf.wpos)
70+
mlen += snprintf(&msg[mlen], sizeof(msg) - mlen, "[%u bytes dropped]\n",
71+
prebuf.len - prebuf.wpos);
72+
log_push(msg, mlen);
73+
#endif
74+
75+
log_push(prebuf.buf, prebuf.wpos);
76+
rfree(prebuf.buf);
77+
prebuf.buf = NULL;
78+
prebuf.len = 0;
79+
prebuf.wpos = 0;
80+
81+
#ifdef PROBE_LOG_DEBUG
82+
mlen = snprintf(msg, sizeof(msg), "[Buffer drained in %llu us]\n",
83+
k_cyc_to_us_near64(sof_cycle_get_64() - stamp));
84+
85+
log_push(msg, mlen);
86+
#endif
87+
}
88+
89+
static void pre_buffer(uint8_t *data, size_t length)
90+
{
91+
int ret;
92+
93+
prebuf.len += length;
94+
if (!prebuf.buf) {
95+
prebuf.buf = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, PRE_BUFFER_SIZE);
96+
if (!prebuf.buf)
97+
return;
98+
}
99+
/* Protection against buffer over flow relies on memcpy_s() */
100+
ret = memcpy_s(&prebuf.buf[prebuf.wpos], PRE_BUFFER_SIZE - prebuf.wpos, data, length);
101+
if (!ret)
102+
prebuf.wpos += length;
103+
}
104+
36105
static int probe_char_out(uint8_t *data, size_t length, void *ctx)
37106
{
38-
if (probe_hook)
39-
probe_hook(data, length);
107+
if (!probe_hook) {
108+
pre_buffer(data, length);
109+
} else {
110+
if (prebuf.wpos)
111+
pre_buffer_drain();
112+
113+
log_push(data, length);
114+
}
40115

41116
return length;
42117
}

0 commit comments

Comments
 (0)