1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "scp_unity.h"
9 #include "unity.h"
10 
11 #include <internal/scmi_perf.h>
12 
13 #ifdef TEST_ON_TARGET
14 #    include <fwk_id.h>
15 #    include <fwk_module.h>
16 #else
17 #    include <Mockfwk_id.h>
18 #    include <Mockfwk_module.h>
19 
20 #    include <internal/Mockfwk_core_internal.h>
21 #endif
22 #include <Mockmod_scmi_perf_extra.h>
23 #include <config_scmi_perf.h>
24 
25 #include <mod_dvfs.h>
26 #include <mod_scmi_perf.h>
27 
28 #include <fwk_element.h>
29 #include <fwk_macros.h>
30 
31 #ifdef BUILD_HAS_SCMI_PERF_PLUGIN_HANDLER
32 #    include <perf_plugins_handler.c>
33 #    include <perf_plugins_handler.h>
34 #endif
35 
36 #include UNIT_TEST_SRC
37 
38 static struct mod_scmi_perf_ctx scmi_perf_ctx;
39 
40 struct mod_scmi_to_protocol_api *to_protocol_api = NULL;
41 
42 struct mod_scmi_from_protocol_api from_protocol_api = {
43     .get_agent_count = mod_scmi_from_protocol_api_get_agent_count,
44     .get_agent_id = mod_scmi_from_protocol_api_get_agent_id,
45     .get_agent_type = mod_scmi_from_protocol_api_get_agent_type,
46     .get_max_payload_size = mod_scmi_from_protocol_api_get_max_payload_size,
47     .write_payload = mod_scmi_from_protocol_api_write_payload,
48     .respond = mod_scmi_from_protocol_api_respond,
49     .notify = mod_scmi_from_protocol_api_notify,
50 };
51 
52 static const struct mod_dvfs_domain_api dvfs_domain_api = {
53     .get_current_opp = mod_dvfs_domain_api_get_current_opp,
54     .get_sustained_opp = mod_dvfs_domain_api_get_sustained_opp,
55     .get_nth_opp = mod_dvfs_domain_api_get_nth_opp,
56     .get_level_id = mod_dvfs_domain_api_get_level_id,
57     .get_opp_count = mod_dvfs_domain_api_get_opp_count,
58     .get_latency = mod_dvfs_domain_api_get_latency,
59     .set_level = mod_dvfs_domain_api_set_level,
60 };
61 
62 char *name = "Test Name";
63 
64 static int return_status;
65 
setUp(void)66 void setUp(void)
67 {
68     scmi_perf_ctx.scmi_api = &from_protocol_api;
69     scmi_perf_ctx.config = config_scmi_perf.data;
70     scmi_perf_ctx.domain_count = scmi_perf_ctx.config->perf_doms_count;
71 
72 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
73     scmi_perf_ctx.fast_channels_rate_limit = SCMI_PERF_FC_MIN_RATE_LIMIT;
74 #endif
75 
76     fwk_id_get_api_idx_ExpectAnyArgsAndReturn(MOD_SCMI_PERF_PROTOCOL_API);
77 
78     module_scmi_perf.process_bind_request(
79         fwk_module_id_scmi,
80         fwk_module_id_scmi_perf,
81         FWK_ID_API(FWK_MODULE_IDX_SCMI_PERF, 0),
82         (const void **)&to_protocol_api);
83 
84     scmi_perf_ctx.dvfs_api = &dvfs_domain_api;
85 }
86 
tearDown(void)87 void tearDown(void)
88 {
89 }
90 
91 /*
92  * Test that the scmi_perf_protocol_version_handler function returns the correct
93  * version of the protocol
94  */
95 
96 /* Check that the return values are as expected */
version_handler_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)97 int version_handler_respond_callback(
98     fwk_id_t service_id,
99     const void *payload,
100     size_t size,
101     int NumCalls)
102 {
103     struct scmi_protocol_version_p2a *return_values;
104     return_values = (struct scmi_protocol_version_p2a *)payload;
105 
106     TEST_ASSERT_EQUAL((int32_t)SCMI_SUCCESS, return_values->status);
107     TEST_ASSERT_EQUAL(SCMI_PROTOCOL_VERSION_PERF, return_values->version);
108 
109     return FWK_SUCCESS;
110 }
111 
version_handler_respond_callback_fail(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)112 int version_handler_respond_callback_fail(
113     fwk_id_t service_id,
114     const void *payload,
115     size_t size,
116     int NumCalls)
117 {
118     struct scmi_protocol_version_p2a *return_values;
119     return_values = (struct scmi_protocol_version_p2a *)payload;
120 
121     TEST_ASSERT_EQUAL(size, sizeof(int32_t));
122     TEST_ASSERT_EQUAL(return_status, return_values->status);
123 
124     return FWK_SUCCESS;
125 }
126 
utest_scmi_perf_message_handler_bad_message_id(void)127 void utest_scmi_perf_message_handler_bad_message_id(void)
128 {
129     int status;
130     fwk_id_t service_id =
131         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
132     struct scmi_protocol_version_p2a payload = { 0 };
133 
134     mod_scmi_from_protocol_api_respond_Stub(
135         version_handler_respond_callback_fail);
136 
137     return_status = SCMI_NOT_SUPPORTED;
138     status = scmi_perf_message_handler(
139         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
140         service_id,
141         (const uint32_t *)&payload,
142         payload_size_table[MOD_SCMI_PROTOCOL_VERSION],
143         MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL);
144 
145     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
146 }
147 
utest_scmi_perf_message_handler_not_found(void)148 void utest_scmi_perf_message_handler_not_found(void)
149 {
150     int status;
151     fwk_id_t service_id =
152         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
153     struct scmi_protocol_version_p2a payload = { 0 };
154 
155     mod_scmi_from_protocol_api_respond_Stub(
156         version_handler_respond_callback_fail);
157 
158     return_status = SCMI_NOT_FOUND;
159     status = scmi_perf_message_handler(
160         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
161         service_id,
162         (const uint32_t *)&payload,
163         payload_size_table[MOD_SCMI_PROTOCOL_VERSION],
164         FWK_ARRAY_SIZE(handler_table));
165 
166     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
167 }
168 
utest_scmi_perf_protocol_version_handler(void)169 void utest_scmi_perf_protocol_version_handler(void)
170 {
171     int status;
172     fwk_id_t service_id =
173         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
174 
175     uint32_t payload = 0;
176 
177     /*
178      * Whenever the mocked function mod_scmi_from_protocol_api_respond is
179      * encountered, the function version_handler_respond_callback will be called
180      */
181     mod_scmi_from_protocol_api_respond_Stub(version_handler_respond_callback);
182 
183     status = to_protocol_api->message_handler(
184         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
185         service_id,
186         (const uint32_t *)&payload,
187         payload_size_table[MOD_SCMI_PROTOCOL_VERSION],
188         MOD_SCMI_PROTOCOL_VERSION);
189 
190     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
191 }
192 
193 /*
194  * Test that the scmi_perf_protocol_attributes_handler function returns the
195  * correct attributes associated with this protocol
196  */
197 
attributes_handler_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)198 int attributes_handler_respond_callback(
199     fwk_id_t service_id,
200     const void *payload,
201     size_t size,
202     int NumCalls)
203 {
204     struct scmi_perf_protocol_attributes_p2a *return_values;
205     return_values = (struct scmi_perf_protocol_attributes_p2a *)payload;
206 
207     TEST_ASSERT_EQUAL((int32_t)SCMI_SUCCESS, return_values->status);
208     TEST_ASSERT_EQUAL(
209         SCMI_PERF_PROTOCOL_ATTRIBUTES(true, scmi_perf_ctx.domain_count),
210         return_values->attributes);
211     TEST_ASSERT_EQUAL(0, return_values->statistics_len);
212 
213     return FWK_SUCCESS;
214 }
215 
utest_scmi_perf_protocol_attributes_handler(void)216 void utest_scmi_perf_protocol_attributes_handler(void)
217 {
218     int status;
219     fwk_id_t service_id =
220         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
221     struct scmi_protocol_attributes_p2a payload = {};
222 
223     mod_scmi_from_protocol_api_respond_Stub(
224         attributes_handler_respond_callback);
225 
226     status = to_protocol_api->message_handler(
227         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
228         service_id,
229         (const uint32_t *)&payload,
230         payload_size_table[MOD_SCMI_PROTOCOL_ATTRIBUTES],
231         MOD_SCMI_PROTOCOL_ATTRIBUTES);
232 
233     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
234 }
235 
236 /* Test the message_attributes_handler function with a valid message_id */
237 
message_attributes_handler_valid_param_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)238 int message_attributes_handler_valid_param_respond_callback(
239     fwk_id_t service_id,
240     const void *payload,
241     size_t size,
242     int NumCalls)
243 {
244     struct scmi_protocol_message_attributes_p2a *return_values;
245     return_values = (struct scmi_protocol_message_attributes_p2a *)payload;
246 
247     TEST_ASSERT_EQUAL((int32_t)SCMI_SUCCESS, return_values->status);
248 
249 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
250     TEST_ASSERT_EQUAL(1, return_values->attributes);
251 #else
252     TEST_ASSERT_EQUAL(0, return_values->attributes);
253 #endif
254 
255     return FWK_SUCCESS;
256 }
257 
utest_scmi_perf_protocol_message_attributes_handler_valid_param(void)258 void utest_scmi_perf_protocol_message_attributes_handler_valid_param(void)
259 {
260     int status;
261     fwk_id_t service_id =
262         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
263 
264     struct scmi_protocol_message_attributes_a2p payload = {
265         .message_id = MOD_SCMI_PERF_LIMITS_GET,
266     };
267 
268     mod_scmi_from_protocol_api_respond_Stub(
269         message_attributes_handler_valid_param_respond_callback);
270 
271     status = to_protocol_api->message_handler(
272         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
273         service_id,
274         (const uint32_t *)&payload,
275         payload_size_table[MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES],
276         MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES);
277 
278     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
279 }
280 
281 /* Test the message_attributes_handler function with an invalid message_id */
282 
message_attributes_handler_invalid_param_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)283 int message_attributes_handler_invalid_param_respond_callback(
284     fwk_id_t service_id,
285     const void *payload,
286     size_t size,
287     int NumCalls)
288 {
289     struct scmi_protocol_message_attributes_p2a *return_values;
290     return_values = (struct scmi_protocol_message_attributes_p2a *)payload;
291 
292     TEST_ASSERT_EQUAL((int32_t)SCMI_NOT_FOUND, return_values->status);
293 
294     return FWK_SUCCESS;
295 }
296 
utest_scmi_perf_protocol_message_attributes_handler_invalid_param(void)297 void utest_scmi_perf_protocol_message_attributes_handler_invalid_param(void)
298 {
299     int status;
300     fwk_id_t service_id =
301         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
302 
303     struct scmi_protocol_message_attributes_a2p payload = {
304         .message_id = FWK_ARRAY_SIZE(handler_table),
305     };
306 
307     mod_scmi_from_protocol_api_respond_Stub(
308         message_attributes_handler_invalid_param_respond_callback);
309 
310     status = to_protocol_api->message_handler(
311         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
312         service_id,
313         (const uint32_t *)&payload,
314         payload_size_table[MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES],
315         MOD_SCMI_PROTOCOL_MESSAGE_ATTRIBUTES);
316 
317     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
318 }
319 
320 /* Test the domain_attributes_handler function with a valid domain_id */
321 
domain_attributes_handler_valid_param_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)322 int domain_attributes_handler_valid_param_respond_callback(
323     fwk_id_t service_id,
324     const void *payload,
325     size_t size,
326     int NumCalls)
327 {
328     struct scmi_perf_domain_attributes_p2a *return_values;
329     return_values = (struct scmi_perf_domain_attributes_p2a *)payload;
330 
331     TEST_ASSERT_EQUAL((int32_t)SCMI_SUCCESS, return_values->status);
332 
333     bool notifications = false;
334     bool fast_channels = false;
335 
336 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
337     fast_channels = true;
338 #endif
339 
340     uint32_t permissions = ((uint32_t)MOD_SCMI_PERF_PERMS_SET_LIMITS) |
341         ((uint32_t)MOD_SCMI_PERF_PERMS_SET_LEVEL);
342 
343     uint32_t expected_attributes = SCMI_PERF_DOMAIN_ATTRIBUTES(
344         (uint32_t)notifications,
345         (uint32_t)notifications,
346         ((permissions & (uint32_t)MOD_SCMI_PERF_PERMS_SET_LEVEL) !=
347          (uint32_t)0) ?
348             1U :
349             0U,
350         ((permissions & (uint32_t)MOD_SCMI_PERF_PERMS_SET_LIMITS) !=
351          (uint32_t)0) ?
352             1U :
353             0U,
354         (uint32_t)fast_channels);
355 
356     TEST_ASSERT_EQUAL(expected_attributes, return_values->attributes);
357 
358     TEST_ASSERT_EQUAL(0, return_values->rate_limit);
359 
360     struct mod_dvfs_opp expected_opp_values = test_dvfs_config.opps[0];
361 
362     TEST_ASSERT_EQUAL(
363         expected_opp_values.frequency, return_values->sustained_freq);
364     TEST_ASSERT_EQUAL(
365         expected_opp_values.level, return_values->sustained_perf_level);
366 
367     TEST_ASSERT_EQUAL_STRING(name, (char *)return_values->name);
368 
369     return FWK_SUCCESS;
370 }
371 
utest_scmi_perf_domain_attributes_handler_valid_param(void)372 void utest_scmi_perf_domain_attributes_handler_valid_param(void)
373 {
374     int status;
375 
376     fwk_id_t service_id =
377         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
378 
379     struct scmi_perf_domain_attributes_a2p payload = {
380         .domain_id = 0,
381     };
382 
383     unsigned int agent_id = TEST_SCMI_AGENT_IDX_0;
384 
385     mod_scmi_from_protocol_api_get_agent_id_ExpectAnyArgsAndReturn(FWK_SUCCESS);
386     mod_scmi_from_protocol_api_get_agent_id_ReturnThruPtr_agent_id(&agent_id);
387 
388     struct mod_dvfs_opp test_opp_values = test_dvfs_config.opps[0];
389 
390     mod_dvfs_domain_api_get_sustained_opp_ExpectAnyArgsAndReturn(FWK_SUCCESS);
391     mod_dvfs_domain_api_get_sustained_opp_ReturnThruPtr_opp(&test_opp_values);
392 
393     fwk_module_get_element_name_ExpectAnyArgsAndReturn(name);
394 
395     mod_scmi_from_protocol_api_respond_Stub(
396         domain_attributes_handler_valid_param_respond_callback);
397 
398     status = to_protocol_api->message_handler(
399         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
400         service_id,
401         (const uint32_t *)&payload,
402         payload_size_table[MOD_SCMI_PERF_DOMAIN_ATTRIBUTES],
403         MOD_SCMI_PERF_DOMAIN_ATTRIBUTES);
404 
405     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
406 }
407 
408 /* Test the domain_attributes_handler function with an invalid domain_id */
409 
domain_attributes_handler_invalid_param_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)410 int domain_attributes_handler_invalid_param_respond_callback(
411     fwk_id_t service_id,
412     const void *payload,
413     size_t size,
414     int NumCalls)
415 {
416     struct scmi_perf_domain_attributes_p2a *return_values;
417     return_values = (struct scmi_perf_domain_attributes_p2a *)payload;
418 
419     TEST_ASSERT_EQUAL((int32_t)SCMI_NOT_FOUND, return_values->status);
420 
421     return FWK_SUCCESS;
422 }
423 
utest_scmi_perf_domain_attributes_handler_invalid_param(void)424 void utest_scmi_perf_domain_attributes_handler_invalid_param(void)
425 {
426     int status;
427 
428     fwk_id_t service_id =
429         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
430 
431     struct scmi_perf_domain_attributes_a2p payload = {
432         .domain_id = scmi_perf_ctx.domain_count,
433     };
434 
435     mod_scmi_from_protocol_api_respond_Stub(
436         domain_attributes_handler_invalid_param_respond_callback);
437 
438     status = to_protocol_api->message_handler(
439         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
440         service_id,
441         (const uint32_t *)&payload,
442         payload_size_table[MOD_SCMI_PERF_DOMAIN_ATTRIBUTES],
443         MOD_SCMI_PERF_DOMAIN_ATTRIBUTES);
444 
445     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
446 }
447 
448 /* Test the describe_levels_handler function with a set of valid parameters */
449 
450 /*
451  * As the dvfs_get_nth_opp function is mocked, we must manually return the
452  * requested OPP
453  */
get_nth_opp_callback(fwk_id_t domain_id,size_t n,struct mod_dvfs_opp * opp,int NumCalls)454 int get_nth_opp_callback(
455     fwk_id_t domain_id,
456     size_t n,
457     struct mod_dvfs_opp *opp,
458     int NumCalls)
459 {
460     *opp = test_dvfs_config.opps[n];
461     return FWK_SUCCESS;
462 }
463 
464 /*
465  * Check that each of the returned levels is correct. Also, check that the
466  * final returned status and number of levels is correct.
467  */
describe_levels_handler_valid_param_write_payload_callback(fwk_id_t service_id,size_t offset,const void * payload,size_t size,int NumCalls)468 int describe_levels_handler_valid_param_write_payload_callback(
469     fwk_id_t service_id,
470     size_t offset,
471     const void *payload,
472     size_t size,
473     int NumCalls)
474 {
475     if (NumCalls < TEST_OPP_COUNT) {
476         struct scmi_perf_level *returned_perf_level =
477             (struct scmi_perf_level *)payload;
478 
479         TEST_ASSERT_EQUAL(
480             test_dvfs_config.opps[NumCalls].voltage,
481             returned_perf_level->power_cost);
482         TEST_ASSERT_EQUAL(
483             test_dvfs_config.opps[NumCalls].level,
484             returned_perf_level->performance_level);
485         TEST_ASSERT_EQUAL(
486             test_dvfs_config.latency, returned_perf_level->attributes);
487 
488     } else if (NumCalls == TEST_OPP_COUNT) {
489         struct scmi_perf_describe_levels_p2a *return_values =
490             (struct scmi_perf_describe_levels_p2a *)payload;
491         TEST_ASSERT_EQUAL(SCMI_SUCCESS, return_values->status);
492         TEST_ASSERT_EQUAL(TEST_OPP_COUNT, return_values->num_levels);
493 
494     } else {
495         return FWK_E_RANGE;
496     }
497 
498     return FWK_SUCCESS;
499 }
500 
utest_scmi_perf_describe_levels_handler_valid_param(void)501 void utest_scmi_perf_describe_levels_handler_valid_param(void)
502 {
503     int status;
504 
505     fwk_id_t service_id =
506         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
507 
508     struct scmi_perf_describe_levels_a2p payload = {
509         .domain_id = 0,
510         .level_index = 0,
511     };
512 
513     size_t size = UINT16_MAX;
514     size_t opp_count = TEST_OPP_COUNT;
515     uint16_t latency = test_dvfs_config.latency;
516 
517     /*
518      * Return an arbitrarily large max_payload_size as we are just testing
519      * whether the returned levels are correct and in the right order
520      */
521     mod_scmi_from_protocol_api_get_max_payload_size_ExpectAnyArgsAndReturn(
522         FWK_SUCCESS);
523     mod_scmi_from_protocol_api_get_max_payload_size_ReturnThruPtr_size(&size);
524 
525     mod_dvfs_domain_api_get_opp_count_ExpectAnyArgsAndReturn(FWK_SUCCESS);
526     mod_dvfs_domain_api_get_opp_count_ReturnThruPtr_opp_count(&opp_count);
527 
528     mod_dvfs_domain_api_get_latency_ExpectAnyArgsAndReturn(FWK_SUCCESS);
529     mod_dvfs_domain_api_get_latency_ReturnThruPtr_latency(&latency);
530 
531     mod_dvfs_domain_api_get_nth_opp_Stub(get_nth_opp_callback);
532 
533     mod_scmi_from_protocol_api_write_payload_Stub(
534         describe_levels_handler_valid_param_write_payload_callback);
535 
536     /* Disable the previous callback for this function */
537     mod_scmi_from_protocol_api_respond_Stub(NULL);
538     mod_scmi_from_protocol_api_respond_ExpectAnyArgsAndReturn(FWK_SUCCESS);
539 
540     status = to_protocol_api->message_handler(
541         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
542         service_id,
543         (const uint32_t *)&payload,
544         payload_size_table[MOD_SCMI_PERF_DESCRIBE_LEVELS],
545         MOD_SCMI_PERF_DESCRIBE_LEVELS);
546 
547     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
548 }
549 
550 /* Test the describe_levels_handler function with an invalid domain_id */
551 
describe_levels_handler_invalid_domain_id_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)552 int describe_levels_handler_invalid_domain_id_respond_callback(
553     fwk_id_t service_id,
554     const void *payload,
555     size_t size,
556     int NumCalls)
557 {
558     int32_t *status = (int32_t *)payload;
559     TEST_ASSERT_EQUAL((int32_t)SCMI_NOT_FOUND, *status);
560 
561     return FWK_SUCCESS;
562 }
563 
utest_scmi_perf_describe_levels_handler_invalid_domain_id(void)564 void utest_scmi_perf_describe_levels_handler_invalid_domain_id(void)
565 {
566     int status;
567 
568     fwk_id_t service_id =
569         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
570 
571     struct scmi_perf_describe_levels_a2p payload = {
572         .domain_id = scmi_perf_ctx.domain_count,
573         .level_index = 0,
574     };
575 
576     size_t size = UINT16_MAX;
577 
578     mod_scmi_from_protocol_api_get_max_payload_size_ExpectAnyArgsAndReturn(
579         FWK_SUCCESS);
580     mod_scmi_from_protocol_api_get_max_payload_size_ReturnThruPtr_size(&size);
581 
582     mod_scmi_from_protocol_api_respond_Stub(
583         describe_levels_handler_invalid_domain_id_respond_callback);
584 
585     status = to_protocol_api->message_handler(
586         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
587         service_id,
588         (const uint32_t *)&payload,
589         payload_size_table[MOD_SCMI_PERF_DESCRIBE_LEVELS],
590         MOD_SCMI_PERF_DESCRIBE_LEVELS);
591 
592     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
593 }
594 
595 /* Test the describe_levels_handler function with an invalid level_index */
596 
describe_levels_handler_invalid_level_index_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)597 int describe_levels_handler_invalid_level_index_respond_callback(
598     fwk_id_t service_id,
599     const void *payload,
600     size_t size,
601     int NumCalls)
602 {
603     int32_t *status = (int32_t *)payload;
604     TEST_ASSERT_EQUAL((int32_t)SCMI_INVALID_PARAMETERS, *status);
605 
606     return FWK_SUCCESS;
607 }
608 
utest_scmi_perf_describe_levels_handler_invalid_level_index(void)609 void utest_scmi_perf_describe_levels_handler_invalid_level_index(void)
610 {
611     int status;
612 
613     fwk_id_t service_id =
614         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
615 
616     struct scmi_perf_describe_levels_a2p payload = {
617         .domain_id = 0,
618         .level_index = TEST_OPP_COUNT,
619     };
620 
621     size_t size = UINT16_MAX;
622     size_t opp_count = TEST_OPP_COUNT;
623 
624     mod_scmi_from_protocol_api_get_max_payload_size_ExpectAnyArgsAndReturn(
625         FWK_SUCCESS);
626     mod_scmi_from_protocol_api_get_max_payload_size_ReturnThruPtr_size(&size);
627 
628     mod_dvfs_domain_api_get_opp_count_ExpectAnyArgsAndReturn(FWK_SUCCESS);
629     mod_dvfs_domain_api_get_opp_count_ReturnThruPtr_opp_count(&opp_count);
630 
631     mod_scmi_from_protocol_api_respond_Stub(
632         describe_levels_handler_invalid_level_index_respond_callback);
633 
634     status = to_protocol_api->message_handler(
635         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
636         service_id,
637         (const uint32_t *)&payload,
638         payload_size_table[MOD_SCMI_PERF_DESCRIBE_LEVELS],
639         MOD_SCMI_PERF_DESCRIBE_LEVELS);
640 
641     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
642 }
643 
644 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
645 
646 /*
647  * Test the scmi_perf_describe_fast_channels function with a set of valid
648  * parameters
649  */
650 
describe_fast_channels_valid_params_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)651 int describe_fast_channels_valid_params_respond_callback(
652     fwk_id_t service_id,
653     const void *payload,
654     size_t size,
655     int NumCalls)
656 {
657     struct scmi_perf_describe_fc_p2a *return_values =
658         (struct scmi_perf_describe_fc_p2a *)payload;
659 
660     TEST_ASSERT_EQUAL((int32_t)SCMI_SUCCESS, return_values->status);
661     TEST_ASSERT_EQUAL(0, return_values->attributes);
662     TEST_ASSERT_EQUAL(
663         scmi_perf_ctx.fast_channels_rate_limit, return_values->rate_limit);
664 
665     int chan_index = (uint32_t)MOD_SCMI_PERF_FAST_CHANNEL_LEVEL_GET;
666     TEST_ASSERT_EQUAL(
667         (uint32_t)(domains[0].fast_channels_addr_ap[chan_index] & ~0UL),
668         return_values->chan_addr_low);
669     TEST_ASSERT_EQUAL(
670         (uint32_t)(domains[0].fast_channels_addr_ap[chan_index] >> 32),
671         return_values->chan_addr_high);
672 
673     TEST_ASSERT_EQUAL(
674         fast_channel_elem_size[MOD_SCMI_PERF_FAST_CHANNEL_LEVEL_GET],
675         return_values->chan_size);
676 
677     return FWK_SUCCESS;
678 }
679 
utest_scmi_perf_describe_fast_channels_valid_params(void)680 void utest_scmi_perf_describe_fast_channels_valid_params(void)
681 {
682     int status;
683 
684     fwk_id_t service_id =
685         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
686 
687     struct scmi_perf_describe_fc_a2p payload = {
688         .domain_id = 0,
689         .message_id = MOD_SCMI_PERF_LEVEL_GET,
690     };
691 
692     mod_scmi_from_protocol_api_respond_Stub(
693         describe_fast_channels_valid_params_respond_callback);
694 
695     status = to_protocol_api->message_handler(
696         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
697         service_id,
698         (const uint32_t *)&payload,
699         payload_size_table[MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL],
700         MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL);
701 
702     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
703 }
704 
705 /*
706  * Test the scmi_perf_describe_fast_channels function with an invalid
707  * domain_id
708  */
709 
describe_fast_channels_invalid_domain_id_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)710 int describe_fast_channels_invalid_domain_id_respond_callback(
711     fwk_id_t service_id,
712     const void *payload,
713     size_t size,
714     int NumCalls)
715 {
716     struct scmi_perf_describe_fc_p2a *return_values =
717         (struct scmi_perf_describe_fc_p2a *)payload;
718 
719     TEST_ASSERT_EQUAL((int32_t)SCMI_NOT_FOUND, return_values->status);
720 
721     return FWK_SUCCESS;
722 }
723 
utest_scmi_perf_describe_fast_channels_invalid_domain_id(void)724 void utest_scmi_perf_describe_fast_channels_invalid_domain_id(void)
725 {
726     int status;
727 
728     fwk_id_t service_id =
729         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
730 
731     struct scmi_perf_describe_fc_a2p payload = {
732         .domain_id = scmi_perf_ctx.domain_count,
733         .message_id = MOD_SCMI_PERF_LEVEL_GET,
734     };
735 
736     mod_scmi_from_protocol_api_respond_Stub(
737         describe_fast_channels_invalid_domain_id_respond_callback);
738 
739     status = to_protocol_api->message_handler(
740         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
741         service_id,
742         (const uint32_t *)&payload,
743         payload_size_table[MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL],
744         MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL);
745 
746     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
747 }
748 
749 /*
750  * Test the scmi_perf_describe_fast_channels function with an invalid
751  * message_id
752  */
753 
describe_fast_channels_invalid_message_id_respond_callback(fwk_id_t service_id,const void * payload,size_t size,int NumCalls)754 int describe_fast_channels_invalid_message_id_respond_callback(
755     fwk_id_t service_id,
756     const void *payload,
757     size_t size,
758     int NumCalls)
759 {
760     struct scmi_perf_describe_fc_p2a *return_values =
761         (struct scmi_perf_describe_fc_p2a *)payload;
762 
763     TEST_ASSERT_EQUAL((int32_t)SCMI_NOT_FOUND, return_values->status);
764 
765     return FWK_SUCCESS;
766 }
767 
utest_scmi_perf_describe_fast_channels_invalid_message_id(void)768 void utest_scmi_perf_describe_fast_channels_invalid_message_id(void)
769 {
770     int status;
771 
772     fwk_id_t service_id =
773         FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, TEST_SCMI_AGENT_IDX_0);
774 
775     struct scmi_perf_describe_fc_a2p payload = {
776         .domain_id = 0,
777         .message_id = MOD_SCMI_PERF_COMMAND_COUNT,
778     };
779 
780     mod_scmi_from_protocol_api_respond_Stub(
781         describe_fast_channels_invalid_message_id_respond_callback);
782 
783     status = to_protocol_api->message_handler(
784         (fwk_id_t)MOD_SCMI_PROTOCOL_ID_PERF,
785         service_id,
786         (const uint32_t *)&payload,
787         payload_size_table[MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL],
788         MOD_SCMI_PERF_DESCRIBE_FAST_CHANNEL);
789 
790     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
791 }
792 
793 #endif
794 
795 /*
796  * Test the find_opp_for_level function with a valid level, without
797  * use_nearest
798  */
utest_find_opp_for_level_valid_level(void)799 void utest_find_opp_for_level_valid_level(void)
800 {
801     int status;
802     uint32_t valid_level = test_dvfs_config.opps[1].level;
803 
804     struct perf_opp_table opp_table = {
805         .opps = test_dvfs_config.opps,
806         .opp_count = TEST_OPP_COUNT,
807     };
808 
809     struct mod_scmi_perf_level_limits level_limits = {
810         .minimum = test_dvfs_config.opps[0].level,
811         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
812     };
813 
814     struct scmi_perf_domain_ctx domain_ctx = {
815         .level_limits = level_limits,
816         .opp_table = &opp_table,
817     };
818 
819     status = find_opp_for_level(&domain_ctx, &valid_level, false);
820     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
821     TEST_ASSERT_EQUAL(opp_table.opps[1].level, valid_level);
822 }
823 
824 /*
825  * Test the find_opp_for_level function with an invalid level, without
826  * use_nearest
827  */
utest_find_opp_for_level_invalid_level(void)828 void utest_find_opp_for_level_invalid_level(void)
829 {
830     int status;
831     uint32_t invalid_level = test_dvfs_config.opps[1].level + 1000000UL;
832 
833     struct perf_opp_table opp_table = {
834         .opps = test_dvfs_config.opps,
835         .opp_count = TEST_OPP_COUNT,
836     };
837 
838     struct mod_scmi_perf_level_limits level_limits = {
839         .minimum = test_dvfs_config.opps[0].level,
840         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
841     };
842 
843     struct scmi_perf_domain_ctx domain_ctx = {
844         .level_limits = level_limits,
845         .opp_table = &opp_table,
846     };
847 
848     status = find_opp_for_level(&domain_ctx, &invalid_level, false);
849     TEST_ASSERT_EQUAL(FWK_E_RANGE, status);
850 }
851 
852 /*
853  * Test the find_opp_for_level function with use_nearest. In this case, expect
854  * an OPP to be found for any level.
855  */
utest_find_opp_for_level_use_nearest(void)856 void utest_find_opp_for_level_use_nearest(void)
857 {
858     int status;
859 
860     struct perf_opp_table opp_table = {
861         .opps = test_dvfs_config.opps,
862         .opp_count = TEST_OPP_COUNT,
863     };
864 
865     struct mod_scmi_perf_level_limits level_limits = {
866         .minimum = test_dvfs_config.opps[0].level,
867         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
868     };
869 
870     struct scmi_perf_domain_ctx domain_ctx = {
871         .level_limits = level_limits,
872         .opp_table = &opp_table,
873     };
874 
875     uint32_t approximate_level = level_limits.maximum + 1000000UL;
876 
877     status = find_opp_for_level(&domain_ctx, &approximate_level, true);
878     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
879     TEST_ASSERT_EQUAL(level_limits.maximum, approximate_level);
880 }
881 
882 /*
883  * Test the validate_new_limits function with a valid set of limits, without
884  * approximating the level
885  */
utest_validate_new_limits_valid_limits(void)886 void utest_validate_new_limits_valid_limits(void)
887 {
888     int status;
889 
890     struct perf_opp_table opp_table = {
891         .opps = test_dvfs_config.opps,
892         .opp_count = TEST_OPP_COUNT,
893     };
894 
895     struct mod_scmi_perf_level_limits level_limits = {
896         .minimum = test_dvfs_config.opps[0].level,
897         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
898     };
899 
900     struct scmi_perf_domain_ctx domain_ctx = {
901         .level_limits = level_limits,
902         .opp_table = &opp_table,
903     };
904 
905     struct mod_scmi_perf_level_limits valid_level_limits = {
906         .minimum = test_dvfs_config.opps[1].level,
907         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
908     };
909 
910     status = validate_new_limits(&domain_ctx, &valid_level_limits);
911     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
912 }
913 
914 /*
915  * Test the validate_new_limits function with an invalid set of limits, without
916  * approximating the level
917  */
utest_validate_new_limits_invalid_limits(void)918 void utest_validate_new_limits_invalid_limits(void)
919 {
920     int status;
921 
922     struct perf_opp_table opp_table = {
923         .opps = test_dvfs_config.opps,
924         .opp_count = TEST_OPP_COUNT,
925     };
926 
927     struct mod_scmi_perf_level_limits level_limits = {
928         .minimum = test_dvfs_config.opps[0].level,
929         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
930     };
931 
932     struct scmi_perf_domain_ctx domain_ctx = {
933         .level_limits = level_limits,
934         .opp_table = &opp_table,
935     };
936 
937     struct mod_scmi_perf_level_limits invalid_level_limits = {
938         .minimum = test_dvfs_config.opps[0].level + 1000000UL,
939         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
940     };
941 
942     status = validate_new_limits(&domain_ctx, &invalid_level_limits);
943     TEST_ASSERT_EQUAL(FWK_E_RANGE, status);
944 }
945 
946 /*
947  * Test the validate_new_limits function, approximating the level. In this
948  * case, expect any set of limits to succeed.
949  */
utest_validate_new_limits_approximate_level(void)950 void utest_validate_new_limits_approximate_level(void)
951 {
952     int status;
953 
954     struct fwk_module_config config_scmi_perf_approximate_level = {
955         .data = &((struct mod_scmi_perf_config){
956             .domains = &domains,
957             .perf_doms_count = FWK_ARRAY_SIZE(domains),
958             .fast_channels_alarm_id = FWK_ID_NONE_INIT,
959             .approximate_level = true,
960         }),
961     };
962 
963     scmi_perf_ctx.config = config_scmi_perf_approximate_level.data;
964 
965     struct perf_opp_table opp_table = {
966         .opps = test_dvfs_config.opps,
967         .opp_count = TEST_OPP_COUNT,
968     };
969     struct mod_scmi_perf_level_limits level_limits = {
970         .minimum = test_dvfs_config.opps[0].level - 1000000UL,
971         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level + 1000000UL,
972     };
973 
974     struct scmi_perf_domain_ctx domain_ctx = {
975         .level_limits = level_limits,
976         .opp_table = &opp_table,
977     };
978 
979     status = validate_new_limits(&domain_ctx, &level_limits);
980     TEST_ASSERT_EQUAL(FWK_SUCCESS, status);
981 }
982 
983 #ifdef BUILD_HAS_SCMI_PERF_PLUGIN_HANDLER
utest_perf_eval_performance_invalid_limits(void)984 void utest_perf_eval_performance_invalid_limits(void)
985 {
986     struct mod_scmi_perf_level_limits limits = {
987         .minimum = 1000,
988         .maximum = 100,
989     };
990     uint32_t level = 500;
991     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 0);
992 
993     perf_eval_performance(perf_id, &limits, &level);
994     TEST_ASSERT_EQUAL(500, level);
995 }
996 
utest_perf_eval_performance_unchanged_limits(void)997 void utest_perf_eval_performance_unchanged_limits(void)
998 {
999     struct scmi_perf_domain_ctx domain0_ctx;
1000     uint32_t level;
1001 
1002     domain0_ctx.level_limits.minimum = test_dvfs_config.opps[0].level;
1003     domain0_ctx.level_limits.maximum =
1004         test_dvfs_config.opps[TEST_OPP_COUNT - 1].level;
1005 
1006     struct mod_scmi_perf_level_limits limits = {
1007         .minimum = test_dvfs_config.opps[0].level,
1008         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
1009     };
1010 
1011     domain0_ctx.opp_table = &((struct perf_opp_table){
1012         .opps = test_dvfs_config.opps,
1013         .opp_count = TEST_OPP_COUNT,
1014     });
1015 
1016     scmi_perf_ctx.domain_ctx_table = &domain0_ctx;
1017     /*
1018      * The level to be evaluated is just above the second OPP. Due to the
1019      * default approximation for `perf_eval_performance`, it should return the
1020      * next OPP just above it.
1021      */
1022     level = test_dvfs_config.opps[1].level + 1;
1023     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 0);
1024 
1025     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 0);
1026 
1027     perf_eval_performance(perf_id, &limits, &level);
1028     TEST_ASSERT_EQUAL(test_dvfs_config.opps[2].level, level);
1029 }
1030 
utest_perf_eval_performance_unchanged_limits_level_down(void)1031 void utest_perf_eval_performance_unchanged_limits_level_down(void)
1032 {
1033     struct scmi_perf_domain_ctx domain0_ctx;
1034     uint32_t level;
1035 
1036     domain0_ctx.level_limits.minimum = test_dvfs_config.opps[0].level;
1037     domain0_ctx.level_limits.maximum =
1038         test_dvfs_config.opps[TEST_OPP_COUNT - 2].level;
1039 
1040     struct mod_scmi_perf_level_limits limits = {
1041         .minimum = test_dvfs_config.opps[0].level,
1042         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 2].level,
1043     };
1044 
1045     domain0_ctx.opp_table = &((struct perf_opp_table){
1046         .opps = test_dvfs_config.opps,
1047         .opp_count = TEST_OPP_COUNT,
1048     });
1049 
1050     scmi_perf_ctx.domain_ctx_table = &domain0_ctx;
1051     /* The level will be reduced to the max limit */
1052     level = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level;
1053     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 0);
1054 
1055     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 0);
1056 
1057     perf_eval_performance(perf_id, &limits, &level);
1058     TEST_ASSERT_EQUAL(test_dvfs_config.opps[TEST_OPP_COUNT - 2].level, level);
1059 }
1060 
utest_perf_eval_performance_unchanged_limits_level_up(void)1061 void utest_perf_eval_performance_unchanged_limits_level_up(void)
1062 {
1063     struct scmi_perf_domain_ctx domain0_ctx;
1064     uint32_t level;
1065 
1066     domain0_ctx.level_limits.minimum = test_dvfs_config.opps[1].level;
1067     domain0_ctx.level_limits.maximum =
1068         test_dvfs_config.opps[TEST_OPP_COUNT - 1].level;
1069 
1070     struct mod_scmi_perf_level_limits limits = {
1071         .minimum = test_dvfs_config.opps[1].level,
1072         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
1073     };
1074 
1075     domain0_ctx.opp_table = &((struct perf_opp_table){
1076         .opps = test_dvfs_config.opps,
1077         .opp_count = TEST_OPP_COUNT,
1078     });
1079 
1080     scmi_perf_ctx.domain_ctx_table = &domain0_ctx;
1081     /* The level will be increased to the min limit */
1082     level = test_dvfs_config.opps[0].level;
1083     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 0);
1084 
1085     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 0);
1086 
1087     perf_eval_performance(perf_id, &limits, &level);
1088     TEST_ASSERT_EQUAL(test_dvfs_config.opps[1].level, level);
1089 }
1090 
utest_perf_eval_performance_new_limits(void)1091 void utest_perf_eval_performance_new_limits(void)
1092 {
1093     struct scmi_perf_domain_ctx domain_table[2];
1094     struct perf_plugins_api *plugins_api_table[1];
1095     uint32_t level;
1096 
1097     domain_table[1].level_limits.minimum = test_dvfs_config.opps[0].level;
1098     domain_table[1].level_limits.maximum =
1099         test_dvfs_config.opps[TEST_OPP_COUNT - 2].level;
1100 
1101     struct mod_scmi_perf_level_limits new_limits = {
1102         .minimum = test_dvfs_config.opps[0].level,
1103         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
1104     };
1105 
1106     domain_table[1].opp_table = &((struct perf_opp_table){
1107         .opps = test_dvfs_config.opps,
1108         .opp_count = TEST_OPP_COUNT,
1109     });
1110 
1111     scmi_perf_ctx.domain_ctx_table = &domain_table[0];
1112     level = test_dvfs_config.opps[1].level;
1113     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 1);
1114 
1115     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 1);
1116     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 1);
1117 
1118     perf_plugins_ctx.config = config_scmi_perf.data;
1119     plugins_api_table[0] = &((struct perf_plugins_api){
1120         .update = NULL,
1121         .report = NULL,
1122     });
1123     perf_plugins_ctx.plugins_api_table = &plugins_api_table[0];
1124 
1125     perf_eval_performance(perf_id, &new_limits, &level);
1126     TEST_ASSERT_EQUAL(test_dvfs_config.opps[1].level, level);
1127 }
1128 
utest_perf_eval_performance_new_limits_level_down(void)1129 void utest_perf_eval_performance_new_limits_level_down(void)
1130 {
1131     struct scmi_perf_domain_ctx domain_table[2];
1132     struct perf_plugins_api *plugins_api_table[1];
1133     uint32_t level;
1134 
1135     domain_table[1].level_limits.minimum = test_dvfs_config.opps[0].level;
1136     domain_table[1].level_limits.maximum =
1137         test_dvfs_config.opps[TEST_OPP_COUNT - 1].level;
1138 
1139     struct mod_scmi_perf_level_limits new_limits = {
1140         .minimum = test_dvfs_config.opps[0].level,
1141         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 2].level,
1142     };
1143 
1144     domain_table[1].opp_table = &((struct perf_opp_table){
1145         .opps = test_dvfs_config.opps,
1146         .opp_count = TEST_OPP_COUNT,
1147     });
1148 
1149     scmi_perf_ctx.domain_ctx_table = &domain_table[0];
1150     /* The level will be reduced to the max limit */
1151     level = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level;
1152     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 1);
1153 
1154     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 1);
1155     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 1);
1156 
1157     perf_plugins_ctx.config = config_scmi_perf.data;
1158     plugins_api_table[0] = &((struct perf_plugins_api){
1159         .update = NULL,
1160         .report = NULL,
1161     });
1162     perf_plugins_ctx.plugins_api_table = &plugins_api_table[0];
1163 
1164     perf_eval_performance(perf_id, &new_limits, &level);
1165     TEST_ASSERT_EQUAL(test_dvfs_config.opps[TEST_OPP_COUNT - 2].level, level);
1166 }
1167 
utest_perf_eval_performance_new_limits_level_up(void)1168 void utest_perf_eval_performance_new_limits_level_up(void)
1169 {
1170     struct scmi_perf_domain_ctx domain_table[2];
1171     struct perf_plugins_api *plugins_api_table[1];
1172     uint32_t level;
1173 
1174     domain_table[1].level_limits.minimum = test_dvfs_config.opps[0].level;
1175     domain_table[1].level_limits.maximum =
1176         test_dvfs_config.opps[TEST_OPP_COUNT - 1].level;
1177 
1178     struct mod_scmi_perf_level_limits new_limits = {
1179         .minimum = test_dvfs_config.opps[1].level,
1180         .maximum = test_dvfs_config.opps[TEST_OPP_COUNT - 1].level,
1181     };
1182 
1183     domain_table[1].opp_table = &((struct perf_opp_table){
1184         .opps = test_dvfs_config.opps,
1185         .opp_count = TEST_OPP_COUNT,
1186     });
1187 
1188     scmi_perf_ctx.domain_ctx_table = &domain_table[0];
1189     /* The level will be increased to the min limit */
1190     level = test_dvfs_config.opps[0].level;
1191     fwk_id_t perf_id = FWK_ID_ELEMENT_INIT(TEST_MODULE_IDX, 1);
1192 
1193     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 1);
1194     fwk_id_get_element_idx_ExpectAndReturn(perf_id, 1);
1195 
1196     perf_plugins_ctx.config = config_scmi_perf.data;
1197     plugins_api_table[0] = &((struct perf_plugins_api){
1198         .update = NULL,
1199         .report = NULL,
1200     });
1201     perf_plugins_ctx.plugins_api_table = &plugins_api_table[0];
1202 
1203     perf_eval_performance(perf_id, &new_limits, &level);
1204     TEST_ASSERT_EQUAL(test_dvfs_config.opps[1].level, level);
1205 }
1206 #endif
1207 
scmi_perf_test_main(void)1208 int scmi_perf_test_main(void)
1209 {
1210     UNITY_BEGIN();
1211 
1212 #ifndef BUILD_HAS_SCMI_PERF_PLUGIN_HANDLER
1213 #    ifndef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
1214     RUN_TEST(utest_scmi_perf_message_handler_bad_message_id);
1215     RUN_TEST(utest_scmi_perf_message_handler_not_found);
1216 #    endif
1217 
1218     RUN_TEST(utest_scmi_perf_protocol_version_handler);
1219     RUN_TEST(utest_scmi_perf_protocol_attributes_handler);
1220 
1221     RUN_TEST(utest_scmi_perf_protocol_message_attributes_handler_valid_param);
1222     RUN_TEST(utest_scmi_perf_protocol_message_attributes_handler_invalid_param);
1223 
1224     RUN_TEST(utest_scmi_perf_domain_attributes_handler_valid_param);
1225     RUN_TEST(utest_scmi_perf_domain_attributes_handler_invalid_param);
1226 
1227     RUN_TEST(utest_scmi_perf_describe_levels_handler_valid_param);
1228     RUN_TEST(utest_scmi_perf_describe_levels_handler_invalid_domain_id);
1229     RUN_TEST(utest_scmi_perf_describe_levels_handler_invalid_level_index);
1230 
1231 #ifdef BUILD_HAS_SCMI_PERF_FAST_CHANNELS
1232     RUN_TEST(utest_scmi_perf_describe_fast_channels_valid_params);
1233     RUN_TEST(utest_scmi_perf_describe_fast_channels_invalid_domain_id);
1234     RUN_TEST(utest_scmi_perf_describe_fast_channels_invalid_message_id);
1235 #endif
1236 
1237     RUN_TEST(utest_find_opp_for_level_valid_level);
1238     RUN_TEST(utest_find_opp_for_level_invalid_level);
1239     RUN_TEST(utest_find_opp_for_level_use_nearest);
1240 
1241     RUN_TEST(utest_validate_new_limits_valid_limits);
1242     RUN_TEST(utest_validate_new_limits_invalid_limits);
1243     RUN_TEST(utest_validate_new_limits_approximate_level);
1244 
1245 #else
1246     RUN_TEST(utest_perf_eval_performance_invalid_limits);
1247 
1248     RUN_TEST(utest_perf_eval_performance_unchanged_limits);
1249     RUN_TEST(utest_perf_eval_performance_unchanged_limits_level_up);
1250     RUN_TEST(utest_perf_eval_performance_unchanged_limits_level_down);
1251 
1252     RUN_TEST(utest_perf_eval_performance_new_limits);
1253     RUN_TEST(utest_perf_eval_performance_new_limits_level_up);
1254     RUN_TEST(utest_perf_eval_performance_new_limits_level_down);
1255 #endif
1256 
1257     return UNITY_END();
1258 }
1259 
1260 #if !defined(TEST_ON_TARGET)
main(void)1261 int main(void)
1262 {
1263     return scmi_perf_test_main();
1264 }
1265 #endif
1266