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