soc/intel_adsp: Unify trace backends

This platform had separate backends for the log subsystem and printk
handler, which was silly.  Unify them to use the same backend so they
don't clobber each other.

This patch appears to be a lot of lines, but it's really mostly code
motion and renaming.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2020-10-29 13:07:50 -07:00 committed by Andrew Boie
commit be2a5824f3
10 changed files with 135 additions and 270 deletions

View file

@ -66,15 +66,9 @@ if LOG
config LOG_PRINTK
default y
config LOG_BACKEND_RB
config LOG_BACKEND_ADSP
default y
config LOG_BACKEND_RB_MEM_BASE
default 0xBE000000
config LOG_BACKEND_RB_MEM_SIZE
default 8192
endif # LOG
if SMP

View file

@ -52,15 +52,9 @@ if LOG
config LOG_PRINTK
default y if !CONSOLE
config LOG_BACKEND_RB
config LOG_BACKEND_ADSP
default y
config LOG_BACKEND_RB_MEM_BASE
default 0xBE000000
config LOG_BACKEND_RB_MEM_SIZE
default 8192
endif # LOG
if SMP

View file

@ -51,15 +51,9 @@ if LOG
config LOG_PRINTK
default y
config LOG_BACKEND_RB
config LOG_BACKEND_ADSP
default y
config LOG_BACKEND_RB_MEM_BASE
default 0xBE000000
config LOG_BACKEND_RB_MEM_SIZE
default 8192
endif # LOG
if SMP

View file

@ -51,15 +51,9 @@ if LOG
config LOG_PRINTK
default y
config LOG_BACKEND_RB
config LOG_BACKEND_ADSP
default y
config LOG_BACKEND_RB_MEM_BASE
default 0xBE000000
config LOG_BACKEND_RB_MEM_SIZE
default 8192
endif # LOG
if SMP

View file

@ -15,7 +15,7 @@ zephyr_library_sources(adsp.c)
zephyr_library_sources(main_entry.S)
zephyr_library_sources(soc.c)
zephyr_library_sources(soc_mp.c)
zephyr_library_sources(printk_out.c)
zephyr_library_sources(trace_out.c)
zephyr_library_link_libraries(INTEL_ADSP_COMMON)

View file

@ -7,11 +7,12 @@
#include <adsp/cache.h>
#include <soc/shim.h>
/* Simple char-at-a-time output rig to the host kernel from a ADSP
* device. The protocol uses an array of "slots" in shared memory,
* each of which has a 16 bit magic number to validate and a
* sequential ID number. The remaining bytes are a (potentially
* nul-terminated) string containing output data.
/* Simple output driver for the trace window of an ADSP device used
* for communication with the host processor as a shared memory
* region. The protocol uses an array of 64-byte "slots", each of
* which is prefixed by a 16 bit magic number followed by a sequential
* ID number. The remaining bytes are a (potentially nul-terminated)
* string containing output data.
*
* IMPORTANT NOTE on cache coherence: the shared memory window is in
* HP-SRAM. Each DSP core has an L1 cache that is incoherent (!) from
@ -44,9 +45,9 @@ struct slot {
struct metadata {
struct k_spinlock lock;
int initialized;
int curr_slot; /* To which slot are we writing? */
int n_bytes; /* How many bytes buffered in curr_slot */
bool initialized;
uint32_t curr_slot; /* To which slot are we writing? */
uint32_t n_bytes; /* How many bytes buffered in curr_slot */
};
/* Give it a cache line all its own! */
@ -64,7 +65,7 @@ static inline struct slot *slot(int i)
return &slots[i];
}
int arch_printk_char_out(int c)
void intel_adsp_trace_out(int8_t *str, size_t len)
{
k_spinlock_key_t key = k_spin_lock(&data->lock);
@ -75,22 +76,41 @@ int arch_printk_char_out(int c)
data->initialized = 1;
}
struct slot *s = slot(data->curr_slot);
/* We work with a local copy of the global data for
* performance reasons (*data is uncached!) and put it back at
* the end.
*/
uint32_t curr_slot = data->curr_slot;
uint32_t n_bytes = data->n_bytes;
s->msg[data->n_bytes++] = c;
for (size_t i = 0; i < len; i++) {
int8_t c = str[i];
struct slot *s = slot(curr_slot);
if (data->n_bytes < MSGSZ) {
s->msg[data->n_bytes] = 0;
s->msg[n_bytes++] = c;
if (c == '\n' || n_bytes >= MSGSZ) {
curr_slot = (curr_slot + 1) % NSLOTS;
n_bytes = 0;
slot(curr_slot)->hdr.magic = 0;
slot(curr_slot)->hdr.id = s->hdr.id + 1;
s->hdr.magic = SLOT_MAGIC;
}
}
if (c == '\n' || data->n_bytes >= MSGSZ) {
data->curr_slot = (data->curr_slot + 1) % NSLOTS;
data->n_bytes = 0;
slot(data->curr_slot)->hdr.magic = 0;
slot(data->curr_slot)->hdr.id = s->hdr.id + 1;
s->hdr.magic = SLOT_MAGIC;
if (n_bytes < MSGSZ) {
slot(curr_slot)->msg[n_bytes] = 0;
}
data->curr_slot = curr_slot;
data->n_bytes = n_bytes;
k_spin_unlock(&data->lock, key);
}
int arch_printk_char_out(int c)
{
int8_t s = c;
intel_adsp_trace_out(&s, 1);
return 0;
}

View file

@ -50,8 +50,8 @@ if(NOT CONFIG_LOG_MINIMAL)
)
zephyr_sources_ifdef(
CONFIG_LOG_BACKEND_RB
log_backend_rb.c
CONFIG_LOG_BACKEND_ADSP
log_backend_adsp.c
)
if(CONFIG_LOG_BACKEND_SPINEL)

