Rev 1498 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1498 | Rev 2216 | ||
---|---|---|---|
Line 6... | Line 6... | ||
6 | 6 | ||
7 | /****************************************************************************** |
7 | /****************************************************************************** |
8 | * |
8 | * |
9 | * 1. Copyright Notice |
9 | * 1. Copyright Notice |
10 | * |
10 | * |
11 | * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
11 | * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
12 | * All rights reserved. |
12 | * All rights reserved. |
13 | * |
13 | * |
14 | * 2. License |
14 | * 2. License |
15 | * |
15 | * |
Line 116... | Line 116... | ||
116 | 116 | ||
117 | #include "acpi.h" |
117 | #include "acpi.h" |
118 | #include "accommon.h" |
118 | #include "accommon.h" |
119 | #include "acevents.h" |
119 | #include "acevents.h" |
120 | #include "acnamesp.h" |
- | |
Line 121... | Line 120... | ||
121 | #include "acinterp.h" |
120 | #include "acnamesp.h" |
122 | 121 | ||
Line -... | Line 122... | ||
- | 122 | #define _COMPONENT ACPI_EVENTS |
|
- | 123 | ACPI_MODULE_NAME ("evgpeinit") |
|
- | 124 | ||
- | 125 | ||
- | 126 | /* |
|
- | 127 | * Note: History of _PRW support in ACPICA |
|
- | 128 | * |
|
- | 129 | * Originally (2000 - 2010), the GPE initialization code performed a walk of |
|
- | 130 | * the entire namespace to execute the _PRW methods and detect all GPEs |
|
- | 131 | * capable of waking the system. |
|
- | 132 | * |
|
- | 133 | * As of 10/2010, the _PRW method execution has been removed since it is |
|
- | 134 | * actually unnecessary. The host OS must in fact execute all _PRW methods |
|
- | 135 | * in order to identify the device/power-resource dependencies. We now put |
|
- | 136 | * the onus on the host OS to identify the wake GPEs as part of this process |
|
- | 137 | * and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This |
|
- | 138 | * not only reduces the complexity of the ACPICA initialization code, but in |
|
123 | #define _COMPONENT ACPI_EVENTS |
139 | * some cases (on systems with very large namespaces) it should reduce the |
124 | ACPI_MODULE_NAME ("evgpeinit") |
140 | * kernel boot time as well. |
125 | 141 | */ |
|
126 | 142 | ||
127 | /******************************************************************************* |
143 | /******************************************************************************* |
Line 286... | Line 302... | ||
286 | * |
302 | * |
287 | * RETURN: None |
303 | * RETURN: None |
288 | * |
304 | * |
289 | * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a |
305 | * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a |
290 | * result of a Load() or LoadTable() operation. If new GPE |
306 | * result of a Load() or LoadTable() operation. If new GPE |
291 | * methods have been installed, register the new methods and |
307 | * methods have been installed, register the new methods. |
292 | * enable and runtime GPEs that are associated with them. Also, |
- | |
293 | * run any newly loaded _PRW methods in order to discover any |
- | |
294 | * new CAN_WAKE GPEs. |
- | |
295 | * |
308 | * |
296 | ******************************************************************************/ |
309 | ******************************************************************************/ |
Line 297... | Line 310... | ||
297 | 310 | ||
298 | void |
311 | void |
Line 301... | Line 314... | ||
301 | { |
314 | { |
302 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo; |
315 | ACPI_GPE_XRUPT_INFO *GpeXruptInfo; |
303 | ACPI_GPE_BLOCK_INFO *GpeBlock; |
316 | ACPI_GPE_BLOCK_INFO *GpeBlock; |
304 | ACPI_GPE_WALK_INFO WalkInfo; |
317 | ACPI_GPE_WALK_INFO WalkInfo; |
305 | ACPI_STATUS Status = AE_OK; |
318 | ACPI_STATUS Status = AE_OK; |
306 | UINT32 NewWakeGpeCount = 0; |
- | |
307 | - | ||
Line 308... | Line -... | ||
308 | - | ||
Line 309... | Line -... | ||
309 | /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ |
- | |
310 | - | ||
311 | WalkInfo.OwnerId = TableOwnerId; |
- | |
312 | WalkInfo.ExecuteByOwnerId = TRUE; |
- | |
313 | WalkInfo.Count = 0; |
- | |
314 | - | ||
315 | if (AcpiGbl_LeaveWakeGpesDisabled) |
319 | |
316 | { |
- | |
317 | /* |
- | |
318 | * 1) Run any newly-loaded _PRW methods to find any GPEs that |
- | |
319 | * can now be marked as CAN_WAKE GPEs. Note: We must run the |
- | |
320 | * _PRW methods before we process the _Lxx/_Exx methods because |
320 | |
321 | * we will enable all runtime GPEs associated with the new |
321 | /* |
322 | * _Lxx/_Exx methods at the time we process those methods. |
- | |
323 | * |
- | |
324 | * Unlock interpreter so that we can run the _PRW methods. |
- | |
325 | */ |
- | |
326 | WalkInfo.GpeBlock = NULL; |
- | |
327 | WalkInfo.GpeDevice = NULL; |
- | |
328 | - | ||
329 | AcpiExExitInterpreter (); |
- | |
330 | - | ||
331 | Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
- | |
332 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
- | |
333 | AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); |
- | |
334 | if (ACPI_FAILURE (Status)) |
- | |
335 | { |
- | |
336 | ACPI_EXCEPTION ((AE_INFO, Status, |
- | |
337 | "While executing _PRW methods")); |
- | |
338 | } |
- | |
339 | - | ||
340 | AcpiExEnterInterpreter (); |
- | |
341 | NewWakeGpeCount = WalkInfo.Count; |
- | |
342 | } |
- | |
343 | - | ||
344 | /* |
- | |
345 | * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. |
322 | * Find any _Lxx/_Exx GPE methods that have just been loaded. |
346 | * |
323 | * |
347 | * Any GPEs that correspond to new _Lxx/_Exx methods and are not |
324 | * Any GPEs that correspond to new _Lxx/_Exx methods are immediately |
348 | * marked as CAN_WAKE are immediately enabled. |
325 | * enabled. |
349 | * |
326 | * |
350 | * Examine the namespace underneath each GpeDevice within the |
327 | * Examine the namespace underneath each GpeDevice within the |
351 | * GpeBlock lists. |
328 | * GpeBlock lists. |
Line 355... | Line 332... | ||
355 | { |
332 | { |
356 | return; |
333 | return; |
357 | } |
334 | } |
Line 358... | Line 335... | ||
358 | 335 | ||
- | 336 | WalkInfo.Count = 0; |
|
359 | WalkInfo.Count = 0; |
337 | WalkInfo.OwnerId = TableOwnerId; |
Line 360... | Line 338... | ||
360 | WalkInfo.EnableThisGpe = TRUE; |
338 | WalkInfo.ExecuteByOwnerId = TRUE; |
Line 361... | Line 339... | ||
361 | 339 | ||
362 | /* Walk the interrupt level descriptor list */ |
340 | /* Walk the interrupt level descriptor list */ |
Line 386... | Line 364... | ||
386 | } |
364 | } |
Line 387... | Line 365... | ||
387 | 365 | ||
388 | GpeXruptInfo = GpeXruptInfo->Next; |
366 | GpeXruptInfo = GpeXruptInfo->Next; |
Line 389... | Line 367... | ||
389 | } |
367 | } |
390 | 368 | ||
391 | if (WalkInfo.Count || NewWakeGpeCount) |
- | |
392 | { |
369 | if (WalkInfo.Count) |
393 | ACPI_INFO ((AE_INFO, |
- | |
394 | "Enabled %u new runtime GPEs, added %u new wakeup GPEs", |
370 | { |
Line 395... | Line 371... | ||
395 | WalkInfo.Count, NewWakeGpeCount)); |
371 | ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count)); |
396 | } |
372 | } |
397 | 373 | ||
Line 421... | Line 397... | ||
421 | * E - means that the GPE is edge triggered |
397 | * E - means that the GPE is edge triggered |
422 | * xx - is the GPE number [in HEX] |
398 | * xx - is the GPE number [in HEX] |
423 | * |
399 | * |
424 | * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods |
400 | * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods |
425 | * with that owner. |
401 | * with that owner. |
426 | * If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE |
- | |
427 | * method is immediately enabled (Used for Load/LoadTable operators) |
- | |
428 | * |
402 | * |
429 | ******************************************************************************/ |
403 | ******************************************************************************/ |
Line 430... | Line 404... | ||
430 | 404 | ||
431 | ACPI_STATUS |
405 | ACPI_STATUS |
Line 436... | Line 410... | ||
436 | void **ReturnValue) |
410 | void **ReturnValue) |
437 | { |
411 | { |
438 | ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); |
412 | ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); |
439 | ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
413 | ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
440 | ACPI_GPE_EVENT_INFO *GpeEventInfo; |
414 | ACPI_GPE_EVENT_INFO *GpeEventInfo; |
441 | ACPI_NAMESPACE_NODE *GpeDevice; |
- | |
442 | ACPI_STATUS Status; |
- | |
443 | UINT32 GpeNumber; |
415 | UINT32 GpeNumber; |
444 | char Name[ACPI_NAME_SIZE + 1]; |
416 | char Name[ACPI_NAME_SIZE + 1]; |
445 | UINT8 Type; |
417 | UINT8 Type; |
Line 472... | Line 444... | ||
472 | } |
444 | } |
Line 473... | Line 445... | ||
473 | 445 | ||
474 | /* |
446 | /* |
475 | * 3) Edge/Level determination is based on the 2nd character |
447 | * 3) Edge/Level determination is based on the 2nd character |
476 | * of the method name |
- | |
477 | * |
- | |
478 | * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is |
- | |
479 | * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. |
448 | * of the method name |
480 | */ |
449 | */ |
481 | switch (Name[1]) |
450 | switch (Name[1]) |
482 | { |
451 | { |
483 | case 'L': |
452 | case 'L': |
Line 549... | Line 518... | ||
549 | 518 | ||
550 | /* |
519 | /* |
551 | * Add the GPE information from above to the GpeEventInfo block for |
520 | * Add the GPE information from above to the GpeEventInfo block for |
552 | * use during dispatch of this GPE. |
521 | * use during dispatch of this GPE. |
- | 522 | */ |
|
553 | */ |
523 | GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK); |
554 | GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); |
524 | GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); |
Line 555... | Line -... | ||
555 | GpeEventInfo->Dispatch.MethodNode = MethodNode; |
- | |
556 | - | ||
557 | /* |
- | |
558 | * Enable this GPE if requested. This only happens when during the |
- | |
559 | * execution of a Load or LoadTable operator. We have found a new |
- | |
560 | * GPE method and want to immediately enable the GPE if it is a |
- | |
561 | * runtime GPE. |
- | |
562 | */ |
- | |
563 | if (WalkInfo->EnableThisGpe) |
- | |
564 | { |
- | |
565 | /* Ignore GPEs that can wake the system */ |
- | |
566 | - | ||
567 | if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) || |
- | |
568 | !AcpiGbl_LeaveWakeGpesDisabled) |
- | |
569 | { |
- | |
570 | WalkInfo->Count++; |
- | |
571 | GpeDevice = WalkInfo->GpeDevice; |
- | |
572 | - | ||
573 | if (GpeDevice == AcpiGbl_FadtGpeDevice) |
- | |
574 | { |
- | |
575 | GpeDevice = NULL; |
- | |
576 | } |
- | |
577 | - | ||
578 | Status = AcpiEnableGpe (GpeDevice, GpeNumber, |
- | |
579 | ACPI_GPE_TYPE_RUNTIME); |
- | |
580 | if (ACPI_FAILURE (Status)) |
- | |
581 | { |
- | |
582 | ACPI_EXCEPTION ((AE_INFO, Status, |
- | |
583 | "Could not enable GPE 0x%02X", GpeNumber)); |
- | |
584 | } |
- | |
585 | } |
- | |
586 | } |
525 | GpeEventInfo->Dispatch.MethodNode = MethodNode; |
587 | 526 | ||
588 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, |
527 | ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, |
589 | "Registered GPE method %s as GPE number 0x%.2X\n", |
528 | "Registered GPE method %s as GPE number 0x%.2X\n", |
590 | Name, GpeNumber)); |
529 | Name, GpeNumber)); |
591 | return_ACPI_STATUS (AE_OK); |
- | |
592 | } |
- | |
593 | - | ||
594 | - | ||
595 | /******************************************************************************* |
- | |
596 | * |
- | |
597 | * FUNCTION: AcpiEvMatchPrwAndGpe |
- | |
598 | * |
- | |
599 | * PARAMETERS: Callback from WalkNamespace |
- | |
600 | * |
- | |
601 | * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is |
- | |
602 | * not aborted on a single _PRW failure. |
- | |
603 | * |
- | |
604 | * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a |
- | |
605 | * Device. Run the _PRW method. If present, extract the GPE |
- | |
606 | * number and mark the GPE as a CAN_WAKE GPE. Allows a |
- | |
607 | * per-OwnerId execution if ExecuteByOwnerId is TRUE in the |
- | |
608 | * WalkInfo parameter block. |
- | |
609 | * |
- | |
610 | * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that |
- | |
611 | * owner. |
- | |
612 | * If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise, |
- | |
613 | * we only execute _PRWs that refer to the input GpeDevice. |
- | |
614 | * |
- | |
615 | ******************************************************************************/ |
- | |
616 | - | ||
617 | ACPI_STATUS |
- | |
618 | AcpiEvMatchPrwAndGpe ( |
- | |
619 | ACPI_HANDLE ObjHandle, |
- | |
620 | UINT32 Level, |
- | |
621 | void *Context, |
- | |
622 | void **ReturnValue) |
- | |
623 | { |
- | |
624 | ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
- | |
625 | ACPI_NAMESPACE_NODE *GpeDevice; |
- | |
626 | ACPI_GPE_BLOCK_INFO *GpeBlock; |
- | |
627 | ACPI_NAMESPACE_NODE *TargetGpeDevice; |
- | |
628 | ACPI_NAMESPACE_NODE *PrwNode; |
- | |
629 | ACPI_GPE_EVENT_INFO *GpeEventInfo; |
- | |
630 | ACPI_OPERAND_OBJECT *PkgDesc; |
- | |
631 | ACPI_OPERAND_OBJECT *ObjDesc; |
- | |
632 | UINT32 GpeNumber; |
- | |
633 | ACPI_STATUS Status; |
- | |
634 | - | ||
635 | - | ||
636 | ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe); |
- | |
637 | - | ||
638 | - | ||
639 | /* Check for a _PRW method under this device */ |
- | |
640 | - | ||
641 | Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW, |
- | |
642 | ACPI_NS_NO_UPSEARCH, &PrwNode); |
- | |
643 | if (ACPI_FAILURE (Status)) |
- | |
644 | { |
- | |
645 | return_ACPI_STATUS (AE_OK); |
- | |
646 | } |
- | |
647 | - | ||
648 | /* Check if requested OwnerId matches this OwnerId */ |
- | |
649 | - | ||
650 | if ((WalkInfo->ExecuteByOwnerId) && |
- | |
651 | (PrwNode->OwnerId != WalkInfo->OwnerId)) |
- | |
652 | { |
- | |
653 | return_ACPI_STATUS (AE_OK); |
- | |
654 | } |
- | |
655 | - | ||
656 | /* Execute the _PRW */ |
- | |
657 | - | ||
658 | Status = AcpiUtEvaluateObject (PrwNode, NULL, |
- | |
659 | ACPI_BTYPE_PACKAGE, &PkgDesc); |
- | |
660 | if (ACPI_FAILURE (Status)) |
- | |
661 | { |
- | |
662 | return_ACPI_STATUS (AE_OK); |
- | |
663 | } |
- | |
664 | - | ||
665 | /* The returned _PRW package must have at least two elements */ |
- | |
666 | - | ||
667 | if (PkgDesc->Package.Count < 2) |
- | |
668 | { |
- | |
669 | goto Cleanup; |
- | |
670 | } |
- | |
671 | - | ||
672 | /* Extract pointers from the input context */ |
- | |
673 | - | ||
674 | GpeDevice = WalkInfo->GpeDevice; |
- | |
675 | GpeBlock = WalkInfo->GpeBlock; |
- | |
676 | - | ||
677 | /* |
- | |
678 | * The _PRW object must return a package, we are only interested |
- | |
679 | * in the first element |
- | |
680 | */ |
- | |
681 | ObjDesc = PkgDesc->Package.Elements[0]; |
- | |
682 | - | ||
683 | if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) |
- | |
684 | { |
- | |
685 | /* Use FADT-defined GPE device (from definition of _PRW) */ |
- | |
686 | - | ||
687 | TargetGpeDevice = NULL; |
- | |
688 | if (GpeDevice) |
- | |
689 | { |
- | |
690 | TargetGpeDevice = AcpiGbl_FadtGpeDevice; |
- | |
691 | } |
- | |
692 | - | ||
693 | /* Integer is the GPE number in the FADT described GPE blocks */ |
- | |
694 | - | ||
695 | GpeNumber = (UINT32) ObjDesc->Integer.Value; |
- | |
696 | } |
- | |
697 | else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) |
- | |
698 | { |
- | |
699 | /* Package contains a GPE reference and GPE number within a GPE block */ |
- | |
700 | - | ||
701 | if ((ObjDesc->Package.Count < 2) || |
- | |
702 | ((ObjDesc->Package.Elements[0])->Common.Type != |
- | |
703 | ACPI_TYPE_LOCAL_REFERENCE) || |
- | |
704 | ((ObjDesc->Package.Elements[1])->Common.Type != |
- | |
705 | ACPI_TYPE_INTEGER)) |
- | |
706 | { |
- | |
707 | goto Cleanup; |
- | |
708 | } |
- | |
709 | - | ||
710 | /* Get GPE block reference and decode */ |
- | |
711 | - | ||
712 | TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node; |
- | |
713 | GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value; |
- | |
714 | } |
- | |
715 | else |
- | |
716 | { |
- | |
717 | /* Unknown type, just ignore it */ |
- | |
718 | - | ||
719 | goto Cleanup; |
- | |
720 | } |
- | |
721 | - | ||
722 | /* Get the GpeEventInfo for this GPE */ |
- | |
723 | - | ||
724 | if (GpeDevice) |
- | |
725 | { |
- | |
726 | /* |
- | |
727 | * Is this GPE within this block? |
- | |
728 | * |
- | |
729 | * TRUE if and only if these conditions are true: |
- | |
730 | * 1) The GPE devices match. |
- | |
731 | * 2) The GPE index(number) is within the range of the Gpe Block |
- | |
732 | * associated with the GPE device. |
- | |
733 | */ |
- | |
734 | if (GpeDevice != TargetGpeDevice) |
- | |
735 | { |
- | |
736 | goto Cleanup; |
- | |
737 | } |
- | |
738 | - | ||
739 | GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); |
- | |
740 | } |
- | |
741 | else |
- | |
742 | { |
- | |
743 | /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */ |
- | |
744 | - | ||
745 | GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber); |
- | |
746 | } |
- | |
747 | - | ||
748 | if (GpeEventInfo) |
- | |
749 | { |
- | |
750 | if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
- | |
751 | { |
- | |
752 | /* This GPE can wake the system */ |
- | |
753 | - | ||
754 | GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; |
- | |
755 | WalkInfo->Count++; |
- | |
756 | } |
- | |
757 | } |
- | |
758 | - | ||
759 | Cleanup: |
- | |
760 | AcpiUtRemoveReference (PkgDesc); |
- | |
761 | return_ACPI_STATUS (AE_OK); |
- |