Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/include/sof/ipc/msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct ipc_msg {
uint32_t tx_size; /* payload size in bytes */
void *tx_data; /* pointer to payload data, must be in a non-cached memory */
struct list_item list;
void (*callback)(struct ipc_msg *msg); /* Function called after sending the message */
};

/**
Expand Down
26 changes: 26 additions & 0 deletions src/include/sof/ipc/notification_pool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright(c) 2025 Intel Corporation. All rights reserved.
*
* Author: Adrian Warecki <adrian.warecki@intel.com>
*/

#ifndef __SOF_IPC_NOTIFICATION_POOL_H__
#define __SOF_IPC_NOTIFICATION_POOL_H__

#include <stdint.h>
#include <sof/ipc/msg.h>

/**
* @brief Retrieves an IPC notification message from the pool.
*
* This function retrieves and returns an IPC notification message
* of the specified size from the notification pool. The size of the
* message is limited by the maximum size available in the pool.
*
* @param size The size of the IPC message to retrieve.
* @return A pointer to the retrieved IPC message, or NULL if retrieval fails.
*/
struct ipc_msg *ipc_notification_pool_get(size_t size);
Comment thread
softwarecki marked this conversation as resolved.

#endif /* __SOF_IPC_NOTIFICATION_POOL_H__ */
1 change: 1 addition & 0 deletions src/ipc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ endif()
add_local_sources(sof
ipc-common.c
ipc-helper.c
notification_pool.c
)

is_zephyr(it_is)
Expand Down
3 changes: 3 additions & 0 deletions src/ipc/ipc-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ void ipc_send_queued_msg(void)
if (ipc_platform_send_msg(msg) == 0) {
/* Remove the message from the list if it has been successfully sent. */
list_item_del(&msg->list);
/* Invoke a callback to notify that the message has been sent. */
if (msg->callback)
msg->callback(msg);
#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS
/* Increment performance counters */
io_perf_monitor_update_data(ipc->io_perf_out_msg_count, 1);
Expand Down
100 changes: 100 additions & 0 deletions src/ipc/notification_pool.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Copyright(c) 2025 Intel Corporation. All rights reserved.
//
// Author: Adrian Warecki <adrian.warecki@intel.com>
//

#include <stdint.h>
#include <sof/common.h>
#include <sof/list.h>
#include <sof/ipc/notification_pool.h>

#define NOTIFICATION_POOL_MAX_PAYLOAD_SIZE 40 /* IPC4 Resource Event needs 10dw */
#define NOTIFICATION_POOL_MAX_DEPTH 8 /* Maximum number of notifications
* in the pool
*/

LOG_MODULE_REGISTER(notification_pool, CONFIG_SOF_LOG_LEVEL);

SOF_DEFINE_REG_UUID(notification_pool);

DECLARE_TR_CTX(notif_tr, SOF_UUID(notification_pool_uuid), LOG_LEVEL_INFO);

struct ipc_notif_pool_item {
struct ipc_msg msg;
uint32_t payload[SOF_DIV_ROUND_UP(NOTIFICATION_POOL_MAX_PAYLOAD_SIZE, sizeof(uint32_t))];
};

static struct list_item pool_free_list = LIST_INIT(pool_free_list);
static struct k_spinlock pool_free_list_lock;
static int pool_depth;

static void ipc_notif_free(struct ipc_msg *msg)
{
struct ipc_notif_pool_item *item = container_of(msg, struct ipc_notif_pool_item, msg);
k_spinlock_key_t key;

key = k_spin_lock(&pool_free_list_lock);
list_item_append(&item->msg.list, &pool_free_list);
k_spin_unlock(&pool_free_list_lock, key);
}

static struct ipc_msg *ipc_notif_new(size_t size)
{
struct ipc_notif_pool_item *item;

item = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*item));
if (!item) {
tr_err(&notif_tr, "Unable to allocate memory for notification message");
return NULL;
}

list_init(&item->msg.list);
item->msg.tx_data = item->payload;
item->msg.tx_size = size;
item->msg.callback = ipc_notif_free;
return &item->msg;
}

struct ipc_msg *ipc_notification_pool_get(size_t size)
{
struct ipc_notif_pool_item *item;
k_spinlock_key_t key;
struct ipc_msg *new_msg;

if (size > NOTIFICATION_POOL_MAX_PAYLOAD_SIZE) {
tr_err(&notif_tr, "Requested size %zu exceeds maximum payload size %u",
size, NOTIFICATION_POOL_MAX_PAYLOAD_SIZE);
return NULL;
}

/* check if we have a free message */
key = k_spin_lock(&pool_free_list_lock);
if (list_is_empty(&pool_free_list)) {
/* allocate a new message */
if (pool_depth >= NOTIFICATION_POOL_MAX_DEPTH) {
k_spin_unlock(&pool_free_list_lock, key);
tr_err(&notif_tr, "Pool depth exceeded");
return NULL;
}
++pool_depth;
k_spin_unlock(&pool_free_list_lock, key);

new_msg = ipc_notif_new(size);
if (!new_msg) {
key = k_spin_lock(&pool_free_list_lock);
--pool_depth;
k_spin_unlock(&pool_free_list_lock, key);
Comment thread
softwarecki marked this conversation as resolved.
}
return new_msg;
}

/* take the first free message */
item = list_first_item(&pool_free_list, struct ipc_notif_pool_item, msg.list);
list_item_del(&item->msg.list);
k_spin_unlock(&pool_free_list_lock, key);

item->msg.tx_size = size;
return &item->msg;
}
1 change: 1 addition & 0 deletions uuid-registry.txt
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,4 @@ d944281a-afe9-4695-a043d7f62b89538e waves
2B79E4F3-4675-F649-89DF3BC194A91AEB brngup
D406D134-C3C1-402C-8AEC6821C0C2B0E6 cold
c51dc642-a2e1-48df-a490e2748cb6363e tflmcly
f36BF24B-9AAF-83f4-8677E072E8AEADB7 notification_pool