| Commit message (Collapse) | Author | Age | Files | Lines |
|\
| |
| | |
Make AddressSpaceHandler Install and _REG execution 2 separate steps
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
ACPI-2.0 says that the EC OpRegion handler must be available immediately
(like the standard default OpRegion handlers):
Quoting from the ACPI spec version 6.3: "6.5.4 _REG (Region) ...
2. OSPM must make Embedded Controller operation regions, accessed via
the Embedded Controllers described in ECDT, available before executing
any control method. These operation regions may become inaccessible
after OSPM runs _REG(EmbeddedControl, 0)."
So the OS must probe the ECDT described EC and install the OpRegion handler
before calling AcpiEnableSubsystem() and AcpiInitializeObjects().
This is a problem because calling AcpiInstallAddressSpaceHandler()
does not just install the OpRegion handler, it also runs the EC's _REG
method. This _REG method may rely on initialization done by the _INI
methods of one of the PCI / _SB root devices.
For the other early/default OpRegion handlers the OpRegion handler
install and the _REG execution is split into 2 separate steps:
1. AcpiEvInstallRegionHandlers(), called early from AcpiLoadTables()
2. AcpiEvInitializeOpRegions(), called from AcpiInitializeObjects()
To fix the EC OpRegion issue, add 2 bew functions:
1. AcpiInstallAddressSpaceHandlerNo_Reg()
2. AcpiExecuteRegMethods()
to allow doing things in 2 steps for other OpRegion handlers,
like the EC handler, too.
Note that the comment describing AcpiEvInstallRegionHandlers() even has
an alinea describing this problem. Using the new methods allows users
to avoid this problem.
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214899
Reported-and-tested-by: Johannes Penßel <johannespenssel@posteo.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|/
|
|
| |
Copyright updates to 2023.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
FFH(Fixed Function Hardware) Opregion is approved to be added in ACPI 6.5 via
code first approach[1]. It requires special context data similar to GPIO and
Generic Serial Bus as it needs to know platform specific offset and length.
Add support for the special context data needed by FFH Opregion.
FFH OpRegion enables advanced use of FFH on some architectures. For example,
it could be used to easily proxy AML code to architecture-specific behavior
(to ensure it is OS initiated)
Actual behavior of FFH is ofcourse architecture specific and depends on
the FFH bindings. The offset and length could have arch specific meaning
or usage.
[1] https://bugzilla.tianocore.org/show_bug.cgi?id=3598
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
|
|
|
|
| |
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some chipsets (such as Loongson's LS7A) support fixed pcie wake event
which is defined in the PM1 block(related description can be found in
4.8.4.1.1 PM1 Status Registers, 4.8.4.2.1 PM1 Control Registers and
5.2.9 Fixed ACPI Description Table (FADT)), so we add code to handle it.
ACPI Spec 6.4 link:
https://uefi.org/specifications/ACPI/6.4/
Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
|
|
|
|
| |
Removed some tabs and // comments.
|
|
|
|
| |
Affects all source modules and utility signons.
|
|
|
|
| |
Repaired with casts.
|
|\
| |
| | |
Use original table pointers rather than round-tripping through ACPI_PHYSICAL_ADDRESS
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Currently the pointer to the table is cast to ACPI_PHYSICAL_ADDRESS and
later cast back to a pointer to be dereferenced. Whether or not this is
supported is implementation-defined.
On CHERI, and thus Arm's experimental Morello prototype architecture,
pointers are represented as capabilities, which are unforgeable bounded
pointers, providing always-on fine-grained spatial memory safety. This
means that any pointer cast to a plain integer will lose all its
associated metadata, and when cast back to a pointer it will give a
null-derived pointer (one that has the same metadata as null but an
address equal to the integer) that will trap on any dereference. As a
result, this is an implementation where ACPI_PHYSICAL_ADDRESS cannot be
used as a hack to store real pointers.
Thus, add a new field to ACPI_OBJECT_REGION to store the pointer for
table regions, and propagate it to AcpiExDataTableSpaceHandler via the
region context, to use a more portable implementation that supports
CHERI.
|
|/
|
|
|
|
|
|
|
|
|
| |
PCC Opregion added in ACPIC 6.3 requires special context data similar
to GPIO and Generic Serial Bus as it needs to know the internal PCC
buffer and its length as well as the PCC channel index when the opregion
handler is being executed by the OSPM.
Lets add support for the special context data needed by PCC Opregion.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
|
|
|
|
|
|
|
|
| |
The handling of the SpaceId == ACPI_ADR_SPACE_GSBUS and
SpaceId == ACPI_ADR_SPACE_GPIO cases is almost identical,
fold the 2 cases into 1 to remove some code duplication.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The handling of the GenericSerialBus (I2C) and GPIO OpRegions in
AcpiEvAddressSpaceDispatch() passes a number of extra parameters to
the address-space handler through the address-space Context pointer
(instead of using more function parameters).
The Context is shared between threads, so if multiple threads try to call
the handler for the same address-space at the same time, then
a second thread could change the parameters of a first thread while the
handler is running for the first thread.
An example of this race hitting is the Lenovo Yoga Tablet2 1015L, where
there are both AttribBytes accesses and AttribByte accesses to the same
address-space. The AttribBytes access stores the number of bytes to
transfer in Context->AccessLength. Where as for the AttribByte access the
number of bytes to transfer is always 1 and FieldObj->Field.AccessLength
is unused (so 0). Both types of accesses racing from different threads
leads to the following problem:
1. Thread a. starts an AttribBytes access, stores a non 0 value
from FieldObj->Field.AccessLength in Context->AccessLength
2. Thread b. starts an AttribByte access, stores 0 in
Context->AccessLength
3. Thread a. calls i2c_acpi_space_handler() (under Linux). Which
sees that the access-type is ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE and
calls acpi_gsb_i2c_read_bytes(..., Context->AccessLength)
4. At this point Context->AccessLength is 0 (set by thread b.)
rather then the FieldObj->Field.AccessLength value from thread a.
This 0 length reads leads to the following errors being logged:
i2c i2c-0: adapter quirk: no zero length (addr 0x0078, size 0, read)
i2c i2c-0: i2c read 0 bytes from client@0x78 starting at reg 0x0 failed, error: -95
Note this is just an example of the problems which this race can cause.
There are likely many more (sporadic) problems caused by this race.
This commit adds a new ContextMutex to acpi_object_addr_handler
and makes AcpiEvAddressSpaceDispatch() take that mutex when
using the shared Context to pass extra parameters to an address-space
handler, fixing this race.
Note the new mutex must be taken *after* exiting the interpreter,
therefor the existing AcpiExExitInterpreter() call is moved to above
the code which stores the extra parameters in the Context.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
|
|
| |
modules.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Before this commit AcpiEvExecuteRegMethods() had special handling
to handle "orphan" (no matching OpRegion declared) _REG methods for EC
nodes.
On Intel Cherry Trail devices there are 2 possible ACPI OpRegions for
accessing GPIOs. The standard GeneralPurposeIo OpRegion and the Cherry
Trail specific UserDefined 0x9X OpRegions.
Having 2 different types of OpRegions leads to potential issues with
checks for OpRegion availability, or in other words checks if _REG has
been called for the OpRegion which the ACPI code wants to use.
Except for the "orphan" EC handling, ACPICA core does not call _REG on
an ACPI node which does not define an OpRegion matching the type being
registered; and the reference design DSDT, from which most Cherry Trail
DSDTs are derived, does not define GeneralPurposeIo, nor UserDefined(0x93)
OpRegions for the GPO2 (UID 3) device, because no pins were assigned ACPI
controlled functions in the reference design.
Together this leads to the perfect storm, at least on the Cherry Trail
based Medion Akayo E1239T. This design does use a GPO2 pin from its ACPI
code and has added the Cherry Trail specific UserDefined(0x93) opregion
to its GPO2 ACPI node to access this pin.
But it uses a has _REG been called availability check for the standard
GeneralPurposeIo OpRegion. This clearly is a bug in the DSDT, but this
does work under Windows. This issue leads to the intel_vbtn driver
reporting the device always being in tablet-mode at boot, even if it
is in laptop mode. Which in turn causes userspace to ignore touchpad
events. So iow this issues causes the touchpad to not work at boot.
This commit fixes this by extending the "orphan" _REG method handling
to also apply to GPIO address-space handlers.
Note it seems that Windows always calls "orphan" _REG methods so me
may want to consider dropping the space-id check and always do
"orphan" _REG method handling.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Erik Kaneda <erik.kaneda@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The ACPICA's strategy with respect to the handling of memory mappings
associated with memory operation regions is to avoid mapping the
entire region at once which may be problematic at least in principle
(for example, it may lead to conflicts with overlapping mappings
having different attributes created by drivers). It may also be
wasteful, because memory opregions on some systems take up vast
chunks of address space while the fields in those regions actually
accessed by AML are sparsely distributed.
For this reason, a one-page "window" is mapped for a given opregion
on the first memory access through it and if that "window" does not
cover an address range accessed through that opregion subsequently,
it is unmapped and a new "window" is mapped to replace it. Next,
if the new "window" is not sufficient to acess memory through the
opregion in question in the future, it will be replaced with yet
another "window" and so on. That may lead to a suboptimal sequence
of memory mapping and unmapping operations, for example if two fields
in one opregion separated from each other by a sufficiently wide
chunk of unused address space are accessed in an alternating pattern.
The situation may still be suboptimal if the deferred unmapping
introduced previously is supported by the OS layer. For instance,
the alternating memory access pattern mentioned above may produce
a relatively long list of mappings to release with substantial
duplication among the entries in it, which could be avoided if
AcpiExSystemMemorySpaceHandler() did not release the mapping
used by it previously as soon as the current access was not covered
by it.
In order to improve that, modify AcpiExSystemMemorySpaceHandler()
to preserve all of the memory mappings created by it until the memory
regions associated with them go away.
Accordingly, update AcpiEvSystemMemoryRegionSetup() to unmap all
memory associated with memory opregions that go away.
Reported-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Erik Kaneda <erik.kaneda@intel.com>
|
|
|
|
|
|
|
|
|
|
|
| |
Introduce a new helper function, AcpiAnyGpeStatusSet(), for
checking the status bits of all enabled GPEs in one go.
It is needed to distinguish spurious SCIs from genuine ones when
deciding whether or not to wake up the system from suspend-to-idle.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Erik Kaneda <erik.kaneda@intel.com>
|
|
|
|
| |
"enable" fixed events -> "disable" all fixed events.
|
|
|
|
| |
Including tool signons.
|
|
|
|
| |
From Clang V5.0.1. Mostly "set but never read" warnings.
|
|
|
|
|
|
|
|
|
|
| |
In some cases it is useful to know whether or not the
AcpiEvDetectGpe() called by AcpiDispatchGpe() has found the GPE to be
active, so return the return value of it (whose data type is UINT32)
from latter.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|
|
|
|
|
|
|
|
|
| |
Introduce acpi_dispatch_gpe() as a wrapper around AcpiEvDetectGpe()
for checking if the given GPE (as represented by a GPE device handle
and a GPE number) is currently active and dispatching it (if that's
the case) outside of interrupt context.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ACPI GPEs (other than the EC one) can be enabled in two situations.
First, the GPEs with existing _Lxx and _Exx methods are enabled
implicitly by ACPICA during system initialization. Second, the GPEs
without these methods (like GPEs listed by _PRW objects for wakeup
devices) need to be enabled directly by the code that is going to use
them (e.g. ACPI power management or device drivers).
In the former case, if the status of a given GPE is set to start
with, its handler method (either _Lxx or _Exx) needs to be invoked to
take care of the events (possibly) signaled before the GPE was
enabled. In the latter case, however, the first caller of
acpi_enable_gpe() for a given GPE should not be expected to care
about any events that might be signaled through it earlier. In that
case, it is better to clear the status of the GPE before enabling it,
to prevent stale events from triggering unwanted actions (like
spurious system resume, for example).
For this reason, modify acpi_ev_add_gpe_reference() to take an
additional boolean argument indicating whether or not the GPE status
needs to be cleared when its reference counter changes from zero to
one and make acpi_enable_gpe() pass TRUE to it through that new
argument.
Fixes: 18996f2db918 ("ACPICA: Events: Stop unconditionally clearing ACPI IRQs during suspend/resume")
Reported-by: Furquan Shaikh <furquan@google.com>
Tested-by: Furquan Shaikh <furquan@google.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This reverts ACPICA commit 6c43e1acdf93a04ca32898d1d89d93fde04d121a.
Revert "ACPICA: Clear status of GPEs before enabling them"
Revert commit c8b1917c8987 ("ACPICA: Clear status of GPEs before
enabling them") that causes problems with Thunderbolt controllers
to occur if a dock device is connected at init time (the xhci_hcd
and thunderbolt modules crash which prevents peripherals connected
through them from working).
Commit c8b1917c8987 effectively causes commit ecc1165b8b74 ("ACPICA:
Dispatch active GPEs at init time") to get undone, so the problem
addressed by commit ecc1165b8b74 appears again as a result of it.
Fixes: c8b1917c8987 ("ACPICA: Clear status of GPEs before enabling them")
Link: https://lore.kernel.org/lkml/s5hy33siofw.wl-tiwai@suse.de/T/#u
Link: https://bugzilla.opensuse.org/show_bug.cgi?id=1132943
Reported-by: Michael Hirmke <opensuse@mike.franken.de>
Reported-by: Takashi Iwai <tiwai@suse.de>
Cc: 4.17+ <stable@vger.kernel.org> # 4.17+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Commit 18996f2db918 ("ACPICA: Events: Stop unconditionally
clearing ACPI IRQs during suspend/resume") was added to stop clearing
of event status bits unconditionally on suspend and resume paths. This
was done because of an issue
reported (https://bugzilla.kernel.org/show_bug.cgi?id=196249) where
lid status stays closed even on resume (which happens because event
status bits are cleared unconditionally on resume). Though this change
fixed the issue on suspend path, it introduced regressions on several
resume paths.
First regression was reported and fixed on S5 path by the following
change: commit fa85015c0d95 ("ACPICA: Clear status of all events when
entering S5"). Next regression was reported and fixed on all legacy
sleep paths by the commit f317c7dc12b7 ("ACPICA: Clear status of all
events when entering sleep states"). However, regression still exists
on S0ix sleep path since it does not follow the legacy sleep path.
In case of S0ix, events are enabled as part of device suspend path. If
status bits for the events are set when they are enabled, it could
result in premature wake from S0ix. This change ensures that status is
cleared for any event that is being enabled so that any stale events
are cleared out.
Signed-off-by: Furquan Shaikh <furquan@google.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|
|
|
|
|
|
| |
ACPI_NAME_SIZE changed to ACPI_NAMESEG_SIZE
This clarifies that this is the length of an individual
nameseg, not the length of a generic namestring/namepath.
Improves understanding of the code.
|
|
|
|
| |
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|\
| |
| | |
Remove legacy module-level code support
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Module-level code refers to executable ASL code that runs during
table load. This is typically used in ASL to declare named objects
based on a condition evaluated during table load like so:
DefinitionBlock(...)
{
OpreationRegion (OPR1, SystemMemory, ...)
Field (OPR1)
{
FLD1, 8 /* Assume that FLD1's value is 0x1 */
}
/* The if statement below is referred to as module-level code */
If (FLD1)
{
/* Declare DEV1 conditionally */
Device (DEV1) {...}
}
Device (DEV2)
{
...
}
}
In legacy module-level code, the execution of the If statement
was deferred after other modules were loaded. The order of
code execution for the table above is the following:
1.) Load OPR1 to the ACPI Namespace
2.) Load FLD1 to the ACPI Namespace (not intended for drivers)
3.) Load DEV2 to the ACPI Namespace
4.) Execute If (FLD1) and load DEV1 if the condition is true
This legacy approach can be problematic for tables that look like the
following:
DefinitionBlock(...)
{
OpreationRegion (OPR1, SystemMemory, ...)
Field (OPR1)
{
FLD1, 8 /* Assume that FLD1's value is 0x1 */
}
/* The if statement below is referred to as module-level code */
If (FLD1)
{
/* Declare DEV1 conditionally */
Device (DEV1) {...}
}
Scope (DEV1)
{
/* Add objects DEV1's scope */
Name (OBJ1, 0x1234)
}
}
When loading this in the legacy approach, Scope DEV1 gets evaluated
before the If statement. The following is the order of execution:
1.) Load OPR1 to the ACPI Namespace
2.) Load FLD1 to the ACPI Namespace (not intended for drivers)
3.) Add OBJ1 under DEV1's scope -- ERROR. DEV1 does not exist
4.) Execute If (FLD1) and load DEV1 if the condition is true
The legacy approach can never succeed for tables like this due to the
deferral of the module-level code. Due to this limitation, a new
module-level code was developed. This new approach exeutes if
statements in the order that they appear in the definition block.
With this approach, the order of execution for the above defintion
block is as follows:
1.) Load OPR1 to the ACPI Namespace
2.) Load FLD1 to the ACPI Namespace (not intended for drivers)
3.) Execute If (FLD1) and load DEV1 because the condition is true
4.) Add OBJ1 under DEV1's scope.
Since DEV1 is loaded in the namespace in step 3, step 4 executes
successfully.
This change removes support for the legacy module-level code
execution. From this point onward, the new module-level code
execution will be the official approach.
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|/
|
|
| |
including tool signons.
|
|
|
|
|
|
| |
These address spaces are defined by the ACPI spec to be
"always available", and thus _REG should never be run on them.
Provides compatibility with other ACPI implementations.
|
|\
| |
| | |
Events: add a return on failure from AcpiHwRegisterRead
|
| |
| |
| |
| |
| |
| |
| | |
This ensures that AcpiEvFixedEventDetect does not use FixedStatus and
and FixedEnable as uninitialized variables.
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|/
|
|
|
| |
This prepares the code for eventual removal of the original
style of deferred execution of the MLC.
|
|\
| |
| | |
macros: fix ACPI_ERROR_NAMESPACE macro
|
| |
| |
| |
| |
| |
| |
| | |
This fix also involves putting some ACPI_ERROR_NAMESPACE parameters inside
macros. By doing so, we avoid compilation errors from unused variables.
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
|
|/
|
|
|
| |
Was AcpiGbl_ParseTableAsTermList, changed to:
AcpiGbl_ExecuteTablesAsMethods.
|
|\
| |
| | |
Acpica gpe
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
After being enabled for the first time, the GPEs may have STS bits already
set. Setting EN bits is not sufficient to trigger the GPEs again, so this
patch polls GPEs after enabling them for the first time.
This is a cleaner version on top of the "GPE clear" fix generated according
to Mika's report and Rafael's original Linux based fix. Based on Linux
commit originated from Rafael J. Wysocki, fixed by Lv Zheng.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
evaluations
There is a risk that a GPE method/handler may be invoked twice. Let's
consider a case, both GPE0(RAW_HANDLER) and GPE1(_Exx) is triggered.
=======================================+=============================
IRQ handler (top-half) |IRQ polling
=======================================+=============================
AcpiEvDetectGpe() |
LOCK() |
READ (GPE0-7 enable/status registers)|
^^^^^^^^^^^^ROOT CAUSE^^^^^^^^^^^^^^^|
Walk GPE0 |
UNLOCK() |LOCK()
Invoke GPE0 RAW_HANDLER |READ (GPE1 enable/status bit)
|AcpiEvGpeDispatch(irq=false)
| CLEAR (GPE1 enable bit)
| CLEAR (GPE1 status bit)
LOCK() |UNLOCK()
Walk GPE1 +=============================
AcpiEvGpeDispatch(irq=true) |IRQ polling (defer)
CLEAR (GPE1 enable bit) +=============================
CLEAR (GPE1 status bit) |AcpiEvAsyncExecuteGpeMethod()
Walk others | Evaluate GPE1 _Exx
fi | AcpiEvAsyncEnableGpe()
UNLOCK() | LOCK()
=======================================+ SET (GPE enable bit)
IRQ handler (bottom-half) | UNLOCK()
=======================================+
AcpiEvAsyncExecuteGpeMethod() |
Evaluate GPE1 _Exx |
AcpiEvAsyncEnableGpe() |
LOCK() |
SET (GPE1 enable bit) |
UNLOCK() |
=======================================+=============================
If AcpiEvDetectGpe() is only invoked from the IRQ context, there won't be
more than one _Lxx/_Exx evaluations for one status bit flagging if the IRQ
handlers controlled by the underlying IRQ chip/driver (ex. APIC) are run in
serial. Note that, this is a known potential gap and we had an approach,
locking entire non-raw-handler processes in the top-half IRQ handler and
handling all raw-handlers out of the locked loop to be friendly to those
IRQ chip/driver. But the approach is too complicated while the issue is not
so real, thus ACPICA treated such issue (if any) as a parallelism/quality
issue of the underlying IRQ chip/driver to stop putting it on the radar.
Bug in link #1 is suspiciously reflecting the same cause, and if so, it can
also be fixed by this simpler approach.
But it will be no excuse an ACPICA problem now if ACPICA starts to poll
IRQs itself. In the changed scenario, _Exx will be evaluated from the task
context due to new ACPICA provided "polling after enabling GPEs" mechanism.
And the above figure uses edge-triggered GPEs demonstrating the possibility
of evaluating _Exx twice for one status bit flagging.
As a conclusion, there is now an increased chance of evaluating _Lxx/_Exx
more than once for one status bit flagging.
However this is still not a real problem if the _Lxx/_Exx checks the
underlying hardware IRQ reasoning and finally just changes the 2nd and the
follow-up evaluations into no-ops. Note that _Lxx should always be written
in this way as a level-trigger GPE could have it's status wrongly
duplicated by the underlying IRQ delivery mechanisms. But _Exx may have
very low quality BIOS by BIOS to trigger real issues. For example, trigger
duplicated button notifications.
To solve this issue, we need to stop reading a bunch of enable/status
register bits, but read only one GPE's enable/status bit. And GPE status
register's W1C nature ensures that acknowledging one GPE won't affect
another GPEs' status bits. Thus the hardware GPE architecture has already
provided us with the mechanism of implementing such parallelism.
So we can lock around one GPE handling process to achieve the parallelism:
1. If we can incorporate GPE enable bit check in detection and ensure the
atomicity of the following process (top-half IRQ handler):
READ (enable/status bit)
if (enabled && raised)
CLEAR (enable bit)
and handle the GPE after this process, we can ensure that we will only
invoke GPE handler once for one status bit flagging.
2. In addtion for edge-triggered GPEs, if we can ensure the atomicity of
the following process (top-half IRQ handler):
READ (enable/status bit)
if (enabled && raised)
CLEAR (enable bit)
CLEAR (status bit)
and handle the GPE after this process, we can ensure that we will only
invoke GPE handler once for one status bit flagging.
By doing a cleanup in this way, we can remove duplicate GPE handling code
and ensure that all logics are collected in 1 function. And the function
will be safe for both IRQ interrupt and IRQ polling, and will be safe for
us to release and re-acquire AcpiGbl_GpeLock at any time rather than raw
handler only during the top-half IRQ handler. Lv Zheng.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=196703 [#1]
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Unconditionally clearing ACPI IRQs during suspend/resume can lead to
unexpected IRQ losts. This patch fixes this issue by removing such IRQ
clearing code.
If this patch triggers regression, the regression should be in the GPE
handlers that cannot correctly determine some spurious triggered events as
no-ops. Please report any regression related to this commit to the ACPI
component on kernel bugzilla. Lv Zheng.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=196249
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Reported-and-tested-by: Eric Bakula-Davis <ericbakuladavis@gmail.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Runtime GPEs have corresponding _Lxx/_Exx methods and are enabled
automatically during the initialization of the ACPI subsystem through
AcpiUpdateAllGpes() with the assumption that AcpiSetupGpeForWake()
will be called in advance for all of the GPEs pointed to by _PRW
objects in the namespace that may be affected by AcpiUpdateAllGpes().
That is, AcpiEvInitializeGpeBlock() can only be called for a GPE
block after AcpiSetupGpeForWake() has been called for all of the
_PRW (wakeup) GPEs in it.
The platform firmware on some systems, however, expects GPEs to be
enabled before the enumeration of devices which is when
AcpiSetupGpeForWake() is called and that goes against the above
assumption.
For this reason, introduce a new flag to be set by
AcpiEvInitializeGpeBlock() when automatically enabling a GPE
to indicate to AcpiSetupGpeForWake() that it needs to drop the
reference to the GPE coming from AcpiEvInitializeGpeBlock()
and modify AcpiSetupGpeForWake() accordingly. These changes
allow AcpiSetupGpeForWake() and AcpiEvInitializeGpeBlock()
to be invoked in any order.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
In some cases GPEs are already active when they are enabled by
AcpiEvInitializeGpeBlock() and whatever happens next may depend
on the result of handling the events signaled by them, so the
events should not be discarded (which is what happens currently) and
they should be handled as soon as reasonably possible.
For this reason, modify AcpiEvInitializeGpeBlock() to
dispatch GPEs with the status flag set in-band right after
enabling them.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|
| |
| |
| |
| | |
including tool signons.
|
|/
|
|
|
|
| |
AE_TIME is seen to be returned from the EC driver/handler so
often that an additional error message is added to help
clarify the problem.
|
|
|
|
|
|
|
| |
This reverts commit 884a0618fcdca932d11aa0eed3ecea21fa24215d, reversing
changes made to d6756a8e6d72426b26bb80e4baa9bab9fd05b764.
Causes a flood of GPEs in AcpiExec.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
After being enabled for the first time, the GPEs may have STS bits already
set. Setting EN bits is not sufficient to trigger the GPEs again, so this
patch polls GPEs after enabling them for the first time.
This is a cleaner version on top of the "GPE clear" fix generated according
to Mika's report and Rafael's original Linux based fix. Based on Linux
commit originated from Rafael J. Wysocki, fixed by Lv Zheng, tested by Mika
Westerberg.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
evaluations
There is a risk that a GPE method/handler may be invoked twice. Let's
consider a case, both GPE0(RAW_HANDLER) and GPE1(_Exx) is triggered.
AcpiEvDetectGpe()
LOCK()
READ (GPE0-7 enable/status registers)
^^^^^^^^^^^^ROOT CAUSE^^^^^^^^^^^^^^^
Walk GPE0
UNLOCK()
Invoke GPE0 RAW_HANDLER READ (GPE1 enable/status bit)
LOCK() AcpiEvGpeDispatch()
Walk GPE1 CLEAR (GPE1 enable bit)
AcpiEvGpeDispatch() CLEAR (GPE1 status bit)
CLEAR (GPE1 enable bit) Evaluate GPE1 _Exx
CLEAR (GPE1 status bit)
Evaluate GPE1 _Exx
fi
UNLOCK()
If AcpiEvDetectGpe() is only invoked from the IRQ context, this situation
may not be triggered if the IRQ handlers are controlled by the IRQ
chip/driver to be run in serial. But it will be a real problem if _Exx will
be evaluated from the task context due to "polling after enabling GPEs".
And the above figure just uses edge-triggered GPEs demonstrated such an
issue.
As a conclusion, there is now an increased chance of evaluating _Lxx/_Exx
more than once for one status bit flagging. This is not a problem if the
_Lxx/_Exx checks underlying hardware IRQ reasoning and finally just changes
the 2nd and the follow-up evaluations into no-ops. Note that _Lxx should
always be written in this way as a level-trigger GPE could have it's status
be wrongly duplicated by the underlying IRQ delivery mechanisms. But _Exx
may have very low quality BIOS by BIOS to trigger issues. For example,
trigger duplicated button notifications.
To solve this issue, we need to stop reading a bunch of enable/status
register bits, but read only one GPE's enable/status bit. And GPE status
register's W1C nature ensures that acknowledging one GPE won't affect
another GPE's handling process. Thus the hardware GPE architecture has
already provided us with the mechanism of implementing such parallelism.
So we can actually only lock around one GPE handling to parallelize GPE
handling processes:
1. If we can incorporate GPE enable bit check in detection and ensure the
atomicity of the following process (top-half IRQ handler):
READ (enable/status bit)
if (enabled && raised)
CLEAR (enable bit)
and handle the GPE after this process, we can ensure that we will only
invoke GPE handler once for one status bit flagging.
2. In addtion for edge-triggered GPEs, if we can ensure the atomicity of
the following process (top-half IRQ handler):
READ (enable/status bit)
if (enabled && raised)
CLEAR (enable bit)
CLEAR (status bit)
and handle the GPE after this process, we can ensure that we will only
invoke GPE handler once for one status bit flagging.
By doing a cleanup in this way, we can remove duplicate GPE handling code
and ensure that all logics are collected in 1 function. And the function
will be safe for both IRQ interrupt and IRQ polling, and will be safe for
us to release and re-acquire AcpiGbl_GpeLock at any time other than the
above "top-half IRQ handler" process. Lv Zheng.
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Unconditionally clearing ACPI IRQs during suspend/resume can lead to
unexpected IRQ losts. This patch fixes this issue by removing such IRQ
clearing code.
If this patch triggers regression, the regression should be in the GPE
handlers that cannot correctly determine some spurious triggered events as
no-ops. Please report any regression related to this commit to the ACPI
component on kernel bugzilla. Lv Zheng.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=196249
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Reported-and-tested-by: Eric Bakula-Davis <ericbakuladavis@gmail.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
|