PageRenderTime 60ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/sys/contrib/dev/acpica/components/events/evgpe.c

https://bitbucket.org/freebsd/freebsd-head/
C | 852 lines | 394 code | 159 blank | 299 comment | 48 complexity | 8f3a7775467f4dff11b8a905d3ce30ed MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.0, LGPL-2.1, BSD-2-Clause, 0BSD, JSON, AGPL-1.0, GPL-2.0
  1. /******************************************************************************
  2. *
  3. * Module Name: evgpe - General Purpose Event handling and dispatch
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2012, Intel Corp.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include <contrib/dev/acpica/include/acpi.h>
  43. #include <contrib/dev/acpica/include/accommon.h>
  44. #include <contrib/dev/acpica/include/acevents.h>
  45. #include <contrib/dev/acpica/include/acnamesp.h>
  46. #define _COMPONENT ACPI_EVENTS
  47. ACPI_MODULE_NAME ("evgpe")
  48. #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
  49. /* Local prototypes */
  50. static void ACPI_SYSTEM_XFACE
  51. AcpiEvAsynchExecuteGpeMethod (
  52. void *Context);
  53. static void ACPI_SYSTEM_XFACE
  54. AcpiEvAsynchEnableGpe (
  55. void *Context);
  56. /*******************************************************************************
  57. *
  58. * FUNCTION: AcpiEvUpdateGpeEnableMask
  59. *
  60. * PARAMETERS: GpeEventInfo - GPE to update
  61. *
  62. * RETURN: Status
  63. *
  64. * DESCRIPTION: Updates GPE register enable mask based upon whether there are
  65. * runtime references to this GPE
  66. *
  67. ******************************************************************************/
  68. ACPI_STATUS
  69. AcpiEvUpdateGpeEnableMask (
  70. ACPI_GPE_EVENT_INFO *GpeEventInfo)
  71. {
  72. ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
  73. UINT32 RegisterBit;
  74. ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
  75. GpeRegisterInfo = GpeEventInfo->RegisterInfo;
  76. if (!GpeRegisterInfo)
  77. {
  78. return_ACPI_STATUS (AE_NOT_EXIST);
  79. }
  80. RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
  81. /* Clear the run bit up front */
  82. ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
  83. /* Set the mask bit only if there are references to this GPE */
  84. if (GpeEventInfo->RuntimeCount)
  85. {
  86. ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
  87. }
  88. return_ACPI_STATUS (AE_OK);
  89. }
  90. /*******************************************************************************
  91. *
  92. * FUNCTION: AcpiEvEnableGpe
  93. *
  94. * PARAMETERS: GpeEventInfo - GPE to enable
  95. *
  96. * RETURN: Status
  97. *
  98. * DESCRIPTION: Clear a GPE of stale events and enable it.
  99. *
  100. ******************************************************************************/
  101. ACPI_STATUS
  102. AcpiEvEnableGpe (
  103. ACPI_GPE_EVENT_INFO *GpeEventInfo)
  104. {
  105. ACPI_STATUS Status;
  106. ACPI_FUNCTION_TRACE (EvEnableGpe);
  107. /*
  108. * We will only allow a GPE to be enabled if it has either an associated
  109. * method (_Lxx/_Exx) or a handler, or is using the implicit notify
  110. * feature. Otherwise, the GPE will be immediately disabled by
  111. * AcpiEvGpeDispatch the first time it fires.
  112. */
  113. if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
  114. ACPI_GPE_DISPATCH_NONE)
  115. {
  116. return_ACPI_STATUS (AE_NO_HANDLER);
  117. }
  118. /* Clear the GPE (of stale events) */
  119. Status = AcpiHwClearGpe (GpeEventInfo);
  120. if (ACPI_FAILURE (Status))
  121. {
  122. return_ACPI_STATUS (Status);
  123. }
  124. /* Enable the requested GPE */
  125. Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
  126. return_ACPI_STATUS (Status);
  127. }
  128. /*******************************************************************************
  129. *
  130. * FUNCTION: AcpiEvAddGpeReference
  131. *
  132. * PARAMETERS: GpeEventInfo - Add a reference to this GPE
  133. *
  134. * RETURN: Status
  135. *
  136. * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
  137. * hardware-enabled.
  138. *
  139. ******************************************************************************/
  140. ACPI_STATUS
  141. AcpiEvAddGpeReference (
  142. ACPI_GPE_EVENT_INFO *GpeEventInfo)
  143. {
  144. ACPI_STATUS Status = AE_OK;
  145. ACPI_FUNCTION_TRACE (EvAddGpeReference);
  146. if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
  147. {
  148. return_ACPI_STATUS (AE_LIMIT);
  149. }
  150. GpeEventInfo->RuntimeCount++;
  151. if (GpeEventInfo->RuntimeCount == 1)
  152. {
  153. /* Enable on first reference */
  154. Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
  155. if (ACPI_SUCCESS (Status))
  156. {
  157. Status = AcpiEvEnableGpe (GpeEventInfo);
  158. }
  159. if (ACPI_FAILURE (Status))
  160. {
  161. GpeEventInfo->RuntimeCount--;
  162. }
  163. }
  164. return_ACPI_STATUS (Status);
  165. }
  166. /*******************************************************************************
  167. *
  168. * FUNCTION: AcpiEvRemoveGpeReference
  169. *
  170. * PARAMETERS: GpeEventInfo - Remove a reference to this GPE
  171. *
  172. * RETURN: Status
  173. *
  174. * DESCRIPTION: Remove a reference to a GPE. When the last reference is
  175. * removed, the GPE is hardware-disabled.
  176. *
  177. ******************************************************************************/
  178. ACPI_STATUS
  179. AcpiEvRemoveGpeReference (
  180. ACPI_GPE_EVENT_INFO *GpeEventInfo)
  181. {
  182. ACPI_STATUS Status = AE_OK;
  183. ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
  184. if (!GpeEventInfo->RuntimeCount)
  185. {
  186. return_ACPI_STATUS (AE_LIMIT);
  187. }
  188. GpeEventInfo->RuntimeCount--;
  189. if (!GpeEventInfo->RuntimeCount)
  190. {
  191. /* Disable on last reference */
  192. Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
  193. if (ACPI_SUCCESS (Status))
  194. {
  195. Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
  196. }
  197. if (ACPI_FAILURE (Status))
  198. {
  199. GpeEventInfo->RuntimeCount++;
  200. }
  201. }
  202. return_ACPI_STATUS (Status);
  203. }
  204. /*******************************************************************************
  205. *
  206. * FUNCTION: AcpiEvLowGetGpeInfo
  207. *
  208. * PARAMETERS: GpeNumber - Raw GPE number
  209. * GpeBlock - A GPE info block
  210. *
  211. * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
  212. * is not within the specified GPE block)
  213. *
  214. * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
  215. * the low-level implementation of EvGetGpeEventInfo.
  216. *
  217. ******************************************************************************/
  218. ACPI_GPE_EVENT_INFO *
  219. AcpiEvLowGetGpeInfo (
  220. UINT32 GpeNumber,
  221. ACPI_GPE_BLOCK_INFO *GpeBlock)
  222. {
  223. UINT32 GpeIndex;
  224. /*
  225. * Validate that the GpeNumber is within the specified GpeBlock.
  226. * (Two steps)
  227. */
  228. if (!GpeBlock ||
  229. (GpeNumber < GpeBlock->BlockBaseNumber))
  230. {
  231. return (NULL);
  232. }
  233. GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
  234. if (GpeIndex >= GpeBlock->GpeCount)
  235. {
  236. return (NULL);
  237. }
  238. return (&GpeBlock->EventInfo[GpeIndex]);
  239. }
  240. /*******************************************************************************
  241. *
  242. * FUNCTION: AcpiEvGetGpeEventInfo
  243. *
  244. * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
  245. * GpeNumber - Raw GPE number
  246. *
  247. * RETURN: A GPE EventInfo struct. NULL if not a valid GPE
  248. *
  249. * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
  250. * Validates the GpeBlock and the GpeNumber
  251. *
  252. * Should be called only when the GPE lists are semaphore locked
  253. * and not subject to change.
  254. *
  255. ******************************************************************************/
  256. ACPI_GPE_EVENT_INFO *
  257. AcpiEvGetGpeEventInfo (
  258. ACPI_HANDLE GpeDevice,
  259. UINT32 GpeNumber)
  260. {
  261. ACPI_OPERAND_OBJECT *ObjDesc;
  262. ACPI_GPE_EVENT_INFO *GpeInfo;
  263. UINT32 i;
  264. ACPI_FUNCTION_ENTRY ();
  265. /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
  266. if (!GpeDevice)
  267. {
  268. /* Examine GPE Block 0 and 1 (These blocks are permanent) */
  269. for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
  270. {
  271. GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
  272. AcpiGbl_GpeFadtBlocks[i]);
  273. if (GpeInfo)
  274. {
  275. return (GpeInfo);
  276. }
  277. }
  278. /* The GpeNumber was not in the range of either FADT GPE block */
  279. return (NULL);
  280. }
  281. /* A Non-NULL GpeDevice means this is a GPE Block Device */
  282. ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
  283. if (!ObjDesc ||
  284. !ObjDesc->Device.GpeBlock)
  285. {
  286. return (NULL);
  287. }
  288. return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
  289. }
  290. /*******************************************************************************
  291. *
  292. * FUNCTION: AcpiEvGpeDetect
  293. *
  294. * PARAMETERS: GpeXruptList - Interrupt block for this interrupt.
  295. * Can have multiple GPE blocks attached.
  296. *
  297. * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  298. *
  299. * DESCRIPTION: Detect if any GP events have occurred. This function is
  300. * executed at interrupt level.
  301. *
  302. ******************************************************************************/
  303. UINT32
  304. AcpiEvGpeDetect (
  305. ACPI_GPE_XRUPT_INFO *GpeXruptList)
  306. {
  307. ACPI_STATUS Status;
  308. ACPI_GPE_BLOCK_INFO *GpeBlock;
  309. ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
  310. UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
  311. UINT8 EnabledStatusByte;
  312. UINT32 StatusReg;
  313. UINT32 EnableReg;
  314. ACPI_CPU_FLAGS Flags;
  315. UINT32 i;
  316. UINT32 j;
  317. ACPI_FUNCTION_NAME (EvGpeDetect);
  318. /* Check for the case where there are no GPEs */
  319. if (!GpeXruptList)
  320. {
  321. return (IntStatus);
  322. }
  323. /*
  324. * We need to obtain the GPE lock for both the data structs and registers
  325. * Note: Not necessary to obtain the hardware lock, since the GPE
  326. * registers are owned by the GpeLock.
  327. */
  328. Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
  329. /* Examine all GPE blocks attached to this interrupt level */
  330. GpeBlock = GpeXruptList->GpeBlockListHead;
  331. while (GpeBlock)
  332. {
  333. /*
  334. * Read all of the 8-bit GPE status and enable registers in this GPE
  335. * block, saving all of them. Find all currently active GP events.
  336. */
  337. for (i = 0; i < GpeBlock->RegisterCount; i++)
  338. {
  339. /* Get the next status/enable pair */
  340. GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
  341. /*
  342. * Optimization: If there are no GPEs enabled within this
  343. * register, we can safely ignore the entire register.
  344. */
  345. if (!(GpeRegisterInfo->EnableForRun |
  346. GpeRegisterInfo->EnableForWake))
  347. {
  348. ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
  349. "Ignore disabled registers for GPE%02X-GPE%02X: "
  350. "RunEnable=%02X, WakeEnable=%02X\n",
  351. GpeRegisterInfo->BaseGpeNumber,
  352. GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
  353. GpeRegisterInfo->EnableForRun,
  354. GpeRegisterInfo->EnableForWake));
  355. continue;
  356. }
  357. /* Read the Status Register */
  358. Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
  359. if (ACPI_FAILURE (Status))
  360. {
  361. goto UnlockAndExit;
  362. }
  363. /* Read the Enable Register */
  364. Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
  365. if (ACPI_FAILURE (Status))
  366. {
  367. goto UnlockAndExit;
  368. }
  369. ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
  370. "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, "
  371. "RunEnable=%02X, WakeEnable=%02X\n",
  372. GpeRegisterInfo->BaseGpeNumber,
  373. GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
  374. StatusReg, EnableReg,
  375. GpeRegisterInfo->EnableForRun,
  376. GpeRegisterInfo->EnableForWake));
  377. /* Check if there is anything active at all in this register */
  378. EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
  379. if (!EnabledStatusByte)
  380. {
  381. /* No active GPEs in this register, move on */
  382. continue;
  383. }
  384. /* Now look at the individual GPEs in this byte register */
  385. for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
  386. {
  387. /* Examine one GPE bit */
  388. if (EnabledStatusByte & (1 << j))
  389. {
  390. /*
  391. * Found an active GPE. Dispatch the event to a handler
  392. * or method.
  393. */
  394. IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node,
  395. &GpeBlock->EventInfo[((ACPI_SIZE) i *
  396. ACPI_GPE_REGISTER_WIDTH) + j],
  397. j + GpeRegisterInfo->BaseGpeNumber);
  398. }
  399. }
  400. }
  401. GpeBlock = GpeBlock->Next;
  402. }
  403. UnlockAndExit:
  404. AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
  405. return (IntStatus);
  406. }
  407. /*******************************************************************************
  408. *
  409. * FUNCTION: AcpiEvAsynchExecuteGpeMethod
  410. *
  411. * PARAMETERS: Context (GpeEventInfo) - Info for this GPE
  412. *
  413. * RETURN: None
  414. *
  415. * DESCRIPTION: Perform the actual execution of a GPE control method. This
  416. * function is called from an invocation of AcpiOsExecute and
  417. * therefore does NOT execute at interrupt level - so that
  418. * the control method itself is not executed in the context of
  419. * an interrupt handler.
  420. *
  421. ******************************************************************************/
  422. static void ACPI_SYSTEM_XFACE
  423. AcpiEvAsynchExecuteGpeMethod (
  424. void *Context)
  425. {
  426. ACPI_GPE_EVENT_INFO *GpeEventInfo = Context;
  427. ACPI_STATUS Status;
  428. ACPI_GPE_EVENT_INFO *LocalGpeEventInfo;
  429. ACPI_EVALUATE_INFO *Info;
  430. ACPI_GPE_NOTIFY_INFO *Notify;
  431. ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
  432. /* Allocate a local GPE block */
  433. LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
  434. if (!LocalGpeEventInfo)
  435. {
  436. ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
  437. "while handling a GPE"));
  438. return_VOID;
  439. }
  440. Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
  441. if (ACPI_FAILURE (Status))
  442. {
  443. return_VOID;
  444. }
  445. /* Must revalidate the GpeNumber/GpeBlock */
  446. if (!AcpiEvValidGpeEvent (GpeEventInfo))
  447. {
  448. Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
  449. return_VOID;
  450. }
  451. /*
  452. * Take a snapshot of the GPE info for this level - we copy the info to
  453. * prevent a race condition with RemoveHandler/RemoveBlock.
  454. */
  455. ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
  456. sizeof (ACPI_GPE_EVENT_INFO));
  457. Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
  458. if (ACPI_FAILURE (Status))
  459. {
  460. return_VOID;
  461. }
  462. /* Do the correct dispatch - normal method or implicit notify */
  463. switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
  464. {
  465. case ACPI_GPE_DISPATCH_NOTIFY:
  466. /*
  467. * Implicit notify.
  468. * Dispatch a DEVICE_WAKE notify to the appropriate handler.
  469. * NOTE: the request is queued for execution after this method
  470. * completes. The notify handlers are NOT invoked synchronously
  471. * from this thread -- because handlers may in turn run other
  472. * control methods.
  473. *
  474. * June 2012: Expand implicit notify mechanism to support
  475. * notifies on multiple device objects.
  476. */
  477. Notify = LocalGpeEventInfo->Dispatch.NotifyList;
  478. while (ACPI_SUCCESS (Status) && Notify)
  479. {
  480. Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode,
  481. ACPI_NOTIFY_DEVICE_WAKE);
  482. Notify = Notify->Next;
  483. }
  484. break;
  485. case ACPI_GPE_DISPATCH_METHOD:
  486. /* Allocate the evaluation information block */
  487. Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
  488. if (!Info)
  489. {
  490. Status = AE_NO_MEMORY;
  491. }
  492. else
  493. {
  494. /*
  495. * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
  496. * _Lxx/_Exx control method that corresponds to this GPE
  497. */
  498. Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
  499. Info->Flags = ACPI_IGNORE_RETURN_VALUE;
  500. Status = AcpiNsEvaluate (Info);
  501. ACPI_FREE (Info);
  502. }
  503. if (ACPI_FAILURE (Status))
  504. {
  505. ACPI_EXCEPTION ((AE_INFO, Status,
  506. "while evaluating GPE method [%4.4s]",
  507. AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
  508. }
  509. break;
  510. default:
  511. return_VOID; /* Should never happen */
  512. }
  513. /* Defer enabling of GPE until all notify handlers are done */
  514. Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
  515. AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
  516. if (ACPI_FAILURE (Status))
  517. {
  518. ACPI_FREE (LocalGpeEventInfo);
  519. }
  520. return_VOID;
  521. }
  522. /*******************************************************************************
  523. *
  524. * FUNCTION: AcpiEvAsynchEnableGpe
  525. *
  526. * PARAMETERS: Context (GpeEventInfo) - Info for this GPE
  527. * Callback from AcpiOsExecute
  528. *
  529. * RETURN: None
  530. *
  531. * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
  532. * complete (i.e., finish execution of Notify)
  533. *
  534. ******************************************************************************/
  535. static void ACPI_SYSTEM_XFACE
  536. AcpiEvAsynchEnableGpe (
  537. void *Context)
  538. {
  539. ACPI_GPE_EVENT_INFO *GpeEventInfo = Context;
  540. (void) AcpiEvFinishGpe (GpeEventInfo);
  541. ACPI_FREE (GpeEventInfo);
  542. return;
  543. }
  544. /*******************************************************************************
  545. *
  546. * FUNCTION: AcpiEvFinishGpe
  547. *
  548. * PARAMETERS: GpeEventInfo - Info for this GPE
  549. *
  550. * RETURN: Status
  551. *
  552. * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
  553. * of a GPE method or a synchronous or asynchronous GPE handler.
  554. *
  555. ******************************************************************************/
  556. ACPI_STATUS
  557. AcpiEvFinishGpe (
  558. ACPI_GPE_EVENT_INFO *GpeEventInfo)
  559. {
  560. ACPI_STATUS Status;
  561. if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
  562. ACPI_GPE_LEVEL_TRIGGERED)
  563. {
  564. /*
  565. * GPE is level-triggered, we clear the GPE status bit after
  566. * handling the event.
  567. */
  568. Status = AcpiHwClearGpe (GpeEventInfo);
  569. if (ACPI_FAILURE (Status))
  570. {
  571. return (Status);
  572. }
  573. }
  574. /*
  575. * Enable this GPE, conditionally. This means that the GPE will
  576. * only be physically enabled if the EnableForRun bit is set
  577. * in the EventInfo.
  578. */
  579. (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
  580. return (AE_OK);
  581. }
  582. /*******************************************************************************
  583. *
  584. * FUNCTION: AcpiEvGpeDispatch
  585. *
  586. * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
  587. * GpeEventInfo - Info for this GPE
  588. * GpeNumber - Number relative to the parent GPE block
  589. *
  590. * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  591. *
  592. * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
  593. * or method (e.g. _Lxx/_Exx) handler.
  594. *
  595. * This function executes at interrupt level.
  596. *
  597. ******************************************************************************/
  598. UINT32
  599. AcpiEvGpeDispatch (
  600. ACPI_NAMESPACE_NODE *GpeDevice,
  601. ACPI_GPE_EVENT_INFO *GpeEventInfo,
  602. UINT32 GpeNumber)
  603. {
  604. ACPI_STATUS Status;
  605. UINT32 ReturnValue;
  606. ACPI_FUNCTION_TRACE (EvGpeDispatch);
  607. /* Invoke global event handler if present */
  608. AcpiGpeCount++;
  609. if (AcpiGbl_GlobalEventHandler)
  610. {
  611. AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice,
  612. GpeNumber, AcpiGbl_GlobalEventHandlerContext);
  613. }
  614. /*
  615. * If edge-triggered, clear the GPE status bit now. Note that
  616. * level-triggered events are cleared after the GPE is serviced.
  617. */
  618. if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
  619. ACPI_GPE_EDGE_TRIGGERED)
  620. {
  621. Status = AcpiHwClearGpe (GpeEventInfo);
  622. if (ACPI_FAILURE (Status))
  623. {
  624. ACPI_EXCEPTION ((AE_INFO, Status,
  625. "Unable to clear GPE%02X", GpeNumber));
  626. return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
  627. }
  628. }
  629. /*
  630. * Always disable the GPE so that it does not keep firing before
  631. * any asynchronous activity completes (either from the execution
  632. * of a GPE method or an asynchronous GPE handler.)
  633. *
  634. * If there is no handler or method to run, just disable the
  635. * GPE and leave it disabled permanently to prevent further such
  636. * pointless events from firing.
  637. */
  638. Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
  639. if (ACPI_FAILURE (Status))
  640. {
  641. ACPI_EXCEPTION ((AE_INFO, Status,
  642. "Unable to disable GPE%02X", GpeNumber));
  643. return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
  644. }
  645. /*
  646. * Dispatch the GPE to either an installed handler or the control
  647. * method associated with this GPE (_Lxx or _Exx). If a handler
  648. * exists, we invoke it and do not attempt to run the method.
  649. * If there is neither a handler nor a method, leave the GPE
  650. * disabled.
  651. */
  652. switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
  653. {
  654. case ACPI_GPE_DISPATCH_HANDLER:
  655. /* Invoke the installed handler (at interrupt level) */
  656. ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
  657. GpeDevice, GpeNumber,
  658. GpeEventInfo->Dispatch.Handler->Context);
  659. /* If requested, clear (if level-triggered) and reenable the GPE */
  660. if (ReturnValue & ACPI_REENABLE_GPE)
  661. {
  662. (void) AcpiEvFinishGpe (GpeEventInfo);
  663. }
  664. break;
  665. case ACPI_GPE_DISPATCH_METHOD:
  666. case ACPI_GPE_DISPATCH_NOTIFY:
  667. /*
  668. * Execute the method associated with the GPE
  669. * NOTE: Level-triggered GPEs are cleared after the method completes.
  670. */
  671. Status = AcpiOsExecute (OSL_GPE_HANDLER,
  672. AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
  673. if (ACPI_FAILURE (Status))
  674. {
  675. ACPI_EXCEPTION ((AE_INFO, Status,
  676. "Unable to queue handler for GPE%02X - event disabled",
  677. GpeNumber));
  678. }
  679. break;
  680. default:
  681. /*
  682. * No handler or method to run!
  683. * 03/2010: This case should no longer be possible. We will not allow
  684. * a GPE to be enabled if it has no handler or method.
  685. */
  686. ACPI_ERROR ((AE_INFO,
  687. "No handler or method for GPE%02X, disabling event",
  688. GpeNumber));
  689. break;
  690. }
  691. return_UINT32 (ACPI_INTERRUPT_HANDLED);
  692. }
  693. #endif /* !ACPI_REDUCED_HARDWARE */