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 = &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 = &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 = &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 = &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