Skip to content

Commit e87ec4e

Browse files
softwareckilgirdwood
authored andcommitted
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 e9b0a88 commit e87ec4e

File tree

6 files changed

+132
-0
lines changed

6 files changed

+132
-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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
#ifndef __SOF_IPC_NOTIFICATION_POOL_H__
9+
#define __SOF_IPC_NOTIFICATION_POOL_H__
10+
11+
#include <stdint.h>
12+
#include <sof/ipc/msg.h>
13+
14+
/**
15+
* @brief Retrieves an IPC notification message from the pool.
16+
*
17+
* This function retrieves and returns an IPC notification message
18+
* of the specified size from the notification pool. The size of the
19+
* message is limited by the maximum size available in the pool.
20+
*
21+
* @param size The size of the IPC message to retrieve.
22+
* @return A pointer to the retrieved IPC message, or NULL if retrieval fails.
23+
*/
24+
struct ipc_msg *ipc_notification_pool_get(size_t size);
25+
26+
#endif /* __SOF_IPC_NOTIFICATION_POOL_H__ */

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: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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+
#define NOTIFICATION_POOL_MAX_DEPTH 8 /* Maximum number of notifications
15+
* in the pool
16+
*/
17+
18+
LOG_MODULE_REGISTER(notification_pool, CONFIG_SOF_LOG_LEVEL);
19+
20+
SOF_DEFINE_REG_UUID(notification_pool);
21+
22+
DECLARE_TR_CTX(notif_tr, SOF_UUID(notification_pool_uuid), LOG_LEVEL_INFO);
23+
24+
struct ipc_notif_pool_item {
25+
struct ipc_msg msg;
26+
uint32_t payload[SOF_DIV_ROUND_UP(NOTIFICATION_POOL_MAX_PAYLOAD_SIZE, sizeof(uint32_t))];
27+
};
28+
29+
static struct list_item pool_free_list = LIST_INIT(pool_free_list);
30+
static struct k_spinlock pool_free_list_lock;
31+
static int pool_depth;
32+
33+
static void ipc_notif_free(struct ipc_msg *msg)
34+
{
35+
struct ipc_notif_pool_item *item = container_of(msg, struct ipc_notif_pool_item, msg);
36+
k_spinlock_key_t key;
37+
38+
key = k_spin_lock(&pool_free_list_lock);
39+
list_item_append(&item->msg.list, &pool_free_list);
40+
k_spin_unlock(&pool_free_list_lock, key);
41+
}
42+
43+
static struct ipc_msg *ipc_notif_new(size_t size)
44+
{
45+
struct ipc_notif_pool_item *item;
46+
47+
item = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*item));
48+
if (!item) {
49+
tr_err(&notif_tr, "Unable to allocate memory for notification message");
50+
return NULL;
51+
}
52+
53+
list_init(&item->msg.list);
54+
item->msg.tx_data = item->payload;
55+
item->msg.tx_size = size;
56+
item->msg.callback = ipc_notif_free;
57+
return &item->msg;
58+
}
59+
60+
struct ipc_msg *ipc_notification_pool_get(size_t size)
61+
{
62+
struct ipc_notif_pool_item *item;
63+
k_spinlock_key_t key;
64+
struct ipc_msg *new_msg;
65+
66+
if (size > NOTIFICATION_POOL_MAX_PAYLOAD_SIZE) {
67+
tr_err(&notif_tr, "Requested size %zu exceeds maximum payload size %u",
68+
size, NOTIFICATION_POOL_MAX_PAYLOAD_SIZE);
69+
return NULL;
70+
}
71+
72+
/* check if we have a free message */
73+
key = k_spin_lock(&pool_free_list_lock);
74+
if (list_is_empty(&pool_free_list)) {
75+
/* allocate a new message */
76+
if (pool_depth >= NOTIFICATION_POOL_MAX_DEPTH) {
77+
k_spin_unlock(&pool_free_list_lock, key);
78+
tr_err(&notif_tr, "Pool depth exceeded");
79+
return NULL;
80+
}
81+
++pool_depth;
82+
k_spin_unlock(&pool_free_list_lock, key);
83+
84+
new_msg = ipc_notif_new(size);
85+
if (!new_msg) {
86+
key = k_spin_lock(&pool_free_list_lock);
87+
--pool_depth;
88+
k_spin_unlock(&pool_free_list_lock, key);
89+
}
90+
return new_msg;
91+
}
92+
93+
/* take the first free message */
94+
item = list_first_item(&pool_free_list, struct ipc_notif_pool_item, msg.list);
95+
list_item_del(&item->msg.list);
96+
k_spin_unlock(&pool_free_list_lock, key);
97+
98+
item->msg.tx_size = size;
99+
return &item->msg;
100+
}

uuid-registry.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,4 @@ d944281a-afe9-4695-a043d7f62b89538e waves
172172
2B79E4F3-4675-F649-89DF3BC194A91AEB brngup
173173
D406D134-C3C1-402C-8AEC6821C0C2B0E6 cold
174174
c51dc642-a2e1-48df-a490e2748cb6363e tflmcly
175+
f36BF24B-9AAF-83f4-8677E072E8AEADB7 notification_pool

0 commit comments

Comments
 (0)