1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 */
8
9 #include "scp_unity.h"
10 #include "unity.h"
11
12 #include <Mockfwk_core.h>
13 #include <Mockfwk_id.h>
14 #include <Mockfwk_mm.h>
15 #include <Mockfwk_module.h>
16 #include <Mockfwk_notification.h>
17 #include <config_mpmm.h>
18
19 #include <internal/Mockfwk_core_internal.h>
20
21 #include <mod_power_domain.h>
22 #include <mod_scmi_perf.h>
23
24 #include <fwk_element.h>
25 #include <fwk_macros.h>
26 #include <fwk_module_idx.h>
27 #include <fwk_notification.h>
28
29 #include UNIT_TEST_SRC
30
31 uint64_t fake_amu_counter[AMU_COUNT] = {
32 0xAAAA1111AAAA1111, 0xAAAA2222AAAA2222, 0xAAAA3333AAAA3333,
33 0xAAAA4444AAAA4444, 0xAAAA5555AAAA5555, 0xAAAA6666AAAA6666,
34 0xAAAA7777AAAA7777,
35 };
36
fake_plugin_set_limits(struct plugin_limits_req * data)37 int fake_plugin_set_limits(struct plugin_limits_req *data)
38 {
39 return FWK_SUCCESS;
40 }
41
amu_mmap_copy_data(fwk_id_t start_counter_id,uint64_t * counter_buff,size_t num_counter)42 int amu_mmap_copy_data(
43 fwk_id_t start_counter_id,
44 uint64_t *counter_buff,
45 size_t num_counter)
46 {
47 memcpy(
48 counter_buff,
49 &fake_amu_counter[start_counter_id.sub_element.sub_element_idx],
50 sizeof(uint64_t) * num_counter);
51 return FWK_SUCCESS;
52 }
53
amu_mmap_return_error(fwk_id_t start_counter_id,uint64_t * counter_buff,size_t num_counter)54 int amu_mmap_return_error(
55 fwk_id_t start_counter_id,
56 uint64_t *counter_buff,
57 size_t num_counter)
58 {
59 return FWK_E_RANGE;
60 }
61
62 uint32_t adj_max_limit = 0xFF;
63 struct mod_mpmm_domain_ctx dev_ctx_table[1];
64 struct perf_plugins_perf_update perf_update = {
65 .domain_id = FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_SCMI_PERF, 0, 0),
66 .adj_max_limit = &adj_max_limit,
67 };
68 struct perf_plugins_perf_report fake_perf_report = {
69 .dep_dom_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0),
70 .level = 0xFF,
71 };
72 struct perf_plugins_handler_api handler_api = {
73 .plugin_set_limits = fake_plugin_set_limits,
74 };
75 struct amu_api amu_api = {
76 .get_counters = amu_mmap_copy_data,
77 };
78
setUp(void)79 void setUp(void)
80 {
81 struct mod_mpmm_domain_ctx *domain_ctx;
82
83 mpmm_ctx.mpmm_domain_count = 1;
84 mpmm_ctx.domain_ctx = domain_ctx = &dev_ctx_table[0];
85 mpmm_ctx.perf_plugins_handler_api = &handler_api;
86 mpmm_ctx.amu_driver_api = &amu_api;
87 mpmm_ctx.amu_driver_api_id =
88 FWK_ID_API(FWK_MODULE_IDX_AMU_MMAP, MOD_AMU_MMAP_API_IDX_AMU);
89
90 domain_ctx->domain_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
91 domain_ctx->num_cores = 1;
92 domain_ctx->num_cores_online = 0;
93 domain_ctx->perf_limit = 1;
94 domain_ctx->wait_for_perf_transition = true;
95 domain_ctx->domain_config = &fake_dom_conf[MPMM_DOM_DEFAULT];
96 }
97
tearDown(void)98 void tearDown(void)
99 {
100 }
101
utest_mpmm_start_mod_id_success(void)102 void utest_mpmm_start_mod_id_success(void)
103 {
104 int status;
105
106 fwk_module_is_valid_module_id_ExpectAndReturn(fwk_module_id_mpmm, true);
107
108 status = mpmm_start(fwk_module_id_mpmm);
109 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
110 }
111
utest_mpmm_start_notif_subscribe_success(void)112 void utest_mpmm_start_notif_subscribe_success(void)
113 {
114 int status;
115 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
116
117 fwk_module_is_valid_module_id_ExpectAndReturn(elem_id, false);
118 fwk_id_get_element_idx_ExpectAndReturn(elem_id, 0);
119 fwk_notification_subscribe_ExpectAndReturn(
120 mod_pd_notification_id_power_state_pre_transition,
121 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
122 mpmm_ctx.domain_ctx->domain_id,
123 FWK_SUCCESS);
124 fwk_notification_subscribe_ExpectAndReturn(
125 mod_pd_notification_id_power_state_transition,
126 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
127 mpmm_ctx.domain_ctx->domain_id,
128 FWK_SUCCESS);
129
130 status = mpmm_start(elem_id);
131 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
132 }
133
utest_mpmm_start_notif_subscribe_pre_transition_fail(void)134 void utest_mpmm_start_notif_subscribe_pre_transition_fail(void)
135 {
136 int status;
137 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
138
139 fwk_module_is_valid_module_id_ExpectAndReturn(elem_id, false);
140 fwk_id_get_element_idx_ExpectAndReturn(elem_id, 0);
141
142 fwk_notification_subscribe_ExpectAndReturn(
143 mod_pd_notification_id_power_state_pre_transition,
144 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
145 mpmm_ctx.domain_ctx->domain_id,
146 FWK_E_STATE);
147
148 status = mpmm_start(elem_id);
149 TEST_ASSERT_EQUAL(FWK_E_STATE, status);
150 }
151
utest_mpmm_start_notif_subscribe_post_transition_fail(void)152 void utest_mpmm_start_notif_subscribe_post_transition_fail(void)
153 {
154 int status;
155 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
156
157 fwk_module_is_valid_module_id_ExpectAndReturn(elem_id, false);
158 fwk_id_get_element_idx_ExpectAndReturn(elem_id, 0);
159 fwk_notification_subscribe_ExpectAndReturn(
160 mod_pd_notification_id_power_state_pre_transition,
161 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
162 mpmm_ctx.domain_ctx->domain_id,
163 FWK_SUCCESS);
164 fwk_notification_subscribe_ExpectAndReturn(
165 mod_pd_notification_id_power_state_transition,
166 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
167 mpmm_ctx.domain_ctx->domain_id,
168 FWK_E_STATE);
169
170 status = mpmm_start(elem_id);
171 TEST_ASSERT_EQUAL(FWK_E_STATE, status);
172 }
173
utest_mpmm_init_success(void)174 void utest_mpmm_init_success(void)
175 {
176 int status;
177 unsigned int count = 1;
178 struct mod_mpmm_domain_ctx domain_ctx;
179 fwk_id_t api_id =
180 FWK_ID_API_INIT(FWK_MODULE_IDX_AMU_MMAP, MOD_AMU_MMAP_API_IDX_AMU);
181
182 fwk_mm_calloc_ExpectAndReturn(
183 count, sizeof(struct mod_mpmm_domain_ctx), &domain_ctx);
184
185 status = mpmm_init(fwk_module_id_mpmm, count, &api_id);
186 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
187 TEST_ASSERT_EQUAL(count, mpmm_ctx.mpmm_domain_count);
188 TEST_ASSERT_EQUAL_PTR(&domain_ctx, mpmm_ctx.domain_ctx);
189 TEST_ASSERT_EQUAL(api_id.value, mpmm_ctx.amu_driver_api_id.value);
190 }
191
utest_mpmm_init_element_count_fail(void)192 void utest_mpmm_init_element_count_fail(void)
193 {
194 int status;
195
196 status = mpmm_init(fwk_module_id_mpmm, 0, NULL);
197 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
198 }
199
utest_mpmm_element_init_two_core_success(void)200 void utest_mpmm_element_init_two_core_success(void)
201 {
202 int status;
203 uint64_t cached_counters[CORE_IDX_COUNT];
204 uint64_t delta[CORE_IDX_COUNT];
205 unsigned int count = CORE_IDX_COUNT;
206 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
207
208 fwk_id_get_element_idx_ExpectAndReturn(elem_id, 0);
209 fwk_id_build_sub_element_id_IgnoreAndReturn(elem_id);
210 fwk_mm_calloc_ExpectAndReturn(
211 dev_ctx_table[0].domain_config->num_threshold_counters,
212 sizeof(*dev_ctx_table[0].core_ctx[CORE0_IDX].cached_counters),
213 &cached_counters[CORE0_IDX]);
214 fwk_mm_calloc_ExpectAndReturn(
215 dev_ctx_table[0].domain_config->num_threshold_counters,
216 sizeof(*dev_ctx_table[0].core_ctx[CORE0_IDX].delta),
217 &delta[CORE0_IDX]);
218 fwk_mm_calloc_ExpectAndReturn(
219 dev_ctx_table[0].domain_config->num_threshold_counters,
220 sizeof(*dev_ctx_table[0].core_ctx[CORE1_IDX].cached_counters),
221 &cached_counters[CORE1_IDX]);
222 fwk_mm_calloc_ExpectAndReturn(
223 dev_ctx_table[0].domain_config->num_threshold_counters,
224 sizeof(*dev_ctx_table[0].core_ctx[CORE1_IDX].delta),
225 &delta[CORE1_IDX]);
226
227 status =
228 mpmm_element_init(elem_id, count, &fake_dom_conf[MPMM_DOM_DEFAULT]);
229 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
230 TEST_ASSERT_EQUAL(count, dev_ctx_table[0].num_cores);
231 TEST_ASSERT_EQUAL(false, dev_ctx_table[0].wait_for_perf_transition);
232 TEST_ASSERT_EQUAL_PTR(
233 &fake_dom_conf[MPMM_DOM_DEFAULT], dev_ctx_table[0].domain_config);
234
235 /* CORE0_IDX */
236 TEST_ASSERT_EQUAL_PTR(
237 fake_core_config[0].mpmm_reg_base,
238 dev_ctx_table[0].core_ctx[CORE0_IDX].mpmm);
239 TEST_ASSERT_EQUAL(
240 fake_core_config[CORE0_IDX].base_aux_counter_id.value,
241 dev_ctx_table[0].core_ctx[CORE0_IDX].base_aux_counter_id.value);
242 TEST_ASSERT_EQUAL_PTR(
243 &cached_counters[CORE0_IDX],
244 dev_ctx_table[0].core_ctx[CORE0_IDX].cached_counters);
245 TEST_ASSERT_EQUAL_PTR(
246 &delta[CORE0_IDX], dev_ctx_table[0].core_ctx[CORE0_IDX].delta);
247
248 /* CORE1_IDX */
249 TEST_ASSERT_EQUAL_PTR(
250 fake_core_config[CORE1_IDX].mpmm_reg_base,
251 dev_ctx_table[0].core_ctx[CORE1_IDX].mpmm);
252 TEST_ASSERT_EQUAL(
253 fake_core_config[CORE1_IDX].base_aux_counter_id.value,
254 dev_ctx_table[0].core_ctx[CORE1_IDX].base_aux_counter_id.value);
255 TEST_ASSERT_EQUAL_PTR(
256 &cached_counters[CORE1_IDX],
257 dev_ctx_table[0].core_ctx[CORE1_IDX].cached_counters);
258 TEST_ASSERT_EQUAL_PTR(
259 &delta[CORE1_IDX], dev_ctx_table[0].core_ctx[CORE1_IDX].delta);
260 }
261
utest_mpmm_element_init_element_count_0_fail(void)262 void utest_mpmm_element_init_element_count_0_fail(void)
263 {
264 int status;
265 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
266
267 status = mpmm_element_init(elem_id, 0, NULL);
268 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
269 }
270
utest_mpmm_element_init_element_count_max_fail(void)271 void utest_mpmm_element_init_element_count_max_fail(void)
272 {
273 int status;
274 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
275
276 status =
277 mpmm_element_init(elem_id, (MPMM_MAX_NUM_CORES_IN_DOMAIN + 1), NULL);
278 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
279 }
280
utest_mpmm_element_init_max_threshold_count_fail(void)281 void utest_mpmm_element_init_max_threshold_count_fail(void)
282 {
283 int status;
284 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
285
286 fwk_id_get_element_idx_ExpectAndReturn(elem_id, 0);
287
288 status = mpmm_element_init(
289 elem_id, 1, &fake_dom_conf[MPMM_DOM_MAX_THRESHOLD_COUNT]);
290 TEST_ASSERT_EQUAL(FWK_E_SUPPORT, status);
291 }
292
utest_mpmm_element_init_num_threshold_mismatch(void)293 void utest_mpmm_element_init_num_threshold_mismatch(void)
294 {
295 int status;
296 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
297
298 fwk_id_get_element_idx_ExpectAndReturn(elem_id, 0);
299 fwk_id_build_sub_element_id_IgnoreAndReturn(elem_id);
300
301 status = mpmm_element_init(
302 elem_id, 1, &fake_dom_conf[MPMM_DOM_NUM_THRESHOLD_NOT_EQUAL]);
303 TEST_ASSERT_EQUAL(FWK_E_DEVICE, status);
304 }
305
utest_mpmm_bind_first_round_success(void)306 void utest_mpmm_bind_first_round_success(void)
307 {
308 int status;
309 unsigned int round = 0;
310
311 status = mpmm_bind(fwk_module_id_mpmm, round);
312 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
313 }
314
utest_mpmm_bind_invalid_module_success(void)315 void utest_mpmm_bind_invalid_module_success(void)
316 {
317 int status;
318 unsigned int round = 1;
319
320 fwk_module_is_valid_module_id_ExpectAndReturn(fwk_module_id_mpmm, false);
321
322 status = mpmm_bind(fwk_module_id_mpmm, round);
323 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
324 }
325
utest_mpmm_bind_module_bind_success(void)326 void utest_mpmm_bind_module_bind_success(void)
327 {
328 int status;
329 unsigned int round = 1;
330
331 fwk_module_is_valid_module_id_ExpectAndReturn(fwk_module_id_mpmm, true);
332 fwk_module_bind_ExpectAndReturn(
333 FWK_ID_MODULE(mpmm_ctx.amu_driver_api_id.common.module_idx),
334 mpmm_ctx.amu_driver_api_id,
335 &mpmm_ctx.amu_driver_api,
336 FWK_SUCCESS);
337 fwk_module_bind_ExpectAndReturn(
338 FWK_ID_MODULE(FWK_MODULE_IDX_SCMI_PERF),
339 FWK_ID_API(FWK_MODULE_IDX_SCMI_PERF, MOD_SCMI_PERF_PLUGINS_API),
340 &mpmm_ctx.perf_plugins_handler_api,
341 FWK_SUCCESS);
342
343 status = mpmm_bind(fwk_module_id_mpmm, round);
344 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
345 }
346
utest_mpmm_bind_amu_bind_fail(void)347 void utest_mpmm_bind_amu_bind_fail(void)
348 {
349 int status;
350 unsigned int round = 1;
351
352 fwk_module_is_valid_module_id_ExpectAndReturn(fwk_module_id_mpmm, true);
353 fwk_module_bind_ExpectAndReturn(
354 FWK_ID_MODULE(mpmm_ctx.amu_driver_api_id.common.module_idx),
355 mpmm_ctx.amu_driver_api_id,
356 &mpmm_ctx.amu_driver_api,
357 FWK_E_PARAM);
358
359 status = mpmm_bind(fwk_module_id_mpmm, round);
360 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
361 }
362
utest_mpmm_process_bind_request_success(void)363 void utest_mpmm_process_bind_request_success(void)
364 {
365 int status;
366 const void *api = NULL;
367
368 fwk_id_is_equal_ExpectAndReturn(
369 fwk_module_id_scmi_perf, FWK_ID_MODULE(FWK_MODULE_IDX_SCMI_PERF), true);
370
371 status = mpmm_process_bind_request(
372 fwk_module_id_scmi_perf, fwk_module_id_mpmm, fwk_module_id_mpmm, &api);
373 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
374 TEST_ASSERT_EQUAL_PTR(&perf_plugins_api, api);
375 }
376
utest_mpmm_process_bind_request_id_not_equal(void)377 void utest_mpmm_process_bind_request_id_not_equal(void)
378 {
379 int status;
380
381 fwk_id_is_equal_ExpectAndReturn(
382 fwk_module_id_mpmm, FWK_ID_MODULE(FWK_MODULE_IDX_SCMI_PERF), false);
383
384 status = mpmm_process_bind_request(
385 fwk_module_id_mpmm, fwk_module_id_mpmm, fwk_module_id_mpmm, NULL);
386 TEST_ASSERT_EQUAL(FWK_E_ACCESS, status);
387 }
388
utest_mpmm_process_notification_pre_state_to_on(void)389 void utest_mpmm_process_notification_pre_state_to_on(void)
390 {
391 int status;
392 struct mod_pd_power_state_pre_transition_notification_params *params;
393 struct fwk_event event = { .target_id =
394 FWK_ID_EVENT(FWK_MODULE_IDX_MPMM, 0) };
395 struct fwk_event resp_event = { 0 };
396
397 dev_ctx_table[0].num_cores_online = 0;
398 dev_ctx_table[0].core_ctx[0].online = true;
399 dev_ctx_table[0].threshold_map = 1;
400 dev_ctx_table[0].current_perf_level =
401 fake_pct_table[FAKE_PCT_TABLE_COUNT - 1].default_perf_limit + 1;
402 dev_ctx_table[0].core_ctx[0].pd_blocked = false;
403 params = (struct mod_pd_power_state_pre_transition_notification_params *)
404 event.params;
405 params->current_state = MOD_PD_STATE_OFF;
406 params->target_state = MOD_PD_STATE_ON;
407
408 fwk_module_is_valid_element_id_ExpectAndReturn(event.target_id, true);
409 fwk_id_get_element_idx_ExpectAndReturn(event.target_id, 0);
410 fwk_id_is_equal_ExpectAndReturn(
411 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
412 event.source_id,
413 true);
414 fwk_id_is_equal_ExpectAndReturn(
415 event.id, mod_pd_notification_id_power_state_pre_transition, true);
416
417 status = mpmm_process_notification(&event, &resp_event);
418 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
419 TEST_ASSERT_EQUAL(1, mpmm_ctx.domain_ctx->num_cores_online);
420 TEST_ASSERT_EQUAL(true, mpmm_ctx.domain_ctx->core_ctx[0].online);
421 TEST_ASSERT_EQUAL(
422 (1 << MPMM_THRESHOLD_MAP_NUM_OF_BITS),
423 mpmm_ctx.domain_ctx->threshold_map);
424 TEST_ASSERT_EQUAL(
425 fake_pct_table[FAKE_PCT_TABLE_COUNT - 1].default_perf_limit,
426 mpmm_ctx.domain_ctx->perf_limit);
427 TEST_ASSERT_EQUAL(true, mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked);
428 TEST_ASSERT_EQUAL(true, mpmm_ctx.domain_ctx->wait_for_perf_transition);
429 TEST_ASSERT_EQUAL(true, resp_event.is_delayed_response);
430 TEST_ASSERT_EQUAL(event.cookie, mpmm_ctx.domain_ctx->core_ctx[0].cookie);
431 }
432
utest_mpmm_process_notification_post_state_to_off(void)433 void utest_mpmm_process_notification_post_state_to_off(void)
434 {
435 int status;
436 struct mod_pd_power_state_transition_notification_params *params;
437 struct fwk_event event = { .target_id =
438 FWK_ID_EVENT(FWK_MODULE_IDX_MPMM, 0) };
439 struct fwk_event resp_event = { 0 };
440
441 mpmm_ctx.domain_ctx->num_cores_online = 1;
442 params = (struct mod_pd_power_state_transition_notification_params *)
443 event.params;
444 params->state = MOD_PD_STATE_OFF;
445
446 fwk_module_is_valid_element_id_ExpectAndReturn(event.target_id, true);
447 fwk_id_get_element_idx_ExpectAndReturn(event.target_id, 0);
448 fwk_id_is_equal_ExpectAndReturn(
449 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
450 event.source_id,
451 true);
452 fwk_id_is_equal_ExpectAndReturn(
453 event.id, mod_pd_notification_id_power_state_pre_transition, false);
454 fwk_id_is_equal_ExpectAndReturn(
455 event.id, mod_pd_notification_id_power_state_transition, true);
456
457 status = mpmm_process_notification(&event, &resp_event);
458 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
459 TEST_ASSERT_EQUAL(0, mpmm_ctx.domain_ctx->num_cores_online);
460 TEST_ASSERT_EQUAL(false, mpmm_ctx.domain_ctx->core_ctx[0].online);
461 }
462
utest_mpmm_process_notification_core_idx_larger(void)463 void utest_mpmm_process_notification_core_idx_larger(void)
464 {
465 int status;
466 struct fwk_event event = { .target_id =
467 FWK_ID_EVENT(FWK_MODULE_IDX_MPMM, 0) };
468 struct fwk_event resp_event = { 0 };
469
470 fwk_module_is_valid_element_id_ExpectAndReturn(event.target_id, true);
471 fwk_id_get_element_idx_ExpectAndReturn(event.target_id, 0);
472 fwk_id_is_equal_ExpectAndReturn(
473 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
474 event.source_id,
475 false);
476
477 status = mpmm_process_notification(&event, &resp_event);
478 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
479 }
480
utest_mpmm_process_notification_no_perf_change(void)481 void utest_mpmm_process_notification_no_perf_change(void)
482 {
483 int status;
484 struct mod_pd_power_state_pre_transition_notification_params *params;
485 struct fwk_event event = { .target_id =
486 FWK_ID_EVENT(FWK_MODULE_IDX_MPMM, 0) };
487 struct fwk_event resp_event = { 0 };
488
489 dev_ctx_table[0].num_cores_online = 0;
490 dev_ctx_table[0].core_ctx[0].online = true;
491 dev_ctx_table[0].threshold_map = 1;
492 dev_ctx_table[0].current_perf_level = 0;
493 dev_ctx_table[0].core_ctx[0].pd_blocked = false;
494
495 params = (struct mod_pd_power_state_pre_transition_notification_params *)
496 event.params;
497 params->target_state = MOD_PD_STATE_ON;
498
499 fwk_module_is_valid_element_id_ExpectAndReturn(event.target_id, true);
500 fwk_id_get_element_idx_ExpectAndReturn(event.target_id, 0);
501 fwk_id_is_equal_ExpectAndReturn(
502 mpmm_ctx.domain_ctx->domain_config->core_config[0].pd_id,
503 event.source_id,
504 true);
505 fwk_id_is_equal_ExpectAndReturn(
506 event.id, mod_pd_notification_id_power_state_pre_transition, true);
507
508 status = mpmm_process_notification(&event, &resp_event);
509 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
510 TEST_ASSERT_EQUAL(1, mpmm_ctx.domain_ctx->num_cores_online);
511 TEST_ASSERT_EQUAL(true, mpmm_ctx.domain_ctx->core_ctx[0].online);
512 TEST_ASSERT_EQUAL(
513 (1 << MPMM_THRESHOLD_MAP_NUM_OF_BITS),
514 mpmm_ctx.domain_ctx->threshold_map);
515 TEST_ASSERT_EQUAL(
516 fake_pct_table[FAKE_PCT_TABLE_COUNT - 1].default_perf_limit,
517 mpmm_ctx.domain_ctx->perf_limit);
518 TEST_ASSERT_EQUAL(false, mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked);
519 }
520
utest_mpmm_update_success(void)521 void utest_mpmm_update_success(void)
522 {
523 int status;
524 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
525
526 mpmm_ctx.domain_ctx->num_cores_online = 1;
527 *perf_update.adj_max_limit = 0xFF;
528
529 fwk_id_get_element_idx_ExpectAndReturn(perf_update.domain_id, 0);
530 fwk_id_is_equal_ExpectAndReturn(
531 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
532
533 status = mpmm_update(&perf_update);
534 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
535 TEST_ASSERT_EQUAL(
536 mpmm_ctx.domain_ctx->perf_limit, *perf_update.adj_max_limit);
537 }
538
utest_mpmm_update_domain_idx_not_found(void)539 void utest_mpmm_update_domain_idx_not_found(void)
540 {
541 int status;
542 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
543 *perf_update.adj_max_limit = 0xFF;
544
545 fwk_id_get_element_idx_ExpectAndReturn(perf_update.domain_id, 0);
546 fwk_id_is_equal_ExpectAndReturn(
547 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, false);
548
549 status = mpmm_update(&perf_update);
550 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
551 TEST_ASSERT_EQUAL(0xFF, *perf_update.adj_max_limit);
552 }
553
utest_mpmm_update_no_cores_online(void)554 void utest_mpmm_update_no_cores_online(void)
555 {
556 int status;
557 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
558 dev_ctx_table[0].num_cores_online = 0;
559 *perf_update.adj_max_limit = 0xFF;
560
561 fwk_id_get_element_idx_ExpectAndReturn(perf_update.domain_id, 0);
562 fwk_id_is_equal_ExpectAndReturn(
563 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
564
565 status = mpmm_update(&perf_update);
566 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
567 TEST_ASSERT_EQUAL(0xFF, *perf_update.adj_max_limit);
568 }
569
utest_mpmm_update_wait_for_perf_transition(void)570 void utest_mpmm_update_wait_for_perf_transition(void)
571 {
572 int status;
573 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
574
575 mpmm_ctx.domain_ctx->num_cores_online = 1;
576 mpmm_ctx.domain_ctx->current_perf_level =
577 mpmm_ctx.domain_ctx->perf_limit + 1;
578 mpmm_ctx.domain_ctx->wait_for_perf_transition = false;
579 *perf_update.adj_max_limit = 0xFF;
580
581 fwk_id_get_element_idx_ExpectAndReturn(perf_update.domain_id, 0);
582 fwk_id_is_equal_ExpectAndReturn(
583 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
584
585 status = mpmm_update(&perf_update);
586 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
587 TEST_ASSERT_EQUAL(
588 mpmm_ctx.domain_ctx->perf_limit, *perf_update.adj_max_limit);
589 TEST_ASSERT_EQUAL(true, mpmm_ctx.domain_ctx->wait_for_perf_transition);
590 }
591
utest_mpmm_report_success(void)592 void utest_mpmm_report_success(void)
593 {
594 int status;
595 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
596
597 mpmm_ctx.domain_ctx->wait_for_perf_transition = true;
598 dev_ctx_table[0].core_ctx[0].pd_blocked = false;
599 dev_ctx_table[0].current_perf_level = 0;
600
601 fwk_id_get_element_idx_ExpectAndReturn(fake_perf_report.dep_dom_id, 0);
602 fwk_id_is_equal_ExpectAndReturn(
603 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
604
605 status = mpmm_report(&fake_perf_report);
606 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
607 TEST_ASSERT_EQUAL(
608 fake_perf_report.level, mpmm_ctx.domain_ctx->current_perf_level);
609 TEST_ASSERT_EQUAL(false, mpmm_ctx.domain_ctx->wait_for_perf_transition);
610 TEST_ASSERT_EQUAL(false, mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked);
611 }
612
utest_mpmm_report_domain_idx_not_found(void)613 void utest_mpmm_report_domain_idx_not_found(void)
614 {
615 int status;
616 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
617
618 fwk_id_get_element_idx_ExpectAndReturn(fake_perf_report.dep_dom_id, 0);
619 fwk_id_is_equal_ExpectAndReturn(
620 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, false);
621
622 status = mpmm_report(&fake_perf_report);
623 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
624 }
625
utest_mpmm_report_no_wait_for_perf_transition(void)626 void utest_mpmm_report_no_wait_for_perf_transition(void)
627 {
628 int status;
629 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
630
631 mpmm_ctx.domain_ctx->wait_for_perf_transition = false;
632 dev_ctx_table[0].current_perf_level = 0;
633
634 fwk_id_get_element_idx_ExpectAndReturn(fake_perf_report.dep_dom_id, 0);
635 fwk_id_is_equal_ExpectAndReturn(
636 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
637
638 status = mpmm_report(&fake_perf_report);
639 TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
640 TEST_ASSERT_EQUAL(
641 fake_perf_report.level, mpmm_ctx.domain_ctx->current_perf_level);
642 }
643
utest_mpmm_report_pd_blocked_delayed_resp_fail(void)644 void utest_mpmm_report_pd_blocked_delayed_resp_fail(void)
645 {
646 int status;
647 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
648
649 fwk_id_get_element_idx_ExpectAndReturn(fake_perf_report.dep_dom_id, 0);
650 fwk_id_is_equal_ExpectAndReturn(
651 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
652 fwk_get_delayed_response_ExpectAnyArgsAndReturn(FWK_E_PARAM);
653
654 mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked = true;
655
656 status = mpmm_report(&fake_perf_report);
657 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
658 TEST_ASSERT_EQUAL(false, mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked);
659 }
660
utest_mpmm_report_pd_blocked_put_event_fail(void)661 void utest_mpmm_report_pd_blocked_put_event_fail(void)
662 {
663 int status;
664 fwk_id_t perf_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_DVFS, 0);
665
666 fwk_id_get_element_idx_ExpectAndReturn(fake_perf_report.dep_dom_id, 0);
667 fwk_id_is_equal_ExpectAndReturn(
668 mpmm_ctx.domain_ctx->domain_config->perf_id, perf_id, true);
669 fwk_get_delayed_response_ExpectAnyArgsAndReturn(FWK_SUCCESS);
670 __fwk_put_event_ExpectAnyArgsAndReturn(FWK_E_PARAM);
671
672 mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked = true;
673
674 status = mpmm_report(&fake_perf_report);
675 TEST_ASSERT_EQUAL(FWK_E_PARAM, status);
676 TEST_ASSERT_EQUAL(false, mpmm_ctx.domain_ctx->core_ctx[0].pd_blocked);
677 }
678
utest_mpmm_core_evaluate_threshold_success(void)679 void utest_mpmm_core_evaluate_threshold_success(void)
680 {
681 uint64_t cached_counters = 0;
682 uint64_t delta = 0;
683 struct mpmm_reg mpmm = { .MPMMCR = MPMM_MPMMCR_EN_MASK };
684 struct mod_mpmm_core_ctx core_ctx_table;
685
686 core_ctx_table.mpmm = &mpmm;
687 core_ctx_table.base_aux_counter_id =
688 FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_AMU_MMAP, CORE0_IDX, AMU_AUX0);
689 core_ctx_table.cached_counters = &cached_counters;
690 core_ctx_table.delta = δ
691 core_ctx_table.threshold = 0xFFFFFFFF;
692
693 mpmm_core_evaluate_threshold(&dev_ctx_table[0], &core_ctx_table);
694 TEST_ASSERT_EQUAL(
695 (dev_ctx_table[0].domain_config->num_threshold_counters - 1),
696 core_ctx_table.threshold);
697 TEST_ASSERT_EQUAL(
698 fake_amu_counter[AMU_AUX0], *core_ctx_table.cached_counters);
699 TEST_ASSERT_EQUAL(fake_amu_counter[AMU_AUX0], *core_ctx_table.delta);
700 }
701
utest_mpmm_core_evaluate_threshold_counter_not_enabled(void)702 void utest_mpmm_core_evaluate_threshold_counter_not_enabled(void)
703 {
704 struct mpmm_reg mpmm = { .MPMMCR = 0 };
705 struct mod_mpmm_core_ctx core_ctx_table;
706
707 core_ctx_table.mpmm = &mpmm;
708
709 mpmm_core_evaluate_threshold(&dev_ctx_table[0], &core_ctx_table);
710 TEST_ASSERT_EQUAL(
711 dev_ctx_table[0].domain_config->num_threshold_counters,
712 core_ctx_table.threshold);
713 }
714
utest_mpmm_domain_set_thresholds_success(void)715 void utest_mpmm_domain_set_thresholds_success(void)
716 {
717 struct mpmm_reg mpmm = { 0 };
718
719 dev_ctx_table[0].core_ctx[0].mpmm = &mpmm;
720 dev_ctx_table[0].core_ctx[0].online = true;
721
722 mpmm_domain_set_thresholds(&dev_ctx_table[0]);
723 TEST_ASSERT_EQUAL(
724 (1 << MPMM_MPMMCR_GEAR_POS), dev_ctx_table[0].core_ctx[0].mpmm->MPMMCR);
725 }
726
utest_get_domain_ctx_null(void)727 void utest_get_domain_ctx_null(void)
728 {
729 struct mod_mpmm_domain_ctx *domain_ctx;
730 fwk_id_t elem_id = FWK_ID_ELEMENT(FWK_MODULE_IDX_MPMM, 0);
731
732 fwk_id_get_element_idx_ExpectAndReturn(elem_id, mpmm_ctx.mpmm_domain_count);
733
734 domain_ctx = get_domain_ctx(elem_id);
735 TEST_ASSERT_EQUAL(NULL, domain_ctx);
736 }
737
utest_mpmm_core_threshold_policy_highest_gear(void)738 void utest_mpmm_core_threshold_policy_highest_gear(void)
739 {
740 uint32_t gear;
741 uint64_t delta = 0;
742 struct mod_mpmm_core_ctx core_ctx_table;
743
744 core_ctx_table.delta = δ
745
746 gear = mpmm_core_threshold_policy(&dev_ctx_table[0], &core_ctx_table);
747 TEST_ASSERT_EQUAL(
748 (dev_ctx_table[0].domain_config->num_threshold_counters - 1), gear);
749 }
750
utest_find_perf_limit_from_pct_default_limit(void)751 void utest_find_perf_limit_from_pct_default_limit(void)
752 {
753 uint32_t perf_limit;
754 uint32_t threshold_map =
755 (fake_pct_table[FAKE_PCT_TABLE_NO_THRESHOLD_BITMAP]
756 .threshold_perf->threshold_bitmap +
757 1);
758
759 perf_limit = find_perf_limit_from_pct(
760 &fake_pct_table[FAKE_PCT_TABLE_NO_THRESHOLD_BITMAP], threshold_map);
761 TEST_ASSERT_EQUAL(
762 fake_pct_table[FAKE_PCT_TABLE_NO_THRESHOLD_BITMAP].default_perf_limit,
763 perf_limit);
764 }
765
utest_mpmm_evaluate_perf_limit_no_entry(void)766 void utest_mpmm_evaluate_perf_limit_no_entry(void)
767 {
768 uint32_t perf_limit;
769
770 mpmm_ctx.domain_ctx->num_cores_online = 2;
771 dev_ctx_table[0].threshold_map = 0;
772
773 perf_limit = mpmm_evaluate_perf_limit(mpmm_ctx.domain_ctx);
774 TEST_ASSERT_EQUAL(
775 fake_pct_table[FAKE_PCT_TABLE_DEFAULT].threshold_perf->perf_limit,
776 perf_limit);
777 }
778
utest_mpmm_monitor_and_control_no_cores_online(void)779 void utest_mpmm_monitor_and_control_no_cores_online(void)
780 {
781 uint32_t prev_perf_limit = mpmm_ctx.domain_ctx->perf_limit;
782
783 mpmm_ctx.domain_ctx->num_cores_online = 0;
784
785 mpmm_monitor_and_control(mpmm_ctx.domain_ctx);
786 TEST_ASSERT_EQUAL(prev_perf_limit, mpmm_ctx.domain_ctx->perf_limit);
787 }
788
utest_mpmm_core_counters_delta_read_two_counter(void)789 void utest_mpmm_core_counters_delta_read_two_counter(void)
790 {
791 /* Initialize cached_counter to a random value to check delta calculation */
792 uint64_t cached_counters[2] = { 0x1111, 0x2222 };
793 uint64_t delta[2] = { 0 };
794 struct mod_mpmm_core_ctx core_ctx_table;
795
796 core_ctx_table.base_aux_counter_id =
797 FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_AMU_MMAP, CORE0_IDX, AMU_AUX0);
798 core_ctx_table.cached_counters = cached_counters;
799 core_ctx_table.delta = delta;
800 mpmm_ctx.amu_driver_api->get_counters = &amu_mmap_copy_data;
801 dev_ctx_table[0].domain_config =
802 &fake_dom_conf[MPMM_DOM_TWO_THRESHOLD_COUNTER];
803
804 mpmm_core_counters_delta(&dev_ctx_table[0], &core_ctx_table);
805
806 TEST_ASSERT_EQUAL(
807 fake_amu_counter[AMU_AUX0], core_ctx_table.cached_counters[0]);
808 TEST_ASSERT_EQUAL(
809 (fake_amu_counter[AMU_AUX0] - 0x1111), core_ctx_table.delta[0]);
810
811 TEST_ASSERT_EQUAL(
812 fake_amu_counter[AMU_AUX1], core_ctx_table.cached_counters[1]);
813 TEST_ASSERT_EQUAL(
814 (fake_amu_counter[AMU_AUX1] - 0x2222), core_ctx_table.delta[1]);
815 }
816
utest_mpmm_core_counters_delta_wraparound(void)817 void utest_mpmm_core_counters_delta_wraparound(void)
818 {
819 /* Initialize cached_counter to value close to max to trigger wraparound */
820 uint64_t cached_counters = UINT64_MAX - 5;
821 uint64_t delta = 0;
822 struct mod_mpmm_core_ctx core_ctx_table;
823
824 core_ctx_table.base_aux_counter_id =
825 FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_AMU_MMAP, CORE0_IDX, AMU_AUX0);
826 core_ctx_table.cached_counters = &cached_counters;
827 core_ctx_table.delta = δ
828 mpmm_ctx.amu_driver_api->get_counters = &amu_mmap_copy_data;
829
830 mpmm_core_counters_delta(&dev_ctx_table[0], &core_ctx_table);
831 TEST_ASSERT_EQUAL(
832 fake_amu_counter[AMU_AUX0], *core_ctx_table.cached_counters);
833 TEST_ASSERT_EQUAL(fake_amu_counter[AMU_AUX0] + 5, *core_ctx_table.delta);
834 }
835
utest_mpmm_core_counters_delta_read_fail(void)836 void utest_mpmm_core_counters_delta_read_fail(void)
837 {
838 uint64_t cached_counters = UINT64_MAX;
839 uint64_t delta = UINT64_MAX;
840 struct mod_mpmm_core_ctx core_ctx_table;
841
842 core_ctx_table.base_aux_counter_id =
843 FWK_ID_SUB_ELEMENT(FWK_MODULE_IDX_AMU_MMAP, CORE0_IDX, AMU_AUX0);
844 core_ctx_table.cached_counters = &cached_counters;
845 core_ctx_table.delta = δ
846 mpmm_ctx.amu_driver_api->get_counters = &amu_mmap_return_error;
847
848 mpmm_core_counters_delta(&dev_ctx_table[0], &core_ctx_table);
849 /* cached_counters and delta should remain the same if read fail */
850 TEST_ASSERT_EQUAL(UINT64_MAX, *core_ctx_table.cached_counters);
851 TEST_ASSERT_EQUAL(UINT64_MAX, *core_ctx_table.delta);
852 }
853
mod_mpmm_test_main(void)854 int mod_mpmm_test_main(void)
855 {
856 UNITY_BEGIN();
857
858 RUN_TEST(utest_mpmm_start_mod_id_success);
859 RUN_TEST(utest_mpmm_start_notif_subscribe_success);
860 RUN_TEST(utest_mpmm_start_notif_subscribe_pre_transition_fail);
861 RUN_TEST(utest_mpmm_start_notif_subscribe_post_transition_fail);
862
863 RUN_TEST(utest_mpmm_init_success);
864 RUN_TEST(utest_mpmm_init_element_count_fail);
865
866 RUN_TEST(utest_mpmm_element_init_two_core_success);
867 RUN_TEST(utest_mpmm_element_init_element_count_0_fail);
868 RUN_TEST(utest_mpmm_element_init_element_count_max_fail);
869 RUN_TEST(utest_mpmm_element_init_max_threshold_count_fail);
870 RUN_TEST(utest_mpmm_element_init_num_threshold_mismatch);
871
872 RUN_TEST(utest_mpmm_bind_first_round_success);
873 RUN_TEST(utest_mpmm_bind_invalid_module_success);
874 RUN_TEST(utest_mpmm_bind_module_bind_success);
875 RUN_TEST(utest_mpmm_bind_amu_bind_fail);
876
877 RUN_TEST(utest_mpmm_process_bind_request_success);
878 RUN_TEST(utest_mpmm_process_bind_request_id_not_equal);
879
880 RUN_TEST(utest_mpmm_process_notification_pre_state_to_on);
881 RUN_TEST(utest_mpmm_process_notification_post_state_to_off);
882 RUN_TEST(utest_mpmm_process_notification_core_idx_larger);
883 RUN_TEST(utest_mpmm_process_notification_no_perf_change);
884
885 RUN_TEST(utest_mpmm_update_success);
886 RUN_TEST(utest_mpmm_update_domain_idx_not_found);
887 RUN_TEST(utest_mpmm_update_no_cores_online);
888 RUN_TEST(utest_mpmm_update_wait_for_perf_transition);
889
890 RUN_TEST(utest_mpmm_report_success);
891 RUN_TEST(utest_mpmm_report_domain_idx_not_found);
892 RUN_TEST(utest_mpmm_report_no_wait_for_perf_transition);
893 RUN_TEST(utest_mpmm_report_pd_blocked_delayed_resp_fail);
894 RUN_TEST(utest_mpmm_report_pd_blocked_put_event_fail);
895
896 RUN_TEST(utest_mpmm_core_evaluate_threshold_success);
897 RUN_TEST(utest_mpmm_core_evaluate_threshold_counter_not_enabled);
898
899 RUN_TEST(utest_mpmm_domain_set_thresholds_success);
900
901 RUN_TEST(utest_get_domain_ctx_null);
902
903 RUN_TEST(utest_mpmm_core_threshold_policy_highest_gear);
904
905 RUN_TEST(utest_find_perf_limit_from_pct_default_limit);
906
907 RUN_TEST(utest_mpmm_evaluate_perf_limit_no_entry);
908
909 RUN_TEST(utest_mpmm_monitor_and_control_no_cores_online);
910
911 RUN_TEST(utest_mpmm_core_counters_delta_read_two_counter);
912 RUN_TEST(utest_mpmm_core_counters_delta_wraparound);
913 RUN_TEST(utest_mpmm_core_counters_delta_read_fail);
914
915 return UNITY_END();
916 }
917
918 #if !defined(TEST_ON_TARGET)
main(void)919 int main(void)
920 {
921 return mod_mpmm_test_main();
922 }
923 #endif
924