View file

@ -528,46 +528,12 @@ config LOG_BACKEND_NET_AUTOSTART
endif # LOG_BACKEND_NET
config LOG_BACKEND_RB
bool "Enable memory ring buffer backend"
select RING_BUFFER
config LOG_BACKEND_ADSP
bool "Enable Intel ADSP buffer backend"
depends on SOC_FAMILY_INTEL_ADSP
help
Enable backend in memory using ring buffer to keep messages.
if LOG_BACKEND_RB
config LOG_BACKEND_RB_MEM_BASE
hex "Ring buffer memory base address"
help
Address of the ring buffer in the memory.
config LOG_BACKEND_RB_MEM_SIZE
int "Size of the ring buffer"
help
Size of the ring buffer. Must be multiply of the message slot
size.
config LOG_BACKEND_RB_SLOT_SIZE
int "Size of the message slot"
default 64
help
Size of the message slot inside ring buffer. All log messages
are split to similar sized logging slots.
config LOG_BACKEND_RB_CLEAR
bool "Clear ring buffer slot"
default y
help
Clearing ring buffer slot helps to write more easy tools to read logs
on different platforms.
config LOG_BACKEND_RB_TIMESTAMP
bool "Add timestamp to the log"
default y
help
Add timestamp to the logging string.
endif # LOG_BACKEND_RB
Enable backend for the host trace protocol of the Intel ADSP
family of audio processors
config LOG_BACKEND_SHOW_COLOR
bool "Enable colors in the backend"

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log_backend.h>
#include <logging/log_core.h>
#include <logging/log_msg.h>
#include <logging/log_output.h>
#include <logging/log_backend_std.h>
void intel_adsp_trace_out(int8_t *str, size_t len);
static int char_out(uint8_t *data, size_t length, void *ctx)
{
intel_adsp_trace_out(data, length);
return length;
}
/* Trace output goes in 64 byte chunks with a 4-byte header, no point
* in buffering more than 60 bytes at a time
*/
static uint8_t log_buf[60];
LOG_OUTPUT_DEFINE(log_output_adsp, char_out, log_buf, 1);
static uint32_t format_flags(void)
{
uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_TIMESTAMP;
if (IS_ENABLED(CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
}
return flags;
}
static inline void put(const struct log_backend *const backend,
struct log_msg *msg)
{
log_backend_std_put(&log_output_adsp, format_flags(), msg);
}
static void panic(struct log_backend const *const backend)
{
log_backend_std_panic(&log_output_adsp);
}
static inline void dropped(const struct log_backend *const backend,
uint32_t cnt)
{
log_output_dropped_process(&log_output_adsp, cnt);
}
static inline void put_sync_string(const struct log_backend *const backend,
struct log_msg_ids src_level,
uint32_t timestamp, const char *fmt,
va_list ap)
{
log_output_string(&log_output_adsp, src_level,
timestamp, fmt, ap, format_flags());
}
static inline void put_sync_hexdump(const struct log_backend *const backend,
struct log_msg_ids src_level,
uint32_t timestamp, const char *metadata,
const uint8_t *data, uint32_t length)
{
log_output_hexdump(&log_output_adsp, src_level, timestamp,
metadata, data, length, format_flags());
}
const struct log_backend_api log_backend_adsp_api = {
#ifdef CONFIG_LOG_IMMEDIATE
.put_sync_string = put_sync_string,
.put_sync_hexdump = put_sync_hexdump,
#else
.put = put,
.dropped = dropped,
#endif
.panic = panic,
};
LOG_BACKEND_DEFINE(log_backend_adsp, log_backend_adsp_api, true);

View file

@ -1,181 +0,0 @@
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log_backend.h>
#include <logging/log_core.h>
#include <logging/log_msg.h>
#include <logging/log_output.h>
#include <sys/byteorder.h>
#include <sys/ring_buffer.h>
static struct ring_buf ringbuf;
/*
* Log message format:
* Logging started with magic number 0x55aa followed by log message id.
* Log message ended with null terminator and takes
* CONFIG_LOG_BACKEND_RB_SLOT_SIZE slot. The long log message can occupy
* several logging slots.
*/
/*
* All log messages are split to similar sized logging slots. Since ring
* buffer slots get rewritten we need to check that all slots are fit to
* the ring buffer
*/
BUILD_ASSERT(CONFIG_LOG_BACKEND_RB_MEM_SIZE %
CONFIG_LOG_BACKEND_RB_SLOT_SIZE == 0);
static void init(void)
{
ring_buf_init(&ringbuf, CONFIG_LOG_BACKEND_RB_MEM_SIZE,
(void *)CONFIG_LOG_BACKEND_RB_MEM_BASE);
}
static void trace(const uint8_t *data, size_t length)
{
const uint16_t magic = 0x55aa;
static uint16_t log_id;
volatile uint8_t *t, *region;
int space;
space = ring_buf_space_get(&ringbuf);
if (space < CONFIG_LOG_BACKEND_RB_SLOT_SIZE) {
uint8_t *dummy;
/* Remove oldest entry */
ring_buf_get_claim(&ringbuf, &dummy,
CONFIG_LOG_BACKEND_RB_SLOT_SIZE);
ring_buf_get_finish(&ringbuf, CONFIG_LOG_BACKEND_RB_SLOT_SIZE);
}
ring_buf_put_claim(&ringbuf, (uint8_t **)&t,
CONFIG_LOG_BACKEND_RB_SLOT_SIZE);
region = t;
/* Add magic number at the beginning of the slot */
sys_put_le16(magic, (uint8_t *)t);
t += 2;
/* Add log id */
sys_put_le16(log_id++, (uint8_t *)t);
t += 2;
length = MIN(length, CONFIG_LOG_BACKEND_RB_SLOT_SIZE - 4);
memcpy((void *)t, data, length);
t += length;
/* Clear logging slot */
if (IS_ENABLED(CONFIG_LOG_BACKEND_RB_CLEAR) &&
length < CONFIG_LOG_BACKEND_RB_SLOT_SIZE - 4) {
memset((void *)t, 0,
CONFIG_LOG_BACKEND_RB_SLOT_SIZE - 4 - length);
}
SOC_DCACHE_FLUSH((void *)region, CONFIG_LOG_BACKEND_RB_SLOT_SIZE);
ring_buf_put_finish(&ringbuf, CONFIG_LOG_BACKEND_RB_SLOT_SIZE);
}
static int char_out(uint8_t *data, size_t length, void *ctx)
{
trace(data, length);
return length;
}
/* magic and log id takes space */
static uint8_t rb_log_buf[CONFIG_LOG_BACKEND_RB_SLOT_SIZE - 4];
LOG_OUTPUT_DEFINE(log_output_rb, char_out, rb_log_buf, sizeof(rb_log_buf));
static void put(const struct log_backend *const backend,
struct log_msg *msg)
{
uint32_t flags = LOG_OUTPUT_FLAG_LEVEL;
log_msg_get(msg);
if (IS_ENABLED(CONFIG_LOG_BACKEND_RB_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_TIMESTAMP;
if (IS_ENABLED(CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
}
}
log_output_msg_process(&log_output_rb, msg, flags);
log_msg_put(msg);
}
static void panic(struct log_backend const *const backend)
{
log_output_flush(&log_output_rb);
}
static void dropped(const struct log_backend *const backend, uint32_t cnt)
{
ARG_UNUSED(backend);
log_output_dropped_process(&log_output_rb, cnt);
}
static void sync_string(const struct log_backend *const backend,
struct log_msg_ids src_level, uint32_t timestamp,
const char *fmt, va_list ap)
{
uint32_t flags = LOG_OUTPUT_FLAG_LEVEL;
uint32_t key;
if (IS_ENABLED(CONFIG_LOG_BACKEND_RB_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_TIMESTAMP;
if (IS_ENABLED(CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
}
}
key = irq_lock();
log_output_string(&log_output_rb, src_level,
timestamp, fmt, ap, flags);
irq_unlock(key);
}
static void sync_hexdump(const struct log_backend *const backend,
struct log_msg_ids src_level, uint32_t timestamp,
const char *metadata, const uint8_t *data, uint32_t length)
{
uint32_t flags = LOG_OUTPUT_FLAG_LEVEL;
uint32_t key;
if (IS_ENABLED(CONFIG_LOG_BACKEND_RB_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_TIMESTAMP;
if (IS_ENABLED(CONFIG_LOG_BACKEND_FORMAT_TIMESTAMP)) {
flags |= LOG_OUTPUT_FLAG_FORMAT_TIMESTAMP;
}
}
key = irq_lock();
log_output_hexdump(&log_output_rb, src_level, timestamp,
metadata, data, length, flags);
irq_unlock(key);
}
const struct log_backend_api log_backend_rb_api = {
.put = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ? NULL : put,
.put_sync_string = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ?
sync_string : NULL,
.put_sync_hexdump = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ?
sync_hexdump : NULL,
.panic = panic,
.init = init,
.dropped = IS_ENABLED(CONFIG_LOG_IMMEDIATE) ? NULL : dropped,
};
LOG_BACKEND_DEFINE(log_backend_adsp, log_backend_rb_api, true);