Skip to content

Commit cd92ceb

Browse files
committed
ipc4: Add notification pool
Add a pool of IPC messages for sending notifications. These messages are dynamically allocated as needed. Add a callback to the ipc_msg structure that is called after sending a message, allowing messages to be returned to the pool once sent. Using a notification pool simplifies the process of sending sporadic notifications by components. This approach eliminates the need for components to manage the allocation and release of notifications. Additionally, it conserves memory, as notifications that are never sent during normal operation will not be allocated. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
1 parent 2f166c8 commit cd92ceb

File tree

6 files changed

+108
-0
lines changed

6 files changed

+108
-0
lines changed

src/include/sof/ipc/msg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct ipc_msg {
3636
uint32_t tx_size; /* payload size in bytes */
3737
void *tx_data; /* pointer to payload data, must be in a non-cached memory */
3838
struct list_item list;
39+
void (*callback)(struct ipc_msg *msg); /* Function called after sending the message */
3940
};
4041

4142
/**
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause
2+
*
3+
* Copyright(c) 2025 Intel Corporation. All rights reserved.
4+
*
5+
* Author: Adrian Warecki <adrian.warecki@intel.com>
6+
*/
7+
8+
#include <stdint.h>
9+
#include <sof/ipc/msg.h>
10+
11+
/**
12+
* @brief Retrieves an IPC notification message from the pool.
13+
*
14+
* This function retrieves and returns an IPC notification message
15+
* of the specified size from the notification pool. The size of the
16+
* message is limited by the maximum size available in the pool.
17+
*
18+
* @param size The size of the IPC message to retrieve.
19+
* @return A pointer to the retrieved IPC message, or NULL if retrieval fails.
20+
*/
21+
struct ipc_msg *ipc_notification_pool_get(size_t size);

src/ipc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ endif()
1010
add_local_sources(sof
1111
ipc-common.c
1212
ipc-helper.c
13+
notification_pool.c
1314
)
1415

1516
is_zephyr(it_is)

src/ipc/ipc-common.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ void ipc_send_queued_msg(void)
162162
if (ipc_platform_send_msg(msg) == 0) {
163163
/* Remove the message from the list if it has been successfully sent. */
164164
list_item_del(&msg->list);
165+
/* Invoke a callback to notify that the message has been sent. */
166+
if (msg->callback)
167+
msg->callback(msg);
165168
#ifdef CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS
166169
/* Increment performance counters */
167170
io_perf_monitor_update_data(ipc->io_perf_out_msg_count, 1);

src/ipc/notification_pool.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2025 Intel Corporation. All rights reserved.
4+
//
5+
// Author: Adrian Warecki <adrian.warecki@intel.com>
6+
//
7+
8+
#include <stdint.h>
9+
#include <sof/common.h>
10+
#include <sof/list.h>
11+
#include <sof/ipc/notification_pool.h>
12+
13+
#define NOTIFICATION_POOL_MAX_PAYLOAD_SIZE 40 /* IPC4 Resource Event needs 10dw */
14+
15+
LOG_MODULE_REGISTER(notification_pool, CONFIG_SOF_LOG_LEVEL);
16+
17+
SOF_DEFINE_REG_UUID(notification_pool);
18+
19+
DECLARE_TR_CTX(notif_tr, SOF_UUID(notification_pool_uuid), LOG_LEVEL_INFO);
20+
21+
struct ipc_notif_pool_item {
22+
struct ipc_msg msg;
23+
uint32_t payload[SOF_DIV_ROUND_UP(NOTIFICATION_POOL_MAX_PAYLOAD_SIZE, sizeof(uint32_t))];
24+
};
25+
26+
static struct list_item pool_free_list = LIST_INIT(pool_free_list);
27+
struct k_spinlock pool_free_list_lock;
28+
29+
static void ipc_notif_free(struct ipc_msg *msg)
30+
{
31+
struct ipc_notif_pool_item *item = container_of(msg, struct ipc_notif_pool_item, msg);
32+
k_spinlock_key_t key;
33+
34+
key = k_spin_lock(&pool_free_list_lock);
35+
list_item_append(&item->msg.list, &pool_free_list);
36+
k_spin_unlock(&pool_free_list_lock, key);
37+
}
38+
39+
static struct ipc_msg *ipc_notif_new(size_t size)
40+
{
41+
struct ipc_notif_pool_item *item;
42+
43+
item = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*item));
44+
if (!item) {
45+
tr_err(&notif_tr, "Unable to allocate memory for notification message");
46+
return NULL;
47+
}
48+
49+
list_init(&item->msg.list);
50+
item->msg.tx_data = item->payload;
51+
item->msg.tx_size = size;
52+
item->msg.callback = ipc_notif_free;
53+
return &item->msg;
54+
}
55+
56+
struct ipc_msg *ipc_notification_pool_get(size_t size)
57+
{
58+
struct ipc_notif_pool_item *item;
59+
k_spinlock_key_t key;
60+
61+
if (size > NOTIFICATION_POOL_MAX_PAYLOAD_SIZE) {
62+
tr_err(&notif_tr, "Requested size %u exceeds maximum payload size %u",
63+
size, NOTIFICATION_POOL_MAX_PAYLOAD_SIZE);
64+
return NULL;
65+
}
66+
67+
/* check if we have a free message */
68+
key = k_spin_lock(&pool_free_list_lock);
69+
if (list_is_empty(&pool_free_list)) {
70+
k_spin_unlock(&pool_free_list_lock, key);
71+
return ipc_notif_new(size);
72+
}
73+
74+
/* take the first free message */
75+
item = list_first_item(&pool_free_list, struct ipc_notif_pool_item, msg.list);
76+
list_item_del(&item->msg.list);
77+
k_spin_unlock(&pool_free_list_lock, key);
78+
79+
item->msg.tx_size = size;
80+
return &item->msg;
81+
}

uuid-registry.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,4 @@ d944281a-afe9-4695-a043d7f62b89538e waves
170170
1547fe68-de0c-11eb-84613158a1294853 zll_sched
171171
2B79E4F3-4675-F649-89DF3BC194A91AEB brngup
172172
D406D134-C3C1-402C-8AEC6821C0C2B0E6 cold
173+
f36BF24B-9AAF-83f4-8677E072E8AEADB7 notification_pool

0 commit comments

Comments
 (0)