]> Git Repo - J-linux.git/blob - drivers/acpi/acpica/evxfregn.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / acpi / 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, ACPI_UINT32_MAX, space_id,
89                                             ACPI_REG_CONNECT);
90         }
91
92 unlock_and_exit:
93         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
94         return_ACPI_STATUS(status);
95 }
96
97 acpi_status
98 acpi_install_address_space_handler(acpi_handle device,
99                                    acpi_adr_space_type space_id,
100                                    acpi_adr_space_handler handler,
101                                    acpi_adr_space_setup setup, void *context)
102 {
103         return acpi_install_address_space_handler_internal(device, space_id,
104                                                            handler, setup,
105                                                            context, TRUE);
106 }
107
108 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
109 acpi_status
110 acpi_install_address_space_handler_no_reg(acpi_handle device,
111                                           acpi_adr_space_type space_id,
112                                           acpi_adr_space_handler handler,
113                                           acpi_adr_space_setup setup,
114                                           void *context)
115 {
116         return acpi_install_address_space_handler_internal(device, space_id,
117                                                            handler, setup,
118                                                            context, FALSE);
119 }
120
121 ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler_no_reg)
122
123 /*******************************************************************************
124  *
125  * FUNCTION:    acpi_remove_address_space_handler
126  *
127  * PARAMETERS:  device          - Handle for the device
128  *              space_id        - The address space ID
129  *              handler         - Address of the handler
130  *
131  * RETURN:      Status
132  *
133  * DESCRIPTION: Remove a previously installed handler.
134  *
135  ******************************************************************************/
136 acpi_status
137 acpi_remove_address_space_handler(acpi_handle device,
138                                   acpi_adr_space_type space_id,
139                                   acpi_adr_space_handler handler)
140 {
141         union acpi_operand_object *obj_desc;
142         union acpi_operand_object *handler_obj;
143         union acpi_operand_object *region_obj;
144         union acpi_operand_object **last_obj_ptr;
145         struct acpi_namespace_node *node;
146         acpi_status status;
147
148         ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
149
150         /* Parameter validation */
151
152         if (!device) {
153                 return_ACPI_STATUS(AE_BAD_PARAMETER);
154         }
155
156         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
157         if (ACPI_FAILURE(status)) {
158                 return_ACPI_STATUS(status);
159         }
160
161         /* Convert and validate the device handle */
162
163         node = acpi_ns_validate_handle(device);
164         if (!node ||
165             ((node->type != ACPI_TYPE_DEVICE) &&
166              (node->type != ACPI_TYPE_PROCESSOR) &&
167              (node->type != ACPI_TYPE_THERMAL) &&
168              (node != acpi_gbl_root_node))) {
169                 status = AE_BAD_PARAMETER;
170                 goto unlock_and_exit;
171         }
172
173         /* Make sure the internal object exists */
174
175         obj_desc = acpi_ns_get_attached_object(node);
176         if (!obj_desc) {
177                 status = AE_NOT_EXIST;
178                 goto unlock_and_exit;
179         }
180
181         /* Find the address handler the user requested */
182
183         handler_obj = obj_desc->common_notify.handler;
184         last_obj_ptr = &obj_desc->common_notify.handler;
185         while (handler_obj) {
186
187                 /* We have a handler, see if user requested this one */
188
189                 if (handler_obj->address_space.space_id == space_id) {
190
191                         /* Handler must be the same as the installed handler */
192
193                         if (handler_obj->address_space.handler != handler) {
194                                 status = AE_BAD_PARAMETER;
195                                 goto unlock_and_exit;
196                         }
197
198                         /* Matched space_id, first dereference this in the Regions */
199
200                         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
201                                           "Removing address handler %p(%p) for region %s "
202                                           "on Device %p(%p)\n",
203                                           handler_obj, handler,
204                                           acpi_ut_get_region_name(space_id),
205                                           node, obj_desc));
206
207                         region_obj = handler_obj->address_space.region_list;
208
209                         /* Walk the handler's region list */
210
211                         while (region_obj) {
212                                 /*
213                                  * First disassociate the handler from the region.
214                                  *
215                                  * NOTE: this doesn't mean that the region goes away
216                                  * The region is just inaccessible as indicated to
217                                  * the _REG method
218                                  */
219                                 acpi_ev_detach_region(region_obj, TRUE);
220
221                                 /*
222                                  * Walk the list: Just grab the head because the
223                                  * detach_region removed the previous head.
224                                  */
225                                 region_obj =
226                                     handler_obj->address_space.region_list;
227                         }
228
229                         /* Remove this Handler object from the list */
230
231                         *last_obj_ptr = handler_obj->address_space.next;
232
233                         /* Now we can delete the handler object */
234
235                         acpi_ut_remove_reference(handler_obj);
236                         goto unlock_and_exit;
237                 }
238
239                 /* Walk the linked list of handlers */
240
241                 last_obj_ptr = &handler_obj->address_space.next;
242                 handler_obj = handler_obj->address_space.next;
243         }
244
245         /* The handler does not exist */
246
247         ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
248                           "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
249                           handler, acpi_ut_get_region_name(space_id), space_id,
250                           node, obj_desc));
251
252         status = AE_NOT_EXIST;
253
254 unlock_and_exit:
255         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
256         return_ACPI_STATUS(status);
257 }
258
259 ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
260 /*******************************************************************************
261  *
262  * FUNCTION:    acpi_execute_reg_methods
263  *
264  * PARAMETERS:  device          - Handle for the device
265  *              max_depth       - Depth to which search for _REG
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, u32 max_depth,
275                          acpi_adr_space_type space_id)
276 {
277         struct acpi_namespace_node *node;
278         acpi_status status;
279
280         ACPI_FUNCTION_TRACE(acpi_execute_reg_methods);
281
282         /* Parameter validation */
283
284         if (!device) {
285                 return_ACPI_STATUS(AE_BAD_PARAMETER);
286         }
287
288         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
289         if (ACPI_FAILURE(status)) {
290                 return_ACPI_STATUS(status);
291         }
292
293         /* Convert and validate the device handle */
294
295         node = acpi_ns_validate_handle(device);
296         if (node) {
297
298                 /* Run all _REG methods for this address space */
299
300                 acpi_ev_execute_reg_methods(node, max_depth, space_id,
301                                             ACPI_REG_CONNECT);
302         } else {
303                 status = AE_BAD_PARAMETER;
304         }
305
306         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
307         return_ACPI_STATUS(status);
308 }
309
310 ACPI_EXPORT_SYMBOL(acpi_execute_reg_methods)
This page took 0.044131 seconds and 4 git commands to generate.