dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / uts / intel / io / acpica / events / evgpeutil.c
blobff4b1cddc6edf35cb18ec722e3b8ea7eb68a4de8
1 /******************************************************************************
3 * Module Name: evgpeutil - GPE utilities
5 *****************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
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.
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.
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.
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acevents.h"
48 #define _COMPONENT ACPI_EVENTS
49 ACPI_MODULE_NAME ("evgpeutil")
52 #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
53 /*******************************************************************************
55 * FUNCTION: AcpiEvWalkGpeList
57 * PARAMETERS: GpeWalkCallback - Routine called for each GPE block
58 * Context - Value passed to callback
60 * RETURN: Status
62 * DESCRIPTION: Walk the GPE lists.
64 ******************************************************************************/
66 ACPI_STATUS
67 AcpiEvWalkGpeList (
68 ACPI_GPE_CALLBACK GpeWalkCallback,
69 void *Context)
71 ACPI_GPE_BLOCK_INFO *GpeBlock;
72 ACPI_GPE_XRUPT_INFO *GpeXruptInfo;
73 ACPI_STATUS Status = AE_OK;
74 ACPI_CPU_FLAGS Flags;
77 ACPI_FUNCTION_TRACE (EvWalkGpeList);
80 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
82 /* Walk the interrupt level descriptor list */
84 GpeXruptInfo = AcpiGbl_GpeXruptListHead;
85 while (GpeXruptInfo)
87 /* Walk all Gpe Blocks attached to this interrupt level */
89 GpeBlock = GpeXruptInfo->GpeBlockListHead;
90 while (GpeBlock)
92 /* One callback per GPE block */
94 Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context);
95 if (ACPI_FAILURE (Status))
97 if (Status == AE_CTRL_END) /* Callback abort */
99 Status = AE_OK;
101 goto UnlockAndExit;
104 GpeBlock = GpeBlock->Next;
107 GpeXruptInfo = GpeXruptInfo->Next;
110 UnlockAndExit:
111 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
112 return_ACPI_STATUS (Status);
116 /*******************************************************************************
118 * FUNCTION: AcpiEvGetGpeDevice
120 * PARAMETERS: GPE_WALK_CALLBACK
122 * RETURN: Status
124 * DESCRIPTION: Matches the input GPE index (0-CurrentGpeCount) with a GPE
125 * block device. NULL if the GPE is one of the FADT-defined GPEs.
127 ******************************************************************************/
129 ACPI_STATUS
130 AcpiEvGetGpeDevice (
131 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
132 ACPI_GPE_BLOCK_INFO *GpeBlock,
133 void *Context)
135 ACPI_GPE_DEVICE_INFO *Info = Context;
138 /* Increment Index by the number of GPEs in this block */
140 Info->NextBlockBaseIndex += GpeBlock->GpeCount;
142 if (Info->Index < Info->NextBlockBaseIndex)
145 * The GPE index is within this block, get the node. Leave the node
146 * NULL for the FADT-defined GPEs
148 if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE)
150 Info->GpeDevice = GpeBlock->Node;
153 Info->Status = AE_OK;
154 return (AE_CTRL_END);
157 return (AE_OK);
161 /*******************************************************************************
163 * FUNCTION: AcpiEvGetGpeXruptBlock
165 * PARAMETERS: InterruptNumber - Interrupt for a GPE block
166 * GpeXruptBlock - Where the block is returned
168 * RETURN: Status
170 * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
171 * block per unique interrupt level used for GPEs. Should be
172 * called only when the GPE lists are semaphore locked and not
173 * subject to change.
175 ******************************************************************************/
177 ACPI_STATUS
178 AcpiEvGetGpeXruptBlock (
179 UINT32 InterruptNumber,
180 ACPI_GPE_XRUPT_INFO **GpeXruptBlock)
182 ACPI_GPE_XRUPT_INFO *NextGpeXrupt;
183 ACPI_GPE_XRUPT_INFO *GpeXrupt;
184 ACPI_STATUS Status;
185 ACPI_CPU_FLAGS Flags;
188 ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
191 /* No need for lock since we are not changing any list elements here */
193 NextGpeXrupt = AcpiGbl_GpeXruptListHead;
194 while (NextGpeXrupt)
196 if (NextGpeXrupt->InterruptNumber == InterruptNumber)
198 *GpeXruptBlock = NextGpeXrupt;
199 return_ACPI_STATUS (AE_OK);
202 NextGpeXrupt = NextGpeXrupt->Next;
205 /* Not found, must allocate a new xrupt descriptor */
207 GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
208 if (!GpeXrupt)
210 return_ACPI_STATUS (AE_NO_MEMORY);
213 GpeXrupt->InterruptNumber = InterruptNumber;
215 /* Install new interrupt descriptor with spin lock */
217 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
218 if (AcpiGbl_GpeXruptListHead)
220 NextGpeXrupt = AcpiGbl_GpeXruptListHead;
221 while (NextGpeXrupt->Next)
223 NextGpeXrupt = NextGpeXrupt->Next;
226 NextGpeXrupt->Next = GpeXrupt;
227 GpeXrupt->Previous = NextGpeXrupt;
229 else
231 AcpiGbl_GpeXruptListHead = GpeXrupt;
234 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
236 /* Install new interrupt handler if not SCI_INT */
238 if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
240 Status = AcpiOsInstallInterruptHandler (InterruptNumber,
241 AcpiEvGpeXruptHandler, GpeXrupt);
242 if (ACPI_FAILURE (Status))
244 ACPI_EXCEPTION ((AE_INFO, Status,
245 "Could not install GPE interrupt handler at level 0x%X",
246 InterruptNumber));
247 return_ACPI_STATUS (Status);
251 *GpeXruptBlock = GpeXrupt;
252 return_ACPI_STATUS (AE_OK);
256 /*******************************************************************************
258 * FUNCTION: AcpiEvDeleteGpeXrupt
260 * PARAMETERS: GpeXrupt - A GPE interrupt info block
262 * RETURN: Status
264 * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
265 * interrupt handler if not the SCI interrupt.
267 ******************************************************************************/
269 ACPI_STATUS
270 AcpiEvDeleteGpeXrupt (
271 ACPI_GPE_XRUPT_INFO *GpeXrupt)
273 ACPI_STATUS Status;
274 ACPI_CPU_FLAGS Flags;
277 ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt);
280 /* We never want to remove the SCI interrupt handler */
282 if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt)
284 GpeXrupt->GpeBlockListHead = NULL;
285 return_ACPI_STATUS (AE_OK);
288 /* Disable this interrupt */
290 Status = AcpiOsRemoveInterruptHandler (
291 GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler);
292 if (ACPI_FAILURE (Status))
294 return_ACPI_STATUS (Status);
297 /* Unlink the interrupt block with lock */
299 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
300 if (GpeXrupt->Previous)
302 GpeXrupt->Previous->Next = GpeXrupt->Next;
304 else
306 /* No previous, update list head */
308 AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
311 if (GpeXrupt->Next)
313 GpeXrupt->Next->Previous = GpeXrupt->Previous;
315 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
317 /* Free the block */
319 ACPI_FREE (GpeXrupt);
320 return_ACPI_STATUS (AE_OK);
324 /*******************************************************************************
326 * FUNCTION: AcpiEvDeleteGpeHandlers
328 * PARAMETERS: GpeXruptInfo - GPE Interrupt info
329 * GpeBlock - Gpe Block info
331 * RETURN: Status
333 * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
334 * Used only prior to termination.
336 ******************************************************************************/
338 ACPI_STATUS
339 AcpiEvDeleteGpeHandlers (
340 ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
341 ACPI_GPE_BLOCK_INFO *GpeBlock,
342 void *Context)
344 ACPI_GPE_EVENT_INFO *GpeEventInfo;
345 ACPI_GPE_NOTIFY_INFO *Notify;
346 ACPI_GPE_NOTIFY_INFO *Next;
347 UINT32 i;
348 UINT32 j;
351 ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
354 /* Examine each GPE Register within the block */
356 for (i = 0; i < GpeBlock->RegisterCount; i++)
358 /* Now look at the individual GPEs in this byte register */
360 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
362 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
363 ACPI_GPE_REGISTER_WIDTH) + j];
365 if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
366 ACPI_GPE_DISPATCH_HANDLER) ||
367 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
368 ACPI_GPE_DISPATCH_RAW_HANDLER))
370 /* Delete an installed handler block */
372 ACPI_FREE (GpeEventInfo->Dispatch.Handler);
373 GpeEventInfo->Dispatch.Handler = NULL;
374 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
376 else if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
377 ACPI_GPE_DISPATCH_NOTIFY)
379 /* Delete the implicit notification device list */
381 Notify = GpeEventInfo->Dispatch.NotifyList;
382 while (Notify)
384 Next = Notify->Next;
385 ACPI_FREE (Notify);
386 Notify = Next;
389 GpeEventInfo->Dispatch.NotifyList = NULL;
390 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
395 return_ACPI_STATUS (AE_OK);
398 #endif /* !ACPI_REDUCED_HARDWARE */