1 /*
2 * SPDX-FileCopyrightText: 2015-2022 The Apache Software Foundation (ASF)
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * SPDX-FileContributor: 2019-2022 Espressif Systems (Shanghai) CO LTD
7 */
8
9 #include <assert.h>
10
11 #include "os/os.h"
12 #include "mem_api.h"
13 #include "bt_osi_mem.h"
14 #include "esp_err.h"
15
16 #if CONFIG_BT_NIMBLE_ENABLED
17 #include "syscfg/syscfg.h"
18 #endif
19
20 #define SYSINIT_PANIC_ASSERT(rc) assert(rc);
21
22 static STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
23 STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
24
25 #if CONFIG_BT_NIMBLE_ENABLED
26 #define OS_MSYS_1_BLOCK_COUNT MYNEWT_VAL(MSYS_1_BLOCK_COUNT)
27 #define OS_MSYS_1_BLOCK_SIZE MYNEWT_VAL(MSYS_1_BLOCK_SIZE)
28 #define OS_MSYS_2_BLOCK_COUNT MYNEWT_VAL(MSYS_2_BLOCK_COUNT)
29 #define OS_MSYS_2_BLOCK_SIZE MYNEWT_VAL(MSYS_2_BLOCK_SIZE)
30
31 #define OS_MSYS_1_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_1_SANITY_MIN_COUNT)
32 #define OS_MSYS_2_SANITY_MIN_COUNT MYNEWT_VAL(MSYS_2_SANITY_MIN_COUNT)
33 #if CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP
34 #define OS_MSYS_BLOCK_FROM_HEAP (1)
35 #else
36 #define OS_MSYS_BLOCK_FROM_HEAP (0)
37 #endif // CONFIG_BT_NIMBLE_MSYS_BUF_FROM_HEAP
38 #else
39 #define OS_MSYS_1_BLOCK_COUNT CONFIG_BT_LE_MSYS_1_BLOCK_COUNT
40 #define OS_MSYS_1_BLOCK_SIZE CONFIG_BT_LE_MSYS_1_BLOCK_SIZE
41 #define OS_MSYS_2_BLOCK_COUNT CONFIG_BT_LE_MSYS_2_BLOCK_COUNT
42 #define OS_MSYS_2_BLOCK_SIZE CONFIG_BT_LE_MSYS_2_BLOCK_SIZE
43
44 #define OS_MSYS_1_SANITY_MIN_COUNT 0
45 #define OS_MSYS_2_SANITY_MIN_COUNT 0
46
47 #if CONFIG_BT_LE_MSYS_BUF_FROM_HEAP
48 #define OS_MSYS_BLOCK_FROM_HEAP (1)
49 #else
50 #define OS_MSYS_BLOCK_FROM_HEAP (0)
51 #endif // CONFIG_BT_LE_MSYS_BUF_FROM_HEAP
52 #endif
53
54
55
56 #if OS_MSYS_1_BLOCK_COUNT > 0
57 #define SYSINIT_MSYS_1_MEMBLOCK_SIZE \
58 OS_ALIGN(OS_MSYS_1_BLOCK_SIZE, 4)
59 #define SYSINIT_MSYS_1_MEMPOOL_SIZE \
60 OS_MEMPOOL_SIZE(OS_MSYS_1_BLOCK_COUNT, \
61 SYSINIT_MSYS_1_MEMBLOCK_SIZE)
62
63 #if !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
64 static os_membuf_t *os_msys_init_1_data;
65 static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
66 static struct os_mempool os_msys_init_1_mempool;
67 #endif // !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
68 #endif
69
70 #if OS_MSYS_2_BLOCK_COUNT > 0
71 #define SYSINIT_MSYS_2_MEMBLOCK_SIZE \
72 OS_ALIGN(OS_MSYS_2_BLOCK_SIZE, 4)
73 #define SYSINIT_MSYS_2_MEMPOOL_SIZE \
74 OS_MEMPOOL_SIZE(OS_MSYS_2_BLOCK_COUNT, \
75 SYSINIT_MSYS_2_MEMBLOCK_SIZE)
76
77 #if !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
78 static os_membuf_t *os_msys_init_2_data;
79 static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
80 static struct os_mempool os_msys_init_2_mempool;
81 #endif // !CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
82 #endif
83
84 #if CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
85 extern int r_esp_ble_msys_init(uint16_t msys_size1, uint16_t msys_size2, uint16_t msys_cnt1, uint16_t msys_cnt2, uint8_t from_heap);
86 extern void r_esp_ble_msys_deinit(void);
87
os_msys_init(void)88 int os_msys_init(void)
89 {
90 return r_esp_ble_msys_init(SYSINIT_MSYS_1_MEMBLOCK_SIZE,
91 SYSINIT_MSYS_2_MEMBLOCK_SIZE,
92 OS_MSYS_1_BLOCK_COUNT,
93 OS_MSYS_2_BLOCK_COUNT,
94 OS_MSYS_BLOCK_FROM_HEAP);
95 }
96
os_msys_deinit(void)97 void os_msys_deinit(void)
98 {
99 r_esp_ble_msys_deinit();
100 }
101
102 #else // CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
103
104 #if OS_MSYS_SANITY_ENABLED
105
106 /**
107 * Retrieves the minimum safe buffer count for an msys pool. That is, the
108 * lowest a pool's buffer count can be without causing the sanity check to
109 * fail.
110 *
111 * @param idx The index of the msys pool to query.
112 *
113 * @return The msys pool's minimum safe buffer count.
114 */
115 static int
os_msys_sanity_min_count(int idx)116 IRAM_ATTR os_msys_sanity_min_count(int idx)
117 {
118 switch (idx) {
119 case 0:
120 return OS_MSYS_1_SANITY_MIN_COUNT;
121
122 case 1:
123 return OS_MSYS_2_SANITY_MIN_COUNT;
124
125 default:
126 BLE_LL_ASSERT(0);
127 return ESP_OK;
128 }
129 }
130
131 static int
os_msys_sanity(struct os_sanity_check * sc,void * arg)132 IRAM_ATTR os_msys_sanity(struct os_sanity_check *sc, void *arg)
133 {
134 const struct os_mbuf_pool *omp;
135 int min_count;
136 int idx;
137
138 idx = 0;
139 STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) {
140 min_count = os_msys_sanity_min_count(idx);
141 if (omp->omp_pool->mp_num_free < min_count) {
142 return OS_ENOMEM;
143 }
144
145 idx++;
146 }
147
148 return ESP_OK;
149 }
150 #endif
151
152 static void
os_msys_init_once(void * data,struct os_mempool * mempool,struct os_mbuf_pool * mbuf_pool,int block_count,int block_size,const char * name)153 os_msys_init_once(void *data, struct os_mempool *mempool,
154 struct os_mbuf_pool *mbuf_pool,
155 int block_count, int block_size, const char *name)
156 {
157 int rc;
158
159 rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
160 name);
161 SYSINIT_PANIC_ASSERT(rc == 0);
162
163 rc = os_msys_register(mbuf_pool);
164 SYSINIT_PANIC_ASSERT(rc == 0);
165 }
166
167 int
os_msys_buf_alloc(void)168 os_msys_buf_alloc(void)
169 {
170 #if OS_MSYS_1_BLOCK_COUNT > 0
171 os_msys_init_1_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_1_MEMPOOL_SIZE));
172 if (!os_msys_init_1_data) {
173 return ESP_ERR_NO_MEM;
174 }
175 #endif
176
177 #if OS_MSYS_2_BLOCK_COUNT > 0
178 os_msys_init_2_data = (os_membuf_t *)bt_osi_mem_calloc(1, (sizeof(os_membuf_t) * SYSINIT_MSYS_2_MEMPOOL_SIZE));
179 if (!os_msys_init_2_data) {
180 #if OS_MSYS_1_BLOCK_COUNT > 0
181 bt_osi_mem_free(os_msys_init_1_data);
182 os_msys_init_1_data = NULL;
183 #endif
184 return ESP_ERR_NO_MEM;
185 }
186 #endif
187
188 return ESP_OK;
189 }
190
191 void
os_msys_buf_free(void)192 os_msys_buf_free(void)
193 {
194 #if OS_MSYS_1_BLOCK_COUNT > 0
195 bt_osi_mem_free(os_msys_init_1_data);
196 os_msys_init_1_data = NULL;
197 #endif
198
199 #if OS_MSYS_2_BLOCK_COUNT > 0
200 bt_osi_mem_free(os_msys_init_2_data);
201 os_msys_init_2_data = NULL;
202 #endif
203
204 }
205
os_msys_init(void)206 void os_msys_init(void)
207 {
208 #if OS_MSYS_SANITY_ENABLED
209 int rc;
210 #endif
211
212 os_msys_reset();
213
214 #if OS_MSYS_1_BLOCK_COUNT > 0
215 os_msys_init_once(os_msys_init_1_data,
216 &os_msys_init_1_mempool,
217 &os_msys_init_1_mbuf_pool,
218 OS_MSYS_1_BLOCK_COUNT,
219 SYSINIT_MSYS_1_MEMBLOCK_SIZE,
220 "msys_1");
221 #endif
222
223 #if OS_MSYS_2_BLOCK_COUNT > 0
224 os_msys_init_once(os_msys_init_2_data,
225 &os_msys_init_2_mempool,
226 &os_msys_init_2_mbuf_pool,
227 OS_MSYS_2_BLOCK_COUNT,
228 SYSINIT_MSYS_2_MEMBLOCK_SIZE,
229 "msys_2");
230 #endif
231
232 #if OS_MSYS_SANITY_ENABLED
233 os_msys_sc.sc_func = os_msys_sanity;
234 os_msys_sc.sc_checkin_itvl =
235 OS_TICKS_PER_SEC * MYNEWT_VAL(MSYS_SANITY_TIMEOUT) / 1000;
236 rc = os_sanity_check_register(&os_msys_sc);
237 SYSINIT_PANIC_ASSERT(rc == 0);
238 #endif
239 }
240 #endif // CONFIG_BT_LE_MSYS_INIT_IN_CONTROLLER
241