Mention branches and keyring.
[releases.git] / acpica / evxfregn.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and
5  *                         Address Spaces.
6  *
7  * Copyright (C) 2000 - 2023, Intel Corp.
8  *
9  *****************************************************************************/
10
11 #define EXPORT_ACPI_INTERFACES
12
13 #include <acpi/acpi.h>
14 #include "accommon.h"
15 #include "acnamesp.h"
16 #include "acevents.h"
17
18 #define _COMPONENT          ACPI_EVENTS
19 ACPI_MODULE_NAME("evxfregn")
20
21 /*******************************************************************************
22  *
23  * FUNCTION:    acpi_install_address_space_handler_internal
24  *
25  * PARAMETERS:  device          - Handle for the device
26  *              space_id        - The address space ID
27  *              handler         - Address of the handler
28  *              setup           - Address of the setup function
29  *              context         - Value passed to the handler on each access
30  *              Run_reg         - Run _REG methods for this address space?
31  *
32  * RETURN:      Status
33  *
34  * DESCRIPTION: Install a handler for all op_regions of a given space_id.
35  *
36  * NOTE: This function should only be called after acpi_enable_subsystem has
37  * been called. This is because any _REG methods associated with the Space ID
38  * are executed here, and these methods can only be safely executed after
39  * the default handlers have been installed and the hardware has been
40  * initialized (via acpi_enable_subsystem.)
41  * To avoid this problem pass FALSE for Run_Reg and later on call
42  * acpi_execute_reg_methods() to execute _REG.
43  *
44  ******************************************************************************/
45 static acpi_status
46 acpi_install_address_space_handler_internal(acpi_handle device,
47                                             acpi_adr_space_type space_id,
48                                             acpi_adr_space_handler handler,
49                                             acpi_adr_space_setup setup,
50                                             void *context, u8 run_reg)
51 {
52         struct acpi_namespace_node *node;
53         acpi_status status;
54
55         ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
56
57         /* Parameter validation */
58
59         if (!device) {
60                 return_ACPI_STATUS(AE_BAD_PARAMETER);
61         }
62
63         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
64         if (ACPI_FAILURE(status)) {
65                 return_ACPI_STATUS(status);
66         }
67
68         /* Convert and validate the device handle */
69
70         node = acpi_ns_validate_handle(device);
71         if (!node) {
72                 status = AE_BAD_PARAMETER;
73                 goto unlock_and_exit;
74         }
75
76         /* Install the handler for all Regions for this Space ID */
77
78         status =
79             acpi_ev_install_space_handler(node, space_id, handler, setup,
80                                           context);
81         if (ACPI_FAILURE(status)) {
82                 goto unlock_and_exit;
83         }
84
85         /* Run all _REG methods for this address space */
86
87         if (run_reg) {
88                 acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
89         }
90
91 unlock_and_exit:
92         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
93         return_ACPI_STATUS(status);
94 }
95
96 acpi_status
97 acpi_install_address_space_handler(acpi_handle device,
98                                    acpi_adr_space_type space_id,
99                                    acpi_adr_space_handler handler,
100                                    acpi_adr_space_setup setup, void *context)
101 {
102         return acpi_install_address_space_handler_internal(device, space_id,
103                                                            handler, setup,
104                                                            context, TRUE);
105 }
106
107 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
108 acpi_status
109 acpi_install_address_space_handler_no_reg(acpi_handle device,
110                                           acpi_adr_space_type space_id,
111                                           acpi_adr_space_handler handler,
112                                           acpi_adr_space_setup setup,
113                                           void *context)
114 {
115         return acpi_install_address_space_handler_internal(device, space_id,
116                                                            handler, setup,
117                                                            context, FALSE);
118 }
119
120 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)
121
122 /*******************************************************************************
123  *
124  * FUNCTION:    acpi_remove_address_space_handler
125  *
126  * PARAMETERS:  device          - Handle for the device
127  *              space_id        - The address space ID
128  *              handler         - Address of the handler
129  *
130  * RETURN:      Status
131  *
132  * DESCRIPTION: Remove a previously installed handler.
133  *
134  ******************************************************************************/
135 acpi_status
136 acpi_remove_address_space_handler(acpi_handle device,
137                                   acpi_adr_space_type space_id,
138                                   acpi_adr_space_handler handler)
139 {
140         union acpi_operand_object *obj_desc;
141         union acpi_operand_object *handler_obj;
142         union acpi_operand_object *region_obj;
143         union acpi_operand_object **last_obj_ptr;
144         struct acpi_namespace_node *node;
145         acpi_status status;
146
147         ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
148
149         /* Parameter validation */
150
151         if (!device) {
152                 return_ACPI_STATUS(AE_BAD_PARAMETER);
153         }
154
155         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
156         if (ACPI_FAILURE(status)) {
157                 return_ACPI_STATUS(status);
158         }
159
160         /* Convert and validate the device handle */
161
162         node = acpi_ns_validate_handle(device);
163         if (!node ||
164             ((node->type != ACPI_TYPE_DEVICE) &&
165              (node->type != ACPI_TYPE_PROCESSOR) &&
166              (node->type != ACPI_TYPE_THERMAL) &&
167              (node != acpi_gbl_root_node))) {
168                 status = AE_BAD_PARAMETER;
169                 goto unlock_and_exit;
170         }
171
172         /* Make sure the internal object exists */
173
174         obj_desc = acpi_ns_get_attached_object(node);
175         if (!obj_desc) {
176                 status = AE_NOT_EXIST;
177                 goto unlock_and_exit;
178         }
179
180         /* Find the address handler the user requested */
181
182         handler_obj = obj_desc->common_notify.handler;
183         last_obj_ptr = &obj_desc->common_notify.handler;
184         while (handler_obj) {
185
186                 /* We have a handler, see if user requested this one */
187
188                 if (handler_obj->address_space.space_id == space_id) {
189
190                         /* Handler must be the same as the installed handler */
191
192                         if (handler_obj->address_space.handler != handler) {
193                                 status = AE_BAD_PARAMETER;
194                                 goto unlock_and_exit;
195                         }
196
197                         /* Matched space_id, first dereference this in the Regions */
198
199                         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
200                                           "Removing address handler %p(%p) for region %s "
201                                           "on Device %p(%p)\n",
202                                           handler_obj, handler,
203                                           acpi_ut_get_region_name(space_id),
204                                           node, obj_desc));
205
206                         region_obj = handler_obj->address_space.region_list;
207
208                         /* Walk the handler's region list */
209
210                         while (region_obj) {
211                                 /*
212                                  * First disassociate the handler from the region.
213                                  *
214                                  * NOTE: this doesn't mean that the region goes away
215                                  * The region is just inaccessible as indicated to
216                                  * the _REG method
217                                  */
218                                 acpi_ev_detach_region(region_obj, TRUE);
219
220                                 /*
221                                  * Walk the list: Just grab the head because the
222                                  * detach_region removed the previous head.
223                                  */
224                                 region_obj =
225                                     handler_obj->address_space.region_list;
226                         }
227
228                         /* Remove this Handler object from the list */
229
230                         *last_obj_ptr = handler_obj->address_space.next;
231
232                         /* Now we can delete the handler object */
233
234                         acpi_os_release_mutex(handler_obj->address_space.
235                                               context_mutex);
236                         acpi_ut_remove_reference(handler_obj);
237                         goto unlock_and_exit;
238                 }
239
240                 /* Walk the linked list of handlers */
241
242                 last_obj_ptr = &handler_obj->address_space.next;
243                 handler_obj = handler_obj->address_space.next;
244         }
245
246         /* The handler does not exist */
247
248         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
249                           "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
250                           handler, acpi_ut_get_region_name(space_id), space_id,
251                           node, obj_desc));
252
253         status = AE_NOT_EXIST;
254
255 unlock_and_exit:
256         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
257         return_ACPI_STATUS(status);
258 }
259
260 ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
261 /*******************************************************************************
262  *
263  * FUNCTION:    acpi_execute_reg_methods
264  *
265  * PARAMETERS:  device          - Handle for the device
266  *              space_id        - The address space ID
267  *
268  * RETURN:      Status
269  *
270  * DESCRIPTION: Execute _REG for all op_regions of a given space_id.
271  *
272  ******************************************************************************/
273 acpi_status
274 acpi_execute_reg_methods(acpi_handle device, acpi_adr_space_type space_id)
275 {
276         struct acpi_namespace_node *node;
277         acpi_status status;
278
279         ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);
280
281         /* Parameter validation */
282
283         if (!device) {
284                 return_ACPI_STATUS(AE_BAD_PARAMETER);
285         }
286
287         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
288         if (ACPI_FAILURE(status)) {
289                 return_ACPI_STATUS(status);
290         }
291
292         /* Convert and validate the device handle */
293
294         node = acpi_ns_validate_handle(device);
295         if (node) {
296
297                 /* Run all _REG methods for this address space */
298
299                 acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
300         } else {
301                 status = AE_BAD_PARAMETER;
302         }
303
304         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
305         return_ACPI_STATUS(status);
306 }
307
308 ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)