1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2019-2022, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <internal/fwk_module.h>
9 
10 #include <fwk_event.h>
11 #include <fwk_id.h>
12 #include <fwk_interrupt.h>
13 #include <fwk_list.h>
14 #include <fwk_log.h>
15 #include <fwk_module.h>
16 #include <fwk_status.h>
17 
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 static const char err_msg_func[] = "[FWK] Error %d in %s";
23 
24 /*
25  * Static functions
26  */
check_api_call(fwk_id_t id,void * data)27 static int check_api_call(fwk_id_t id, void *data)
28 {
29     if (fwk_is_interrupt_context()) {
30         return FWK_E_ACCESS;
31     }
32 
33     if ((!fwk_module_is_valid_entity_id(id)) || (data == NULL)) {
34         return FWK_E_PARAM;
35     }
36 
37     return FWK_SUCCESS;
38 }
39 
40 /*
41  * Internal interface functions for use by framework only
42  */
__fwk_get_delayed_response_list(fwk_id_t id)43 struct fwk_slist *__fwk_get_delayed_response_list(fwk_id_t id)
44 {
45     if (fwk_id_is_type(id, FWK_ID_TYPE_MODULE)) {
46         return &fwk_module_get_ctx(id)->delayed_response_list;
47     }
48 
49     return &fwk_module_get_element_ctx(id)->delayed_response_list;
50 }
51 
__fwk_search_delayed_response(fwk_id_t id,uint32_t cookie)52 struct fwk_event *__fwk_search_delayed_response(fwk_id_t id, uint32_t cookie)
53 {
54     struct fwk_slist *delayed_response_list;
55     struct fwk_slist_node *delayed_response_node;
56 
57     delayed_response_list = __fwk_get_delayed_response_list(id);
58     delayed_response_node = fwk_list_head(delayed_response_list);
59 
60     while (delayed_response_node != NULL) {
61         struct fwk_event *delayed_response;
62 
63         delayed_response =
64             FWK_LIST_GET(delayed_response_node, struct fwk_event, slist_node);
65         if (delayed_response->cookie == cookie) {
66             return delayed_response;
67         }
68 
69         delayed_response_node =
70             fwk_list_next(delayed_response_list, delayed_response_node);
71     }
72 
73     return NULL;
74 }
75 
76 /*
77  * Public Interface functions for use by Modules
78  */
fwk_get_delayed_response(fwk_id_t id,uint32_t cookie,struct fwk_event * event)79 int fwk_get_delayed_response(
80     fwk_id_t id,
81     uint32_t cookie,
82     struct fwk_event *event)
83 {
84     int status;
85     struct fwk_event *delayed_response;
86 
87     status = check_api_call(id, event);
88     if (status != FWK_SUCCESS) {
89         goto error;
90     }
91 
92     delayed_response = __fwk_search_delayed_response(id, cookie);
93     if (delayed_response == NULL) {
94         status = FWK_E_PARAM;
95         goto error;
96     }
97 
98     *event = *delayed_response;
99 
100     return FWK_SUCCESS;
101 
102 error:
103     FWK_LOG_CRIT(err_msg_func, status, __func__);
104     return status;
105 }
106 
fwk_is_delayed_response_list_empty(fwk_id_t id,bool * is_empty)107 int fwk_is_delayed_response_list_empty(fwk_id_t id, bool *is_empty)
108 {
109     int status;
110     struct fwk_slist *delayed_response_list;
111     struct fwk_slist_node *delayed_response_node;
112 
113     status = check_api_call(id, is_empty);
114     if (status != FWK_SUCCESS) {
115         goto error;
116     }
117 
118     delayed_response_list = __fwk_get_delayed_response_list(id);
119     delayed_response_node = fwk_list_head(delayed_response_list);
120 
121     *is_empty = (delayed_response_node == NULL);
122 
123     return FWK_SUCCESS;
124 
125 error:
126     FWK_LOG_CRIT(err_msg_func, status, __func__);
127     return status;
128 }
129 
fwk_get_first_delayed_response(fwk_id_t id,struct fwk_event * event)130 int fwk_get_first_delayed_response(fwk_id_t id, struct fwk_event *event)
131 {
132     int status;
133     struct fwk_slist *delayed_response_list;
134     struct fwk_slist_node *delayed_response_node;
135 
136     status = check_api_call(id, event);
137     if (status != FWK_SUCCESS) {
138         goto error;
139     }
140 
141     delayed_response_list = __fwk_get_delayed_response_list(id);
142     delayed_response_node = fwk_list_head(delayed_response_list);
143 
144     if (delayed_response_node != NULL) {
145         *event = *(
146             FWK_LIST_GET(delayed_response_node, struct fwk_event, slist_node));
147     } else {
148         return FWK_E_STATE;
149     }
150 
151     return FWK_SUCCESS;
152 
153 error:
154     FWK_LOG_CRIT(err_msg_func, status, __func__);
155     return status;
156 }
157