@@ -244,6 +244,156 @@ ZTEST(policy_api, test_pm_policy_next_state_default_latency)
244244 expected_latency = SYS_FOREVER_US ;
245245 pm_policy_latency_request_remove (& req1 );
246246}
247+
248+ struct test_data {
249+ struct k_timer timer ;
250+ struct onoff_manager mgr ;
251+ struct onoff_monitor monitor ;
252+ int res ;
253+ onoff_notify_fn notify ;
254+ k_timeout_t timeout ;
255+ bool on ;
256+ };
257+
258+ struct test_req {
259+ struct pm_policy_latency_request req ;
260+ volatile int result ;
261+ };
262+
263+ static void onoff_monitor_cb (struct onoff_manager * mgr ,
264+ struct onoff_monitor * mon ,
265+ uint32_t state ,
266+ int res )
267+ {
268+ struct test_data * data = CONTAINER_OF (mgr , struct test_data , mgr );
269+
270+ data -> on = (state == ONOFF_STATE_ON );
271+ }
272+
273+ static void onoff_timeout (struct k_timer * timer )
274+ {
275+ struct test_data * data = CONTAINER_OF (timer , struct test_data , timer );
276+
277+ data -> notify (& data -> mgr , data -> res );
278+ }
279+
280+ K_TIMER_DEFINE (onoff_timer , onoff_timeout , NULL );
281+
282+ static void onoff_start (struct onoff_manager * mgr , onoff_notify_fn notify )
283+ {
284+ struct test_data * data = CONTAINER_OF (mgr , struct test_data , mgr );
285+
286+ data -> notify = notify ;
287+ k_timer_start (& data -> timer , data -> timeout , K_NO_WAIT );
288+ }
289+
290+ static void onoff_stop (struct onoff_manager * mgr , onoff_notify_fn notify )
291+ {
292+ struct test_data * data = CONTAINER_OF (mgr , struct test_data , mgr );
293+
294+ data -> notify = notify ;
295+ k_timer_start (& data -> timer , data -> timeout , K_NO_WAIT );
296+ }
297+
298+ static void immediate_ctrl_binary_init (struct test_data * data , uint32_t thr , uint32_t t_op )
299+ {
300+ static const struct onoff_transitions transitions = {
301+ .start = onoff_start ,
302+ .stop = onoff_stop
303+ };
304+ static struct pm_policy_latency_immediate_binary bin_mgr ;
305+ struct pm_policy_latency_immediate_ctrl ctrl ;
306+ int rv ;
307+
308+ bin_mgr .mgr = & data -> mgr ;
309+ bin_mgr .thr = thr ;
310+ ctrl .onoff = true;
311+ ctrl .bin_mgr = & bin_mgr ;
312+ data -> monitor .callback = onoff_monitor_cb ;
313+
314+ data -> timeout = K_MSEC (t_op );
315+ k_timer_init (& data -> timer , onoff_timeout , NULL );
316+ rv = onoff_manager_init (& data -> mgr , & transitions );
317+ zassert_equal (rv , 0 );
318+
319+ rv = onoff_monitor_register (& data -> mgr , & data -> monitor );
320+ zassert_equal (rv , 0 );
321+
322+ rv = pm_policy_latency_immediate_ctrl_add (& ctrl );
323+ zassert_equal (rv , 0 );
324+ }
325+
326+ static void latency_changed (struct pm_policy_latency_request * req , int32_t result )
327+ {
328+ struct test_req * test_req = CONTAINER_OF (req , struct test_req , req );
329+
330+ test_req -> result = result ;
331+ }
332+
333+ ZTEST (policy_api , test_pm_policy_latency_immediate_action_bin )
334+ {
335+ struct test_data data ;
336+ uint32_t thr = 1000 ;
337+ uint32_t t_op = 1 ;
338+ struct test_req req1 , req2 ;
339+ int rv ;
340+ int result = - EAGAIN ;
341+
342+ immediate_ctrl_binary_init (& data , thr , t_op );
343+
344+ sys_notify_init_spinwait (& req1 .req .cli .notify );
345+
346+ /* Latency above threhold so requirement is already met. */
347+ rv = pm_policy_latency_request_add (& req1 .req , thr + 1 );
348+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
349+ zassert_equal (sys_notify_fetch_result (& req1 .req .cli .notify , & result ), 0 );
350+ zassert_equal (result , 0 , "Unexpected result: %d" , result );
351+
352+ req2 .result = - EIO ;
353+ sys_notify_init_callback (& req2 .req .cli .notify , latency_changed );
354+ rv = pm_policy_latency_request_add (& req2 .req , thr + 2 );
355+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
356+ zassert_equal (req2 .result , 0 , "Unexpected rv: %d" , req2 .result );
357+
358+ req2 .result = - EIO ;
359+ sys_notify_init_callback (& req2 .req .cli .notify , latency_changed );
360+ /* Below the threshold, it triggers asynchronous action. */
361+ rv = pm_policy_latency_request_update (& req2 .req , thr - 1 );
362+ zassert_equal (rv , 1 , "Unexpected rv: %d" , rv );
363+ /* Not finished yet. */
364+ zassert_equal (req2 .result , - EIO , "Unexpected rv: %d" , req2 .result );
365+ k_msleep (t_op );
366+ zassert_equal (req2 .result , 0 , "Unexpected rv: %d" , req2 .result );
367+
368+ rv = pm_policy_latency_request_remove (& req1 .req );
369+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
370+
371+ rv = pm_policy_latency_request_remove (& req2 .req );
372+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
373+
374+ zassert_false (data .on );
375+ rv = pm_policy_latency_request_add_sync (& req1 .req , thr - 1 );
376+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
377+ /* Synchronous request blocks until immediate action is completed. */
378+ zassert_true (data .on );
379+
380+ rv = pm_policy_latency_request_remove (& req1 .req );
381+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
382+
383+ /* Add request below the threshold. */
384+ rv = pm_policy_latency_request_add (& req1 .req , thr + 1 );
385+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
386+ zassert_false (data .on );
387+
388+ /* Synchronous request for update that trigger the immediate action. */
389+ rv = pm_policy_latency_request_update_sync (& req1 .req , thr - 1 );
390+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
391+ zassert_true (data .on );
392+
393+ rv = pm_policy_latency_request_remove (& req1 .req );
394+ zassert_equal (rv , 0 , "Unexpected rv: %d" , rv );
395+ }
396+
247397#else
248398ZTEST (policy_api , test_pm_policy_next_state_default )
249399{
0 commit comments