blob: b253063b09d39c1c3c5bb3c81a375c8cec8756cf [file] [log] [blame]
Erik Schmauss95857632018-03-14 16:13:07 -07001// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/******************************************************************************
3 *
4 * Module Name: evgpeblk - GPE block creation and initialization.
5 *
Bob Mooreda6f8322018-01-04 10:06:38 -08006 * Copyright (C) 2000 - 2018, Intel Corp.
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
Erik Schmauss95857632018-03-14 16:13:07 -07008 *****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
10#include <acpi/acpi.h>
Len Browne2f7a772009-01-09 00:30:03 -050011#include "accommon.h"
12#include "acevents.h"
13#include "acnamesp.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
15#define _COMPONENT ACPI_EVENTS
Len Brown4be44fc2005-08-05 00:44:28 -040016ACPI_MODULE_NAME("evgpeblk")
Bob Moore33620c52012-02-14 18:14:27 +080017#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
Robert Moore44f6c012005-04-18 22:49:35 -040018/* Local prototypes */
Len Brown4be44fc2005-08-05 00:44:28 -040019static acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040020acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
21 u32 interrupt_number);
Robert Moore44f6c012005-04-18 22:49:35 -040022
23static acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040024acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
26/*******************************************************************************
27 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 * FUNCTION: acpi_ev_install_gpe_block
29 *
Bob Moore9f15fc62008-11-12 16:01:56 +080030 * PARAMETERS: gpe_block - New GPE block
31 * interrupt_number - Xrupt to be associated with this
32 * GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -070033 *
34 * RETURN: Status
35 *
36 * DESCRIPTION: Install new GPE block with mutex support
37 *
38 ******************************************************************************/
39
40static acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -040041acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
42 u32 interrupt_number)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043{
Len Brown4be44fc2005-08-05 00:44:28 -040044 struct acpi_gpe_block_info *next_gpe_block;
45 struct acpi_gpe_xrupt_info *gpe_xrupt_block;
46 acpi_status status;
Bob Mooreb8e4d892006-01-27 16:43:00 -050047 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Bob Mooreb229cf92006-04-21 17:15:00 -040049 ACPI_FUNCTION_TRACE(ev_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Len Brown4be44fc2005-08-05 00:44:28 -040051 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
52 if (ACPI_FAILURE(status)) {
53 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 }
55
Bob Moore4bec3d82014-01-08 13:44:10 +080056 status =
57 acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block);
58 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070059 goto unlock_and_exit;
60 }
61
Robert Moore44f6c012005-04-18 22:49:35 -040062 /* Install the new block at the end of the list with lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
Len Brown4be44fc2005-08-05 00:44:28 -040064 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 if (gpe_xrupt_block->gpe_block_list_head) {
66 next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
67 while (next_gpe_block->next) {
68 next_gpe_block = next_gpe_block->next;
69 }
70
71 next_gpe_block->next = gpe_block;
72 gpe_block->previous = next_gpe_block;
Len Brown4be44fc2005-08-05 00:44:28 -040073 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 gpe_xrupt_block->gpe_block_list_head = gpe_block;
75 }
76
77 gpe_block->xrupt_block = gpe_xrupt_block;
Len Brown4be44fc2005-08-05 00:44:28 -040078 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070079
Lv Zheng10622bf2013-10-29 09:30:02 +080080unlock_and_exit:
Bob Moore4bec3d82014-01-08 13:44:10 +080081 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
Len Brown4be44fc2005-08-05 00:44:28 -040082 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083}
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085/*******************************************************************************
86 *
87 * FUNCTION: acpi_ev_delete_gpe_block
88 *
Bob Moore9f15fc62008-11-12 16:01:56 +080089 * PARAMETERS: gpe_block - Existing GPE block
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 *
91 * RETURN: Status
92 *
93 * DESCRIPTION: Remove a GPE block
94 *
95 ******************************************************************************/
96
Len Brown4be44fc2005-08-05 00:44:28 -040097acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
Len Brown4be44fc2005-08-05 00:44:28 -040099 acpi_status status;
Bob Mooreb8e4d892006-01-27 16:43:00 -0500100 acpi_cpu_flags flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Bob Mooreb229cf92006-04-21 17:15:00 -0400102 ACPI_FUNCTION_TRACE(ev_install_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Len Brown4be44fc2005-08-05 00:44:28 -0400104 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
105 if (ACPI_FAILURE(status)) {
106 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 }
108
109 /* Disable all GPEs in this block */
110
Bob Mooree97d6bf2008-12-30 09:45:17 +0800111 status =
112 acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
114 if (!gpe_block->previous && !gpe_block->next) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400115
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 /* This is the last gpe_block on this interrupt */
117
Len Brown4be44fc2005-08-05 00:44:28 -0400118 status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
119 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 goto unlock_and_exit;
121 }
Len Brown4be44fc2005-08-05 00:44:28 -0400122 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 /* Remove the block on this interrupt with lock */
124
Len Brown4be44fc2005-08-05 00:44:28 -0400125 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 if (gpe_block->previous) {
127 gpe_block->previous->next = gpe_block->next;
Len Brown4be44fc2005-08-05 00:44:28 -0400128 } else {
129 gpe_block->xrupt_block->gpe_block_list_head =
130 gpe_block->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 }
132
133 if (gpe_block->next) {
134 gpe_block->next->previous = gpe_block->previous;
135 }
Bob Moore1fad8732015-12-29 13:54:36 +0800136
Len Brown4be44fc2005-08-05 00:44:28 -0400137 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 }
139
Lin Ming0f849d22010-04-06 14:52:37 +0800140 acpi_current_gpe_count -= gpe_block->gpe_count;
Bob Mooree97d6bf2008-12-30 09:45:17 +0800141
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 /* Free the gpe_block */
143
Bob Moore83135242006-10-03 00:00:00 -0400144 ACPI_FREE(gpe_block->register_info);
145 ACPI_FREE(gpe_block->event_info);
146 ACPI_FREE(gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Lv Zheng10622bf2013-10-29 09:30:02 +0800148unlock_and_exit:
Len Brown4be44fc2005-08-05 00:44:28 -0400149 status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
150 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151}
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153/*******************************************************************************
154 *
155 * FUNCTION: acpi_ev_create_gpe_info_blocks
156 *
157 * PARAMETERS: gpe_block - New GPE block
158 *
159 * RETURN: Status
160 *
161 * DESCRIPTION: Create the register_info and event_info blocks for this GPE block
162 *
163 ******************************************************************************/
164
165static acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400166acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167{
Len Brown4be44fc2005-08-05 00:44:28 -0400168 struct acpi_gpe_register_info *gpe_register_info = NULL;
169 struct acpi_gpe_event_info *gpe_event_info = NULL;
170 struct acpi_gpe_event_info *this_event;
171 struct acpi_gpe_register_info *this_register;
Bob Moore67a119f2008-06-10 13:42:13 +0800172 u32 i;
173 u32 j;
Len Brown4be44fc2005-08-05 00:44:28 -0400174 acpi_status status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Bob Mooreb229cf92006-04-21 17:15:00 -0400176 ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
178 /* Allocate the GPE register information block */
179
Lv Zhengf5c1e1c2016-05-05 12:57:53 +0800180 gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->
Bob Moore83135242006-10-03 00:00:00 -0400181 register_count *
182 sizeof(struct
183 acpi_gpe_register_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 if (!gpe_register_info) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500185 ACPI_ERROR((AE_INFO,
Bob Mooreb229cf92006-04-21 17:15:00 -0400186 "Could not allocate the GpeRegisterInfo table"));
Len Brown4be44fc2005-08-05 00:44:28 -0400187 return_ACPI_STATUS(AE_NO_MEMORY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188 }
189
190 /*
191 * Allocate the GPE event_info block. There are eight distinct GPEs
Bob Moore96db2552005-11-02 00:00:00 -0500192 * per register. Initialization to zeros is sufficient.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193 */
Lv Zhengf5c1e1c2016-05-05 12:57:53 +0800194 gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->gpe_count *
Bob Moore83135242006-10-03 00:00:00 -0400195 sizeof(struct
196 acpi_gpe_event_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 if (!gpe_event_info) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500198 ACPI_ERROR((AE_INFO,
Bob Mooreb229cf92006-04-21 17:15:00 -0400199 "Could not allocate the GpeEventInfo table"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 status = AE_NO_MEMORY;
201 goto error_exit;
202 }
203
204 /* Save the new Info arrays in the GPE block */
205
206 gpe_block->register_info = gpe_register_info;
Len Brown4be44fc2005-08-05 00:44:28 -0400207 gpe_block->event_info = gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
209 /*
Bob Moore96db2552005-11-02 00:00:00 -0500210 * Initialize the GPE Register and Event structures. A goal of these
Bob Moore9f15fc62008-11-12 16:01:56 +0800211 * tables is to hide the fact that there are two separate GPE register
212 * sets in a given GPE hardware block, the status registers occupy the
213 * first half, and the enable registers occupy the second half.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 */
215 this_register = gpe_register_info;
Len Brown4be44fc2005-08-05 00:44:28 -0400216 this_event = gpe_event_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
218 for (i = 0; i < gpe_block->register_count; i++) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400219
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 /* Init the register_info for this GPE register (8 GPEs) */
221
Bob Moore7505da42014-04-30 10:06:15 +0800222 this_register->base_gpe_number = (u16)
223 (gpe_block->block_base_number +
224 (i * ACPI_GPE_REGISTER_WIDTH));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Bob Moore7505da42014-04-30 10:06:15 +0800226 this_register->status_address.address = gpe_block->address + i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
Bob Moore59fa8502007-02-02 19:48:23 +0300228 this_register->enable_address.address =
Bob Moore7505da42014-04-30 10:06:15 +0800229 gpe_block->address + i + gpe_block->register_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
Bob Moore7505da42014-04-30 10:06:15 +0800231 this_register->status_address.space_id = gpe_block->space_id;
232 this_register->enable_address.space_id = gpe_block->space_id;
Bob Mooref3d2e782007-02-02 19:48:18 +0300233 this_register->status_address.bit_width =
Len Brown4be44fc2005-08-05 00:44:28 -0400234 ACPI_GPE_REGISTER_WIDTH;
Bob Mooref3d2e782007-02-02 19:48:18 +0300235 this_register->enable_address.bit_width =
Len Brown4be44fc2005-08-05 00:44:28 -0400236 ACPI_GPE_REGISTER_WIDTH;
Bob Mooreecfbbc72008-12-31 02:55:32 +0800237 this_register->status_address.bit_offset = 0;
238 this_register->enable_address.bit_offset = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
240 /* Init the event_info for each GPE within this register */
241
242 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
Alexey Starikovskiy69874162007-02-02 19:48:19 +0300243 this_event->gpe_number =
244 (u8) (this_register->base_gpe_number + j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 this_event->register_info = this_register;
246 this_event++;
247 }
248
Bob Moore96db2552005-11-02 00:00:00 -0500249 /* Disable all GPEs within this register */
250
Bob Moorec6b57742009-06-24 09:44:06 +0800251 status = acpi_hw_write(0x00, &this_register->enable_address);
Len Brown4be44fc2005-08-05 00:44:28 -0400252 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 goto error_exit;
254 }
255
Bob Moore96db2552005-11-02 00:00:00 -0500256 /* Clear any pending GPE events within this register */
257
Bob Moorec6b57742009-06-24 09:44:06 +0800258 status = acpi_hw_write(0xFF, &this_register->status_address);
Len Brown4be44fc2005-08-05 00:44:28 -0400259 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 goto error_exit;
261 }
262
263 this_register++;
264 }
265
Len Brown4be44fc2005-08-05 00:44:28 -0400266 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Lv Zheng10622bf2013-10-29 09:30:02 +0800268error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 if (gpe_register_info) {
Bob Moore83135242006-10-03 00:00:00 -0400270 ACPI_FREE(gpe_register_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 }
272 if (gpe_event_info) {
Bob Moore83135242006-10-03 00:00:00 -0400273 ACPI_FREE(gpe_event_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 }
275
Len Brown4be44fc2005-08-05 00:44:28 -0400276 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277}
278
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279/*******************************************************************************
280 *
281 * FUNCTION: acpi_ev_create_gpe_block
282 *
283 * PARAMETERS: gpe_device - Handle to the parent GPE block
Bob Mooreba494be2012-07-12 09:40:10 +0800284 * gpe_block_address - Address and space_ID
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 * register_count - Number of GPE register pairs in the block
286 * gpe_block_base_number - Starting GPE number for the block
Robert Moore6f42ccf2005-05-13 00:00:00 -0400287 * interrupt_number - H/W interrupt for the block
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 * return_gpe_block - Where the new block descriptor is returned
289 *
290 * RETURN: Status
291 *
Bob Moore96db2552005-11-02 00:00:00 -0500292 * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
293 * the block are disabled at exit.
294 * Note: Assumes namespace is locked.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 *
296 ******************************************************************************/
297
298acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400299acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
Bob Moore7505da42014-04-30 10:06:15 +0800300 u64 address,
301 u8 space_id,
Len Brown4be44fc2005-08-05 00:44:28 -0400302 u32 register_count,
Bob Moore7505da42014-04-30 10:06:15 +0800303 u16 gpe_block_base_number,
Len Brown4be44fc2005-08-05 00:44:28 -0400304 u32 interrupt_number,
305 struct acpi_gpe_block_info **return_gpe_block)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
Len Brown4be44fc2005-08-05 00:44:28 -0400307 acpi_status status;
Bob Moore96db2552005-11-02 00:00:00 -0500308 struct acpi_gpe_block_info *gpe_block;
Bob Moore186c3072010-04-27 11:32:28 +0800309 struct acpi_gpe_walk_info walk_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
Bob Mooreb229cf92006-04-21 17:15:00 -0400311 ACPI_FUNCTION_TRACE(ev_create_gpe_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
313 if (!register_count) {
Len Brown4be44fc2005-08-05 00:44:28 -0400314 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 }
316
317 /* Allocate a new GPE block */
318
Bob Moore83135242006-10-03 00:00:00 -0400319 gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 if (!gpe_block) {
Len Brown4be44fc2005-08-05 00:44:28 -0400321 return_ACPI_STATUS(AE_NO_MEMORY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 }
323
324 /* Initialize the new GPE block */
325
Bob Moore7505da42014-04-30 10:06:15 +0800326 gpe_block->address = address;
327 gpe_block->space_id = space_id;
Bob Moore96db2552005-11-02 00:00:00 -0500328 gpe_block->node = gpe_device;
Lin Ming0f849d22010-04-06 14:52:37 +0800329 gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
Lin Mingda503372010-12-13 13:39:37 +0800330 gpe_block->initialized = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 gpe_block->register_count = register_count;
332 gpe_block->block_base_number = gpe_block_base_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Bob Moore96db2552005-11-02 00:00:00 -0500334 /*
335 * Create the register_info and event_info sub-structures
336 * Note: disables and clears all GPEs in the block
337 */
Len Brown4be44fc2005-08-05 00:44:28 -0400338 status = acpi_ev_create_gpe_info_blocks(gpe_block);
339 if (ACPI_FAILURE(status)) {
Bob Moore83135242006-10-03 00:00:00 -0400340 ACPI_FREE(gpe_block);
Len Brown4be44fc2005-08-05 00:44:28 -0400341 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 }
343
Bob Moore96db2552005-11-02 00:00:00 -0500344 /* Install the new block in the global lists */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
Len Brown4be44fc2005-08-05 00:44:28 -0400346 status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
347 if (ACPI_FAILURE(status)) {
Tomasz Nowickib739f102013-06-08 01:00:07 +0000348 ACPI_FREE(gpe_block->register_info);
349 ACPI_FREE(gpe_block->event_info);
Bob Moore83135242006-10-03 00:00:00 -0400350 ACPI_FREE(gpe_block);
Len Brown4be44fc2005-08-05 00:44:28 -0400351 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 }
353
Lin Ming3a378982010-12-13 13:36:15 +0800354 acpi_gbl_all_gpes_initialized = FALSE;
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200355
Bob Moore186c3072010-04-27 11:32:28 +0800356 /* Find all GPE methods (_Lxx or_Exx) for this block */
357
358 walk_info.gpe_block = gpe_block;
359 walk_info.gpe_device = gpe_device;
Bob Moore186c3072010-04-27 11:32:28 +0800360 walk_info.execute_by_owner_id = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Len Brown4be44fc2005-08-05 00:44:28 -0400362 status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
363 ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
Lin Ming0f849d22010-04-06 14:52:37 +0800364 acpi_ev_match_gpe_method, NULL,
Bob Moore186c3072010-04-27 11:32:28 +0800365 &walk_info, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Bob Moore96db2552005-11-02 00:00:00 -0500367 /* Return the new block */
368
369 if (return_gpe_block) {
370 (*return_gpe_block) = gpe_block;
371 }
372
Bob Moore3e5621a2012-12-31 00:07:13 +0000373 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
Bob Moore7505da42014-04-30 10:06:15 +0800374 " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
Bob Moore3e5621a2012-12-31 00:07:13 +0000375 (u32)gpe_block->block_base_number,
376 (u32)(gpe_block->block_base_number +
377 (gpe_block->gpe_count - 1)),
378 gpe_device->name.ascii, gpe_block->register_count,
Bob Moore7505da42014-04-30 10:06:15 +0800379 interrupt_number,
380 interrupt_number ==
381 acpi_gbl_FADT.sci_interrupt ? " (SCI)" : ""));
Bob Moore96db2552005-11-02 00:00:00 -0500382
Bob Mooree97d6bf2008-12-30 09:45:17 +0800383 /* Update global count of currently available GPEs */
384
Lin Ming0f849d22010-04-06 14:52:37 +0800385 acpi_current_gpe_count += gpe_block->gpe_count;
Bob Moore96db2552005-11-02 00:00:00 -0500386 return_ACPI_STATUS(AE_OK);
387}
388
389/*******************************************************************************
390 *
391 * FUNCTION: acpi_ev_initialize_gpe_block
392 *
Lin Mingda503372010-12-13 13:39:37 +0800393 * PARAMETERS: acpi_gpe_callback
Bob Moore96db2552005-11-02 00:00:00 -0500394 *
395 * RETURN: Status
396 *
Lin Mingda503372010-12-13 13:39:37 +0800397 * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
398 * associated methods.
Bob Moore96db2552005-11-02 00:00:00 -0500399 * Note: Assumes namespace is locked.
400 *
401 ******************************************************************************/
402
403acpi_status
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200404acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
405 struct acpi_gpe_block_info *gpe_block,
Erik Schmauss87cd8262018-03-14 16:12:59 -0700406 void *context)
Bob Moore96db2552005-11-02 00:00:00 -0500407{
Lin Ming0f849d22010-04-06 14:52:37 +0800408 acpi_status status;
Bob Moore96db2552005-11-02 00:00:00 -0500409 struct acpi_gpe_event_info *gpe_event_info;
Bob Moore96db2552005-11-02 00:00:00 -0500410 u32 gpe_enabled_count;
Lin Ming0f849d22010-04-06 14:52:37 +0800411 u32 gpe_index;
Bob Moore67a119f2008-06-10 13:42:13 +0800412 u32 i;
413 u32 j;
Erik Schmauss87cd8262018-03-14 16:12:59 -0700414 u8 *is_polling_needed = context;
Erik Schmauss0fe0beb2018-03-14 16:13:05 -0700415 ACPI_ERROR_ONLY(u32 gpe_number);
Bob Moore96db2552005-11-02 00:00:00 -0500416
Bob Mooreb229cf92006-04-21 17:15:00 -0400417 ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
Bob Moore96db2552005-11-02 00:00:00 -0500418
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200419 /*
Lin Mingda503372010-12-13 13:39:37 +0800420 * Ignore a null GPE block (e.g., if no GPE block 1 exists), and
421 * any GPE blocks that have been initialized already.
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200422 */
423 if (!gpe_block || gpe_block->initialized) {
Bob Moore96db2552005-11-02 00:00:00 -0500424 return_ACPI_STATUS(AE_OK);
425 }
426
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 /*
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200428 * Enable all GPEs that have a corresponding method and have the
Lin Mingda503372010-12-13 13:39:37 +0800429 * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
430 * must be enabled via the acpi_enable_gpe() interface.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 gpe_enabled_count = 0;
Lin Ming0f849d22010-04-06 14:52:37 +0800433
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 for (i = 0; i < gpe_block->register_count; i++) {
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100435 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400436
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 /* Get the info block for this particular GPE */
Lin Ming0f849d22010-04-06 14:52:37 +0800438
439 gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100440 gpe_event_info = &gpe_block->event_info[gpe_index];
Erik Schmauss0fe0beb2018-03-14 16:13:05 -0700441 ACPI_ERROR_ONLY(gpe_number =
442 gpe_block->block_base_number +
443 gpe_index);
Erik Schmauss87cd8262018-03-14 16:12:59 -0700444 gpe_event_info->flags |= ACPI_GPE_INITIALIZED;
Rafael J. Wysockice43ace2010-06-08 10:50:20 +0200445
Lin Mingbba63a22010-12-13 13:39:17 +0800446 /*
447 * Ignore GPEs that have no corresponding _Lxx/_Exx method
Rafael J. Wysockiecc11652017-08-10 00:30:09 +0200448 * and GPEs that are used for wakeup
Lin Mingbba63a22010-12-13 13:39:17 +0800449 */
Rafael J. Wysockiecc11652017-08-10 00:30:09 +0200450 if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
451 ACPI_GPE_DISPATCH_METHOD)
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200452 || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100453 continue;
Lin Ming0f849d22010-04-06 14:52:37 +0800454 }
455
Lin Ming3a378982010-12-13 13:36:15 +0800456 status = acpi_ev_add_gpe_reference(gpe_event_info);
Lin Ming0f849d22010-04-06 14:52:37 +0800457 if (ACPI_FAILURE(status)) {
458 ACPI_EXCEPTION((AE_INFO, status,
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200459 "Could not enable GPE 0x%02X",
Rafael J. Wysockiecc11652017-08-10 00:30:09 +0200460 gpe_number));
Lin Ming0f849d22010-04-06 14:52:37 +0800461 continue;
462 }
463
Rafael J. Wysocki1312b7e2017-08-10 00:31:58 +0200464 gpe_event_info->flags |= ACPI_GPE_AUTO_ENABLED;
465
Erik Schmauss87cd8262018-03-14 16:12:59 -0700466 if (is_polling_needed &&
467 ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
468 *is_polling_needed = TRUE;
Rafael J. Wysockiecc11652017-08-10 00:30:09 +0200469 }
470
Lin Ming0f849d22010-04-06 14:52:37 +0800471 gpe_enabled_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 }
473 }
474
Rafael J. Wysocki98746472010-07-08 00:43:36 +0200475 if (gpe_enabled_count) {
Bob Moore05fb04b2016-02-19 14:16:42 +0800476 ACPI_INFO(("Enabled %u GPEs in block %02X to %02X",
Bob Moore3e5621a2012-12-31 00:07:13 +0000477 gpe_enabled_count, (u32)gpe_block->block_base_number,
478 (u32)(gpe_block->block_base_number +
479 (gpe_block->gpe_count - 1))));
Bob Moore186c3072010-04-27 11:32:28 +0800480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Rafael J. Wysockia2100802010-09-16 00:30:43 +0200482 gpe_block->initialized = TRUE;
483
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +0100484 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485}
Bob Moore33620c52012-02-14 18:14:27 +0800486
487#endif /* !ACPI_REDUCED_HARDWARE */