1 /******************************************************************************
2 *
3 * Module Name: evgpeutil - GPE utilities
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2011, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45 #include "acpi.h"
46 #include "accommon.h"
47 #include "acevents.h"
48
49 #define _COMPONENT ACPI_EVENTS
50 ACPI_MODULE_NAME ("evgpeutil")
51
52
53 /*******************************************************************************
54 *
55 * FUNCTION: AcpiEvWalkGpeList
56 *
57 * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
58 * Context - Value passed to callback
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Walk the GPE lists.
63 *
64 ******************************************************************************/
65
66 ACPI_STATUS
67 AcpiEvWalkGpeList (
68 ACPI_GPE_CALLBACK GpeWalkCallback,
69 void *Context)
70 {
71 ACPI_GPE_BLOCK_INFO *GpeBlock;
72 ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
200 * NULL for the FADT-defined GPEs
201 */
202 if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE)
203 {
204 Info->GpeDevice = GpeBlock->Node;
205 }
206
207 Info->Status = AE_OK;
208 return (AE_CTRL_END);
209 }
210
211 return (AE_OK);
212 }
213
214
215 /*******************************************************************************
216 *
217 * FUNCTION: AcpiEvGetGpeXruptBlock
218 *
219 * PARAMETERS: InterruptNumber - Interrupt for a GPE block
220 *
221 * RETURN: A GPE interrupt block
222 *
223 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
224 * block per unique interrupt level used for GPEs. Should be
225 * called only when the GPE lists are semaphore locked and not
226 * subject to change.
227 *
228 ******************************************************************************/
229
230 ACPI_GPE_XRUPT_INFO *
231 AcpiEvGetGpeXruptBlock (
232 UINT32 InterruptNumber)
233 {
234 ACPI_GPE_XRUPT_INFO *NextGpeXrupt;
235 ACPI_GPE_XRUPT_INFO *GpeXrupt;
236 ACPI_STATUS Status;
237 ACPI_CPU_FLAGS Flags;
238
239
240 ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
241
242
243 /* No need for lock since we are not changing any list elements here */
244
245 NextGpeXrupt = AcpiGbl_GpeXruptListHead;
246 while (NextGpeXrupt)
247 {
248 if (NextGpeXrupt->InterruptNumber == InterruptNumber)
249 {
250 return_PTR (NextGpeXrupt);
251 }
252
253 NextGpeXrupt = NextGpeXrupt->Next;
254 }
255
256 /* Not found, must allocate a new xrupt descriptor */
257
258 GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
259 if (!GpeXrupt)
260 {
261 return_PTR (NULL);
262 }
263
264 GpeXrupt->InterruptNumber = InterruptNumber;
265
266 /* Install new interrupt descriptor with spin lock */
267
268 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
269 if (AcpiGbl_GpeXruptListHead)
270 {
271 NextGpeXrupt = AcpiGbl_GpeXruptListHead;
272 while (NextGpeXrupt->Next)
273 {
274 NextGpeXrupt = NextGpeXrupt->Next;
275 }
276
277 NextGpeXrupt->Next = GpeXrupt;
278 GpeXrupt->Previous = NextGpeXrupt;
279 }
280 else
281 {
282 AcpiGbl_GpeXruptListHead = GpeXrupt;
283 }
284 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
285
286 /* Install new interrupt handler if not SCI_INT */
287
288 if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
289 {
290 Status = AcpiOsInstallInterruptHandler (InterruptNumber,
291 AcpiEvGpeXruptHandler, GpeXrupt);
292 if (ACPI_FAILURE (Status))
293 {
294 ACPI_ERROR ((AE_INFO,
295 "Could not install GPE interrupt handler at level 0x%X",
296 InterruptNumber));
297 return_PTR (NULL);
298 }
299 }
300
301 return_PTR (GpeXrupt);
302 }
303
304
305 /*******************************************************************************
306 *
307 * FUNCTION: AcpiEvDeleteGpeXrupt
308 *
309 * PARAMETERS: GpeXrupt - A GPE interrupt info block
310 *
311 * RETURN: Status
312 *
313 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
314 * interrupt handler if not the SCI interrupt.
315 *
316 ******************************************************************************/
317
318 ACPI_STATUS
319 AcpiEvDeleteGpeXrupt (
320 ACPI_GPE_XRUPT_INFO *GpeXrupt)
321 {
374 *
375 * FUNCTION: AcpiEvDeleteGpeHandlers
376 *
377 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
378 * GpeBlock - Gpe Block info
379 *
380 * RETURN: Status
381 *
382 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
383 * Used only prior to termination.
384 *
385 ******************************************************************************/
386
387 ACPI_STATUS
388 AcpiEvDeleteGpeHandlers (
389 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
390 ACPI_GPE_BLOCK_INFO *GpeBlock,
391 void *Context)
392 {
393 ACPI_GPE_EVENT_INFO *GpeEventInfo;
394 UINT32 i;
395 UINT32 j;
396
397
398 ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
399
400
401 /* Examine each GPE Register within the block */
402
403 for (i = 0; i < GpeBlock->RegisterCount; i++)
404 {
405 /* Now look at the individual GPEs in this byte register */
406
407 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
408 {
409 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
410 ACPI_GPE_REGISTER_WIDTH) + j];
411
412 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
413 ACPI_GPE_DISPATCH_HANDLER)
414 {
415 ACPI_FREE (GpeEventInfo->Dispatch.Handler);
416 GpeEventInfo->Dispatch.Handler = NULL;
417 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
418 }
419 }
420 }
421
422 return_ACPI_STATUS (AE_OK);
423 }
424
|
1 /******************************************************************************
2 *
3 * Module Name: evgpeutil - GPE utilities
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acevents.h"
47
48 #define _COMPONENT ACPI_EVENTS
49 ACPI_MODULE_NAME ("evgpeutil")
50
51
52 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
53 /*******************************************************************************
54 *
55 * FUNCTION: AcpiEvWalkGpeList
56 *
57 * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
58 * Context - Value passed to callback
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Walk the GPE lists.
63 *
64 ******************************************************************************/
65
66 ACPI_STATUS
67 AcpiEvWalkGpeList (
68 ACPI_GPE_CALLBACK GpeWalkCallback,
69 void *Context)
70 {
71 ACPI_GPE_BLOCK_INFO *GpeBlock;
72 ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
200 * NULL for the FADT-defined GPEs
201 */
202 if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE)
203 {
204 Info->GpeDevice = GpeBlock->Node;
205 }
206
207 Info->Status = AE_OK;
208 return (AE_CTRL_END);
209 }
210
211 return (AE_OK);
212 }
213
214
215 /*******************************************************************************
216 *
217 * FUNCTION: AcpiEvGetGpeXruptBlock
218 *
219 * PARAMETERS: InterruptNumber - Interrupt for a GPE block
220 * GpeXruptBlock - Where the block is returned
221 *
222 * RETURN: Status
223 *
224 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
225 * block per unique interrupt level used for GPEs. Should be
226 * called only when the GPE lists are semaphore locked and not
227 * subject to change.
228 *
229 ******************************************************************************/
230
231 ACPI_STATUS
232 AcpiEvGetGpeXruptBlock (
233 UINT32 InterruptNumber,
234 ACPI_GPE_XRUPT_INFO **GpeXruptBlock)
235 {
236 ACPI_GPE_XRUPT_INFO *NextGpeXrupt;
237 ACPI_GPE_XRUPT_INFO *GpeXrupt;
238 ACPI_STATUS Status;
239 ACPI_CPU_FLAGS Flags;
240
241
242 ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
243
244
245 /* No need for lock since we are not changing any list elements here */
246
247 NextGpeXrupt = AcpiGbl_GpeXruptListHead;
248 while (NextGpeXrupt)
249 {
250 if (NextGpeXrupt->InterruptNumber == InterruptNumber)
251 {
252 *GpeXruptBlock = NextGpeXrupt;
253 return_ACPI_STATUS (AE_OK);
254 }
255
256 NextGpeXrupt = NextGpeXrupt->Next;
257 }
258
259 /* Not found, must allocate a new xrupt descriptor */
260
261 GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
262 if (!GpeXrupt)
263 {
264 return_ACPI_STATUS (AE_NO_MEMORY);
265 }
266
267 GpeXrupt->InterruptNumber = InterruptNumber;
268
269 /* Install new interrupt descriptor with spin lock */
270
271 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
272 if (AcpiGbl_GpeXruptListHead)
273 {
274 NextGpeXrupt = AcpiGbl_GpeXruptListHead;
275 while (NextGpeXrupt->Next)
276 {
277 NextGpeXrupt = NextGpeXrupt->Next;
278 }
279
280 NextGpeXrupt->Next = GpeXrupt;
281 GpeXrupt->Previous = NextGpeXrupt;
282 }
283 else
284 {
285 AcpiGbl_GpeXruptListHead = GpeXrupt;
286 }
287
288 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
289
290 /* Install new interrupt handler if not SCI_INT */
291
292 if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
293 {
294 Status = AcpiOsInstallInterruptHandler (InterruptNumber,
295 AcpiEvGpeXruptHandler, GpeXrupt);
296 if (ACPI_FAILURE (Status))
297 {
298 ACPI_EXCEPTION ((AE_INFO, Status,
299 "Could not install GPE interrupt handler at level 0x%X",
300 InterruptNumber));
301 return_ACPI_STATUS (Status);
302 }
303 }
304
305 *GpeXruptBlock = GpeXrupt;
306 return_ACPI_STATUS (AE_OK);
307 }
308
309
310 /*******************************************************************************
311 *
312 * FUNCTION: AcpiEvDeleteGpeXrupt
313 *
314 * PARAMETERS: GpeXrupt - A GPE interrupt info block
315 *
316 * RETURN: Status
317 *
318 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
319 * interrupt handler if not the SCI interrupt.
320 *
321 ******************************************************************************/
322
323 ACPI_STATUS
324 AcpiEvDeleteGpeXrupt (
325 ACPI_GPE_XRUPT_INFO *GpeXrupt)
326 {
379 *
380 * FUNCTION: AcpiEvDeleteGpeHandlers
381 *
382 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
383 * GpeBlock - Gpe Block info
384 *
385 * RETURN: Status
386 *
387 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
388 * Used only prior to termination.
389 *
390 ******************************************************************************/
391
392 ACPI_STATUS
393 AcpiEvDeleteGpeHandlers (
394 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
395 ACPI_GPE_BLOCK_INFO *GpeBlock,
396 void *Context)
397 {
398 ACPI_GPE_EVENT_INFO *GpeEventInfo;
399 ACPI_GPE_NOTIFY_INFO *Notify;
400 ACPI_GPE_NOTIFY_INFO *Next;
401 UINT32 i;
402 UINT32 j;
403
404
405 ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
406
407
408 /* Examine each GPE Register within the block */
409
410 for (i = 0; i < GpeBlock->RegisterCount; i++)
411 {
412 /* Now look at the individual GPEs in this byte register */
413
414 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
415 {
416 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
417 ACPI_GPE_REGISTER_WIDTH) + j];
418
419 if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
420 ACPI_GPE_DISPATCH_HANDLER)
421 {
422 /* Delete an installed handler block */
423
424 ACPI_FREE (GpeEventInfo->Dispatch.Handler);
425 GpeEventInfo->Dispatch.Handler = NULL;
426 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
427 }
428 else if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
429 ACPI_GPE_DISPATCH_NOTIFY)
430 {
431 /* Delete the implicit notification device list */
432
433 Notify = GpeEventInfo->Dispatch.NotifyList;
434 while (Notify)
435 {
436 Next = Notify->Next;
437 ACPI_FREE (Notify);
438 Notify = Next;
439 }
440 GpeEventInfo->Dispatch.NotifyList = NULL;
441 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
442 }
443 }
444 }
445
446 return_ACPI_STATUS (AE_OK);
447 }
448
449 #endif /* !ACPI_REDUCED_HARDWARE */
|