xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/evgpeblk.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: evgpeblk - GPE block creation and initialization.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2000 - 2020, Intel Corp.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *****************************************************************************/
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <acpi/acpi.h>
11*4882a593Smuzhiyun #include "accommon.h"
12*4882a593Smuzhiyun #include "acevents.h"
13*4882a593Smuzhiyun #include "acnamesp.h"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #define _COMPONENT          ACPI_EVENTS
16*4882a593Smuzhiyun ACPI_MODULE_NAME("evgpeblk")
17*4882a593Smuzhiyun #if (!ACPI_REDUCED_HARDWARE)	/* Entire module */
18*4882a593Smuzhiyun /* Local prototypes */
19*4882a593Smuzhiyun static acpi_status
20*4882a593Smuzhiyun acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
21*4882a593Smuzhiyun 			  u32 interrupt_number);
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun static acpi_status
24*4882a593Smuzhiyun acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /*******************************************************************************
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * FUNCTION:    acpi_ev_install_gpe_block
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  * PARAMETERS:  gpe_block               - New GPE block
31*4882a593Smuzhiyun  *              interrupt_number        - Xrupt to be associated with this
32*4882a593Smuzhiyun  *                                        GPE block
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  * RETURN:      Status
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  * DESCRIPTION: Install new GPE block with mutex support
37*4882a593Smuzhiyun  *
38*4882a593Smuzhiyun  ******************************************************************************/
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static acpi_status
acpi_ev_install_gpe_block(struct acpi_gpe_block_info * gpe_block,u32 interrupt_number)41*4882a593Smuzhiyun acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
42*4882a593Smuzhiyun 			  u32 interrupt_number)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	struct acpi_gpe_block_info *next_gpe_block;
45*4882a593Smuzhiyun 	struct acpi_gpe_xrupt_info *gpe_xrupt_block;
46*4882a593Smuzhiyun 	acpi_status status;
47*4882a593Smuzhiyun 	acpi_cpu_flags flags;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ev_install_gpe_block);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
52*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
53*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
54*4882a593Smuzhiyun 	}
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	status =
57*4882a593Smuzhiyun 	    acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block);
58*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
59*4882a593Smuzhiyun 		goto unlock_and_exit;
60*4882a593Smuzhiyun 	}
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	/* Install the new block at the end of the list with lock */
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
65*4882a593Smuzhiyun 	if (gpe_xrupt_block->gpe_block_list_head) {
66*4882a593Smuzhiyun 		next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
67*4882a593Smuzhiyun 		while (next_gpe_block->next) {
68*4882a593Smuzhiyun 			next_gpe_block = next_gpe_block->next;
69*4882a593Smuzhiyun 		}
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 		next_gpe_block->next = gpe_block;
72*4882a593Smuzhiyun 		gpe_block->previous = next_gpe_block;
73*4882a593Smuzhiyun 	} else {
74*4882a593Smuzhiyun 		gpe_xrupt_block->gpe_block_list_head = gpe_block;
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	gpe_block->xrupt_block = gpe_xrupt_block;
78*4882a593Smuzhiyun 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun unlock_and_exit:
81*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
82*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun /*******************************************************************************
86*4882a593Smuzhiyun  *
87*4882a593Smuzhiyun  * FUNCTION:    acpi_ev_delete_gpe_block
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  * PARAMETERS:  gpe_block           - Existing GPE block
90*4882a593Smuzhiyun  *
91*4882a593Smuzhiyun  * RETURN:      Status
92*4882a593Smuzhiyun  *
93*4882a593Smuzhiyun  * DESCRIPTION: Remove a GPE block
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  ******************************************************************************/
96*4882a593Smuzhiyun 
acpi_ev_delete_gpe_block(struct acpi_gpe_block_info * gpe_block)97*4882a593Smuzhiyun acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	acpi_status status;
100*4882a593Smuzhiyun 	acpi_cpu_flags flags;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ev_install_gpe_block);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
105*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
106*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
107*4882a593Smuzhiyun 	}
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	/* Disable all GPEs in this block */
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	status =
112*4882a593Smuzhiyun 	    acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL);
113*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
114*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	if (!gpe_block->previous && !gpe_block->next) {
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 		/* This is the last gpe_block on this interrupt */
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 		status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
122*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
123*4882a593Smuzhiyun 			goto unlock_and_exit;
124*4882a593Smuzhiyun 		}
125*4882a593Smuzhiyun 	} else {
126*4882a593Smuzhiyun 		/* Remove the block on this interrupt with lock */
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 		flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
129*4882a593Smuzhiyun 		if (gpe_block->previous) {
130*4882a593Smuzhiyun 			gpe_block->previous->next = gpe_block->next;
131*4882a593Smuzhiyun 		} else {
132*4882a593Smuzhiyun 			gpe_block->xrupt_block->gpe_block_list_head =
133*4882a593Smuzhiyun 			    gpe_block->next;
134*4882a593Smuzhiyun 		}
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 		if (gpe_block->next) {
137*4882a593Smuzhiyun 			gpe_block->next->previous = gpe_block->previous;
138*4882a593Smuzhiyun 		}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 		acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	acpi_current_gpe_count -= gpe_block->gpe_count;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	/* Free the gpe_block */
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	ACPI_FREE(gpe_block->register_info);
148*4882a593Smuzhiyun 	ACPI_FREE(gpe_block->event_info);
149*4882a593Smuzhiyun 	ACPI_FREE(gpe_block);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun unlock_and_exit:
152*4882a593Smuzhiyun 	status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
153*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun /*******************************************************************************
157*4882a593Smuzhiyun  *
158*4882a593Smuzhiyun  * FUNCTION:    acpi_ev_create_gpe_info_blocks
159*4882a593Smuzhiyun  *
160*4882a593Smuzhiyun  * PARAMETERS:  gpe_block   - New GPE block
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  * RETURN:      Status
163*4882a593Smuzhiyun  *
164*4882a593Smuzhiyun  * DESCRIPTION: Create the register_info and event_info blocks for this GPE block
165*4882a593Smuzhiyun  *
166*4882a593Smuzhiyun  ******************************************************************************/
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static acpi_status
acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info * gpe_block)169*4882a593Smuzhiyun acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct acpi_gpe_register_info *gpe_register_info = NULL;
172*4882a593Smuzhiyun 	struct acpi_gpe_event_info *gpe_event_info = NULL;
173*4882a593Smuzhiyun 	struct acpi_gpe_event_info *this_event;
174*4882a593Smuzhiyun 	struct acpi_gpe_register_info *this_register;
175*4882a593Smuzhiyun 	u32 i;
176*4882a593Smuzhiyun 	u32 j;
177*4882a593Smuzhiyun 	acpi_status status;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	/* Allocate the GPE register information block */
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->
184*4882a593Smuzhiyun 						 register_count *
185*4882a593Smuzhiyun 						 sizeof(struct
186*4882a593Smuzhiyun 							acpi_gpe_register_info));
187*4882a593Smuzhiyun 	if (!gpe_register_info) {
188*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO,
189*4882a593Smuzhiyun 			    "Could not allocate the GpeRegisterInfo table"));
190*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/*
194*4882a593Smuzhiyun 	 * Allocate the GPE event_info block. There are eight distinct GPEs
195*4882a593Smuzhiyun 	 * per register. Initialization to zeros is sufficient.
196*4882a593Smuzhiyun 	 */
197*4882a593Smuzhiyun 	gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->gpe_count *
198*4882a593Smuzhiyun 					      sizeof(struct
199*4882a593Smuzhiyun 						     acpi_gpe_event_info));
200*4882a593Smuzhiyun 	if (!gpe_event_info) {
201*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO,
202*4882a593Smuzhiyun 			    "Could not allocate the GpeEventInfo table"));
203*4882a593Smuzhiyun 		status = AE_NO_MEMORY;
204*4882a593Smuzhiyun 		goto error_exit;
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	/* Save the new Info arrays in the GPE block */
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	gpe_block->register_info = gpe_register_info;
210*4882a593Smuzhiyun 	gpe_block->event_info = gpe_event_info;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	/*
213*4882a593Smuzhiyun 	 * Initialize the GPE Register and Event structures. A goal of these
214*4882a593Smuzhiyun 	 * tables is to hide the fact that there are two separate GPE register
215*4882a593Smuzhiyun 	 * sets in a given GPE hardware block, the status registers occupy the
216*4882a593Smuzhiyun 	 * first half, and the enable registers occupy the second half.
217*4882a593Smuzhiyun 	 */
218*4882a593Smuzhiyun 	this_register = gpe_register_info;
219*4882a593Smuzhiyun 	this_event = gpe_event_info;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	for (i = 0; i < gpe_block->register_count; i++) {
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 		/* Init the register_info for this GPE register (8 GPEs) */
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 		this_register->base_gpe_number = (u16)
226*4882a593Smuzhiyun 		    (gpe_block->block_base_number +
227*4882a593Smuzhiyun 		     (i * ACPI_GPE_REGISTER_WIDTH));
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 		this_register->status_address.address = gpe_block->address + i;
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 		this_register->enable_address.address =
232*4882a593Smuzhiyun 		    gpe_block->address + i + gpe_block->register_count;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 		this_register->status_address.space_id = gpe_block->space_id;
235*4882a593Smuzhiyun 		this_register->enable_address.space_id = gpe_block->space_id;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		/* Init the event_info for each GPE within this register */
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
240*4882a593Smuzhiyun 			this_event->gpe_number =
241*4882a593Smuzhiyun 			    (u8) (this_register->base_gpe_number + j);
242*4882a593Smuzhiyun 			this_event->register_info = this_register;
243*4882a593Smuzhiyun 			this_event++;
244*4882a593Smuzhiyun 		}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 		/* Disable all GPEs within this register */
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 		status = acpi_hw_gpe_write(0x00, &this_register->enable_address);
249*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
250*4882a593Smuzhiyun 			goto error_exit;
251*4882a593Smuzhiyun 		}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 		/* Clear any pending GPE events within this register */
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		status = acpi_hw_gpe_write(0xFF, &this_register->status_address);
256*4882a593Smuzhiyun 		if (ACPI_FAILURE(status)) {
257*4882a593Smuzhiyun 			goto error_exit;
258*4882a593Smuzhiyun 		}
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 		this_register++;
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun error_exit:
266*4882a593Smuzhiyun 	if (gpe_register_info) {
267*4882a593Smuzhiyun 		ACPI_FREE(gpe_register_info);
268*4882a593Smuzhiyun 	}
269*4882a593Smuzhiyun 	if (gpe_event_info) {
270*4882a593Smuzhiyun 		ACPI_FREE(gpe_event_info);
271*4882a593Smuzhiyun 	}
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun /*******************************************************************************
277*4882a593Smuzhiyun  *
278*4882a593Smuzhiyun  * FUNCTION:    acpi_ev_create_gpe_block
279*4882a593Smuzhiyun  *
280*4882a593Smuzhiyun  * PARAMETERS:  gpe_device          - Handle to the parent GPE block
281*4882a593Smuzhiyun  *              gpe_block_address   - Address and space_ID
282*4882a593Smuzhiyun  *              register_count      - Number of GPE register pairs in the block
283*4882a593Smuzhiyun  *              gpe_block_base_number - Starting GPE number for the block
284*4882a593Smuzhiyun  *              interrupt_number    - H/W interrupt for the block
285*4882a593Smuzhiyun  *              return_gpe_block    - Where the new block descriptor is returned
286*4882a593Smuzhiyun  *
287*4882a593Smuzhiyun  * RETURN:      Status
288*4882a593Smuzhiyun  *
289*4882a593Smuzhiyun  * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
290*4882a593Smuzhiyun  *              the block are disabled at exit.
291*4882a593Smuzhiyun  *              Note: Assumes namespace is locked.
292*4882a593Smuzhiyun  *
293*4882a593Smuzhiyun  ******************************************************************************/
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node * gpe_device,u64 address,u8 space_id,u32 register_count,u16 gpe_block_base_number,u32 interrupt_number,struct acpi_gpe_block_info ** return_gpe_block)296*4882a593Smuzhiyun acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
297*4882a593Smuzhiyun 			 u64 address,
298*4882a593Smuzhiyun 			 u8 space_id,
299*4882a593Smuzhiyun 			 u32 register_count,
300*4882a593Smuzhiyun 			 u16 gpe_block_base_number,
301*4882a593Smuzhiyun 			 u32 interrupt_number,
302*4882a593Smuzhiyun 			 struct acpi_gpe_block_info **return_gpe_block)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun 	acpi_status status;
305*4882a593Smuzhiyun 	struct acpi_gpe_block_info *gpe_block;
306*4882a593Smuzhiyun 	struct acpi_gpe_walk_info walk_info;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ev_create_gpe_block);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	if (!register_count) {
311*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_OK);
312*4882a593Smuzhiyun 	}
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	/* Validate the space_ID */
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
317*4882a593Smuzhiyun 	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
318*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO,
319*4882a593Smuzhiyun 			    "Unsupported address space: 0x%X", space_id));
320*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_SUPPORT);
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
324*4882a593Smuzhiyun 		status = acpi_hw_validate_io_block(address,
325*4882a593Smuzhiyun 						   ACPI_GPE_REGISTER_WIDTH,
326*4882a593Smuzhiyun 						   register_count);
327*4882a593Smuzhiyun 		if (ACPI_FAILURE(status))
328*4882a593Smuzhiyun 			return_ACPI_STATUS(status);
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	/* Allocate a new GPE block */
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
334*4882a593Smuzhiyun 	if (!gpe_block) {
335*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	/* Initialize the new GPE block */
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	gpe_block->address = address;
341*4882a593Smuzhiyun 	gpe_block->space_id = space_id;
342*4882a593Smuzhiyun 	gpe_block->node = gpe_device;
343*4882a593Smuzhiyun 	gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
344*4882a593Smuzhiyun 	gpe_block->initialized = FALSE;
345*4882a593Smuzhiyun 	gpe_block->register_count = register_count;
346*4882a593Smuzhiyun 	gpe_block->block_base_number = gpe_block_base_number;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	/*
349*4882a593Smuzhiyun 	 * Create the register_info and event_info sub-structures
350*4882a593Smuzhiyun 	 * Note: disables and clears all GPEs in the block
351*4882a593Smuzhiyun 	 */
352*4882a593Smuzhiyun 	status = acpi_ev_create_gpe_info_blocks(gpe_block);
353*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
354*4882a593Smuzhiyun 		ACPI_FREE(gpe_block);
355*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	/* Install the new block in the global lists */
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
361*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
362*4882a593Smuzhiyun 		ACPI_FREE(gpe_block->register_info);
363*4882a593Smuzhiyun 		ACPI_FREE(gpe_block->event_info);
364*4882a593Smuzhiyun 		ACPI_FREE(gpe_block);
365*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	acpi_gbl_all_gpes_initialized = FALSE;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	/* Find all GPE methods (_Lxx or_Exx) for this block */
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	walk_info.gpe_block = gpe_block;
373*4882a593Smuzhiyun 	walk_info.gpe_device = gpe_device;
374*4882a593Smuzhiyun 	walk_info.execute_by_owner_id = FALSE;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	(void)acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
377*4882a593Smuzhiyun 				     ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
378*4882a593Smuzhiyun 				     acpi_ev_match_gpe_method, NULL, &walk_info,
379*4882a593Smuzhiyun 				     NULL);
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	/* Return the new block */
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	if (return_gpe_block) {
384*4882a593Smuzhiyun 		(*return_gpe_block) = gpe_block;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
388*4882a593Smuzhiyun 			      "    Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
389*4882a593Smuzhiyun 			      (u32)gpe_block->block_base_number,
390*4882a593Smuzhiyun 			      (u32)(gpe_block->block_base_number +
391*4882a593Smuzhiyun 				    (gpe_block->gpe_count - 1)),
392*4882a593Smuzhiyun 			      gpe_device->name.ascii, gpe_block->register_count,
393*4882a593Smuzhiyun 			      interrupt_number,
394*4882a593Smuzhiyun 			      interrupt_number ==
395*4882a593Smuzhiyun 			      acpi_gbl_FADT.sci_interrupt ? " (SCI)" : ""));
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	/* Update global count of currently available GPEs */
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	acpi_current_gpe_count += gpe_block->gpe_count;
400*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun /*******************************************************************************
404*4882a593Smuzhiyun  *
405*4882a593Smuzhiyun  * FUNCTION:    acpi_ev_initialize_gpe_block
406*4882a593Smuzhiyun  *
407*4882a593Smuzhiyun  * PARAMETERS:  acpi_gpe_callback
408*4882a593Smuzhiyun  *
409*4882a593Smuzhiyun  * RETURN:      Status
410*4882a593Smuzhiyun  *
411*4882a593Smuzhiyun  * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
412*4882a593Smuzhiyun  *              associated methods.
413*4882a593Smuzhiyun  *              Note: Assumes namespace is locked.
414*4882a593Smuzhiyun  *
415*4882a593Smuzhiyun  ******************************************************************************/
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun acpi_status
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info * gpe_xrupt_info,struct acpi_gpe_block_info * gpe_block,void * context)418*4882a593Smuzhiyun acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
419*4882a593Smuzhiyun 			     struct acpi_gpe_block_info *gpe_block,
420*4882a593Smuzhiyun 			     void *context)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun 	acpi_status status;
423*4882a593Smuzhiyun 	struct acpi_gpe_event_info *gpe_event_info;
424*4882a593Smuzhiyun 	u32 gpe_enabled_count;
425*4882a593Smuzhiyun 	u32 gpe_index;
426*4882a593Smuzhiyun 	u32 i;
427*4882a593Smuzhiyun 	u32 j;
428*4882a593Smuzhiyun 	u8 *is_polling_needed = context;
429*4882a593Smuzhiyun 	ACPI_ERROR_ONLY(u32 gpe_number);
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	/*
434*4882a593Smuzhiyun 	 * Ignore a null GPE block (e.g., if no GPE block 1 exists), and
435*4882a593Smuzhiyun 	 * any GPE blocks that have been initialized already.
436*4882a593Smuzhiyun 	 */
437*4882a593Smuzhiyun 	if (!gpe_block || gpe_block->initialized) {
438*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_OK);
439*4882a593Smuzhiyun 	}
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	/*
442*4882a593Smuzhiyun 	 * Enable all GPEs that have a corresponding method and have the
443*4882a593Smuzhiyun 	 * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
444*4882a593Smuzhiyun 	 * must be enabled via the acpi_enable_gpe() interface.
445*4882a593Smuzhiyun 	 */
446*4882a593Smuzhiyun 	gpe_enabled_count = 0;
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	for (i = 0; i < gpe_block->register_count; i++) {
449*4882a593Smuzhiyun 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 			/* Get the info block for this particular GPE */
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 			gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
454*4882a593Smuzhiyun 			gpe_event_info = &gpe_block->event_info[gpe_index];
455*4882a593Smuzhiyun 			ACPI_ERROR_ONLY(gpe_number =
456*4882a593Smuzhiyun 					gpe_block->block_base_number +
457*4882a593Smuzhiyun 					gpe_index);
458*4882a593Smuzhiyun 			gpe_event_info->flags |= ACPI_GPE_INITIALIZED;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 			/*
461*4882a593Smuzhiyun 			 * Ignore GPEs that have no corresponding _Lxx/_Exx method
462*4882a593Smuzhiyun 			 * and GPEs that are used for wakeup
463*4882a593Smuzhiyun 			 */
464*4882a593Smuzhiyun 			if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
465*4882a593Smuzhiyun 			     ACPI_GPE_DISPATCH_METHOD)
466*4882a593Smuzhiyun 			    || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
467*4882a593Smuzhiyun 				continue;
468*4882a593Smuzhiyun 			}
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 			status = acpi_ev_add_gpe_reference(gpe_event_info, FALSE);
471*4882a593Smuzhiyun 			if (ACPI_FAILURE(status)) {
472*4882a593Smuzhiyun 				ACPI_EXCEPTION((AE_INFO, status,
473*4882a593Smuzhiyun 					"Could not enable GPE 0x%02X",
474*4882a593Smuzhiyun 					gpe_number));
475*4882a593Smuzhiyun 				continue;
476*4882a593Smuzhiyun 			}
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 			gpe_event_info->flags |= ACPI_GPE_AUTO_ENABLED;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 			if (is_polling_needed &&
481*4882a593Smuzhiyun 			    ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
482*4882a593Smuzhiyun 				*is_polling_needed = TRUE;
483*4882a593Smuzhiyun 			}
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 			gpe_enabled_count++;
486*4882a593Smuzhiyun 		}
487*4882a593Smuzhiyun 	}
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	if (gpe_enabled_count) {
490*4882a593Smuzhiyun 		ACPI_INFO(("Enabled %u GPEs in block %02X to %02X",
491*4882a593Smuzhiyun 			   gpe_enabled_count, (u32)gpe_block->block_base_number,
492*4882a593Smuzhiyun 			   (u32)(gpe_block->block_base_number +
493*4882a593Smuzhiyun 				 (gpe_block->gpe_count - 1))));
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	gpe_block->initialized = TRUE;
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun #endif				/* !ACPI_REDUCED_HARDWARE */
502