Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,129 @@
APEI Error INJection
~~~~~~~~~~~~~~~~~~~~
EINJ provides a hardware error injection mechanism
It is very useful for debugging and testing of other APEI and RAS features.
To use EINJ, make sure the following are enabled in your kernel
configuration:
CONFIG_DEBUG_FS
CONFIG_ACPI_APEI
CONFIG_ACPI_APEI_EINJ
The user interface of EINJ is debug file system, under the
directory apei/einj. The following files are provided.
- available_error_type
Reading this file returns the error injection capability of the
platform, that is, which error types are supported. The error type
definition is as follow, the left field is the error type value, the
right field is error description.
0x00000001 Processor Correctable
0x00000002 Processor Uncorrectable non-fatal
0x00000004 Processor Uncorrectable fatal
0x00000008 Memory Correctable
0x00000010 Memory Uncorrectable non-fatal
0x00000020 Memory Uncorrectable fatal
0x00000040 PCI Express Correctable
0x00000080 PCI Express Uncorrectable fatal
0x00000100 PCI Express Uncorrectable non-fatal
0x00000200 Platform Correctable
0x00000400 Platform Uncorrectable non-fatal
0x00000800 Platform Uncorrectable fatal
The format of file contents are as above, except there are only the
available error type lines.
- error_type
This file is used to set the error type value. The error type value
is defined in "available_error_type" description.
- error_inject
Write any integer to this file to trigger the error
injection. Before this, please specify all necessary error
parameters.
- flags
Present for kernel version 3.13 and above. Used to specify which
of param{1..4} are valid and should be used by BIOS during injection.
Value is a bitmask as specified in ACPI5.0 spec for the
SET_ERROR_TYPE_WITH_ADDRESS data structure:
Bit 0 - Processor APIC field valid (see param3 below)
Bit 1 - Memory address and mask valid (param1 and param2)
Bit 2 - PCIe (seg,bus,dev,fn) valid (param4 below)
If set to zero, legacy behaviour is used where the type of injection
specifies just one bit set, and param1 is multiplexed.
- param1
This file is used to set the first error parameter value. Effect of
parameter depends on error_type specified. For example, if error
type is memory related type, the param1 should be a valid physical
memory address. [Unless "flag" is set - see above]
- param2
This file is used to set the second error parameter value. Effect of
parameter depends on error_type specified. For example, if error
type is memory related type, the param2 should be a physical memory
address mask. Linux requires page or narrower granularity, say,
0xfffffffffffff000.
- param3
Used when the 0x1 bit is set in "flag" to specify the APIC id
- param4
Used when the 0x4 bit is set in "flag" to specify target PCIe device
- notrigger
The EINJ mechanism is a two step process. First inject the error, then
perform some actions to trigger it. Setting "notrigger" to 1 skips the
trigger phase, which *may* allow the user to cause the error in some other
context by a simple access to the cpu, memory location, or device that is
the target of the error injection. Whether this actually works depends
on what operations the BIOS actually includes in the trigger phase.
BIOS versions based in the ACPI 4.0 specification have limited options
to control where the errors are injected. Your BIOS may support an
extension (enabled with the param_extension=1 module parameter, or
boot command line einj.param_extension=1). This allows the address
and mask for memory injections to be specified by the param1 and
param2 files in apei/einj.
BIOS versions using the ACPI 5.0 specification have more control over
the target of the injection. For processor related errors (type 0x1,
0x2 and 0x4) the APICID of the target should be provided using the
param1 file in apei/einj. For memory errors (type 0x8, 0x10 and 0x20)
the address is set using param1 with a mask in param2 (0x0 is equivalent
to all ones). For PCI express errors (type 0x40, 0x80 and 0x100) the
segment, bus, device and function are specified using param1:
31 24 23 16 15 11 10 8 7 0
+-------------------------------------------------+
| segment | bus | device | function | reserved |
+-------------------------------------------------+
An ACPI 5.0 BIOS may also allow vendor specific errors to be injected.
In this case a file named vendor will contain identifying information
from the BIOS that hopefully will allow an application wishing to use
the vendor specific extension to tell that they are running on a BIOS
that supports it. All vendor extensions have the 0x80000000 bit set in
error_type. A file vendor_flags controls the interpretation of param1
and param2 (1 = PROCESSOR, 2 = MEMORY, 4 = PCI). See your BIOS vendor
documentation for details (and expect changes to this API if vendors
creativity in using this feature expands beyond our expectations).
Example:
# cd /sys/kernel/debug/apei/einj
# cat available_error_type # See which errors can be injected
0x00000002 Processor Uncorrectable non-fatal
0x00000008 Memory Correctable
0x00000010 Memory Uncorrectable non-fatal
# echo 0x12345000 > param1 # Set memory address for injection
# echo 0xfffffffffffff000 > param2 # Mask - anywhere in this page
# echo 0x8 > error_type # Choose correctable memory error
# echo 1 > error_inject # Inject now
For more information about EINJ, please refer to ACPI specification
version 4.0, section 17.5 and ACPI 5.0, section 18.6.

View file

@ -0,0 +1,147 @@
APEI output format
~~~~~~~~~~~~~~~~~~
APEI uses printk as hardware error reporting interface, the output
format is as follow.
<error record> :=
APEI generic hardware error status
severity: <integer>, <severity string>
section: <integer>, severity: <integer>, <severity string>
flags: <integer>
<section flags strings>
fru_id: <uuid string>
fru_text: <string>
section_type: <section type string>
<section data>
<severity string>* := recoverable | fatal | corrected | info
<section flags strings># :=
[primary][, containment warning][, reset][, threshold exceeded]\
[, resource not accessible][, latent error]
<section type string> := generic processor error | memory error | \
PCIe error | unknown, <uuid string>
<section data> :=
<generic processor section data> | <memory section data> | \
<pcie section data> | <null>
<generic processor section data> :=
[processor_type: <integer>, <proc type string>]
[processor_isa: <integer>, <proc isa string>]
[error_type: <integer>
<proc error type strings>]
[operation: <integer>, <proc operation string>]
[flags: <integer>
<proc flags strings>]
[level: <integer>]
[version_info: <integer>]
[processor_id: <integer>]
[target_address: <integer>]
[requestor_id: <integer>]
[responder_id: <integer>]
[IP: <integer>]
<proc type string>* := IA32/X64 | IA64
<proc isa string>* := IA32 | IA64 | X64
<processor error type strings># :=
[cache error][, TLB error][, bus error][, micro-architectural error]
<proc operation string>* := unknown or generic | data read | data write | \
instruction execution
<proc flags strings># :=
[restartable][, precise IP][, overflow][, corrected]
<memory section data> :=
[error_status: <integer>]
[physical_address: <integer>]
[physical_address_mask: <integer>]
[node: <integer>]
[card: <integer>]
[module: <integer>]
[bank: <integer>]
[device: <integer>]
[row: <integer>]
[column: <integer>]
[bit_position: <integer>]
[requestor_id: <integer>]
[responder_id: <integer>]
[target_id: <integer>]
[error_type: <integer>, <mem error type string>]
<mem error type string>* :=
unknown | no error | single-bit ECC | multi-bit ECC | \
single-symbol chipkill ECC | multi-symbol chipkill ECC | master abort | \
target abort | parity error | watchdog timeout | invalid address | \
mirror Broken | memory sparing | scrub corrected error | \
scrub uncorrected error
<pcie section data> :=
[port_type: <integer>, <pcie port type string>]
[version: <integer>.<integer>]
[command: <integer>, status: <integer>]
[device_id: <integer>:<integer>:<integer>.<integer>
slot: <integer>
secondary_bus: <integer>
vendor_id: <integer>, device_id: <integer>
class_code: <integer>]
[serial number: <integer>, <integer>]
[bridge: secondary_status: <integer>, control: <integer>]
[aer_status: <integer>, aer_mask: <integer>
<aer status string>
[aer_uncor_severity: <integer>]
aer_layer=<aer layer string>, aer_agent=<aer agent string>
aer_tlp_header: <integer> <integer> <integer> <integer>]
<pcie port type string>* := PCIe end point | legacy PCI end point | \
unknown | unknown | root port | upstream switch port | \
downstream switch port | PCIe to PCI/PCI-X bridge | \
PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \
root complex event collector
if section severity is fatal or recoverable
<aer status string># :=
unknown | unknown | unknown | unknown | Data Link Protocol | \
unknown | unknown | unknown | unknown | unknown | unknown | unknown | \
Poisoned TLP | Flow Control Protocol | Completion Timeout | \
Completer Abort | Unexpected Completion | Receiver Overflow | \
Malformed TLP | ECRC | Unsupported Request
else
<aer status string># :=
Receiver Error | unknown | unknown | unknown | unknown | unknown | \
Bad TLP | Bad DLLP | RELAY_NUM Rollover | unknown | unknown | unknown | \
Replay Timer Timeout | Advisory Non-Fatal
fi
<aer layer string> :=
Physical Layer | Data Link Layer | Transaction Layer
<aer agent string> :=
Receiver ID | Requester ID | Completer ID | Transmitter ID
Where, [] designate corresponding content is optional
All <field string> description with * has the following format:
field: <integer>, <field string>
Where value of <integer> should be the position of "string" in <field
string> description. Otherwise, <field string> will be "unknown".
All <field strings> description with # has the following format:
field: <integer>
<field strings>
Where each string in <fields strings> corresponding to one set bit of
<integer>. The bit position is the position of "string" in <field
strings> description.
For more detailed explanation of every field, please refer to UEFI
specification version 2.3 or later, section Appendix N: Common
Platform Error Record.

View file

@ -0,0 +1,148 @@
ACPI Debug Output
The ACPI CA, the Linux ACPI core, and some ACPI drivers can generate debug
output. This document describes how to use this facility.
Compile-time configuration
--------------------------
ACPI debug output is globally enabled by CONFIG_ACPI_DEBUG. If this config
option is turned off, the debug messages are not even built into the
kernel.
Boot- and run-time configuration
--------------------------------
When CONFIG_ACPI_DEBUG=y, you can select the component and level of messages
you're interested in. At boot-time, use the acpi.debug_layer and
acpi.debug_level kernel command line options. After boot, you can use the
debug_layer and debug_level files in /sys/module/acpi/parameters/ to control
the debug messages.
debug_layer (component)
-----------------------
The "debug_layer" is a mask that selects components of interest, e.g., a
specific driver or part of the ACPI interpreter. To build the debug_layer
bitmask, look for the "#define _COMPONENT" in an ACPI source file.
You can set the debug_layer mask at boot-time using the acpi.debug_layer
command line argument, and you can change it after boot by writing values
to /sys/module/acpi/parameters/debug_layer.
The possible components are defined in include/acpi/acoutput.h and
include/acpi/acpi_drivers.h. Reading /sys/module/acpi/parameters/debug_layer
shows the supported mask values, currently these:
ACPI_UTILITIES 0x00000001
ACPI_HARDWARE 0x00000002
ACPI_EVENTS 0x00000004
ACPI_TABLES 0x00000008
ACPI_NAMESPACE 0x00000010
ACPI_PARSER 0x00000020
ACPI_DISPATCHER 0x00000040
ACPI_EXECUTER 0x00000080
ACPI_RESOURCES 0x00000100
ACPI_CA_DEBUGGER 0x00000200
ACPI_OS_SERVICES 0x00000400
ACPI_CA_DISASSEMBLER 0x00000800
ACPI_COMPILER 0x00001000
ACPI_TOOLS 0x00002000
ACPI_BUS_COMPONENT 0x00010000
ACPI_AC_COMPONENT 0x00020000
ACPI_BATTERY_COMPONENT 0x00040000
ACPI_BUTTON_COMPONENT 0x00080000
ACPI_SBS_COMPONENT 0x00100000
ACPI_FAN_COMPONENT 0x00200000
ACPI_PCI_COMPONENT 0x00400000
ACPI_POWER_COMPONENT 0x00800000
ACPI_CONTAINER_COMPONENT 0x01000000
ACPI_SYSTEM_COMPONENT 0x02000000
ACPI_THERMAL_COMPONENT 0x04000000
ACPI_MEMORY_DEVICE_COMPONENT 0x08000000
ACPI_VIDEO_COMPONENT 0x10000000
ACPI_PROCESSOR_COMPONENT 0x20000000
debug_level
-----------
The "debug_level" is a mask that selects different types of messages, e.g.,
those related to initialization, method execution, informational messages, etc.
To build debug_level, look at the level specified in an ACPI_DEBUG_PRINT()
statement.
The ACPI interpreter uses several different levels, but the Linux
ACPI core and ACPI drivers generally only use ACPI_LV_INFO.
You can set the debug_level mask at boot-time using the acpi.debug_level
command line argument, and you can change it after boot by writing values
to /sys/module/acpi/parameters/debug_level.
The possible levels are defined in include/acpi/acoutput.h. Reading
/sys/module/acpi/parameters/debug_level shows the supported mask values,
currently these:
ACPI_LV_INIT 0x00000001
ACPI_LV_DEBUG_OBJECT 0x00000002
ACPI_LV_INFO 0x00000004
ACPI_LV_INIT_NAMES 0x00000020
ACPI_LV_PARSE 0x00000040
ACPI_LV_LOAD 0x00000080
ACPI_LV_DISPATCH 0x00000100
ACPI_LV_EXEC 0x00000200
ACPI_LV_NAMES 0x00000400
ACPI_LV_OPREGION 0x00000800
ACPI_LV_BFIELD 0x00001000
ACPI_LV_TABLES 0x00002000
ACPI_LV_VALUES 0x00004000
ACPI_LV_OBJECTS 0x00008000
ACPI_LV_RESOURCES 0x00010000
ACPI_LV_USER_REQUESTS 0x00020000
ACPI_LV_PACKAGE 0x00040000
ACPI_LV_ALLOCATIONS 0x00100000
ACPI_LV_FUNCTIONS 0x00200000
ACPI_LV_OPTIMIZATIONS 0x00400000
ACPI_LV_MUTEX 0x01000000
ACPI_LV_THREADS 0x02000000
ACPI_LV_IO 0x04000000
ACPI_LV_INTERRUPTS 0x08000000
ACPI_LV_AML_DISASSEMBLE 0x10000000
ACPI_LV_VERBOSE_INFO 0x20000000
ACPI_LV_FULL_TABLES 0x40000000
ACPI_LV_EVENTS 0x80000000
Examples
--------
For example, drivers/acpi/bus.c contains this:
#define _COMPONENT ACPI_BUS_COMPONENT
...
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
To turn on this message, set the ACPI_BUS_COMPONENT bit in acpi.debug_layer
and the ACPI_LV_INFO bit in acpi.debug_level. (The ACPI_DEBUG_PRINT
statement uses ACPI_DB_INFO, which is macro based on the ACPI_LV_INFO
definition.)
Enable all AML "Debug" output (stores to the Debug object while interpreting
AML) during boot:
acpi.debug_layer=0xffffffff acpi.debug_level=0x2
Enable PCI and PCI interrupt routing debug messages:
acpi.debug_layer=0x400000 acpi.debug_level=0x4
Enable all ACPI hardware-related messages:
acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
Enable all ACPI_DB_INFO messages after boot:
# echo 0x4 > /sys/module/acpi/parameters/debug_level
Show all valid component values:
# cat /sys/module/acpi/parameters/debug_layer

View file

@ -0,0 +1,7 @@
Linux supports a method of overriding the BIOS DSDT:
CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
When to use this method is described in detail on the
Linux/ACPI home page:
https://01.org/linux-acpi/documentation/overriding-dsdt

View file

@ -0,0 +1,341 @@
ACPI based device enumeration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ACPI 5 introduced a set of new resources (UartTSerialBus, I2cSerialBus,
SpiSerialBus, GpioIo and GpioInt) which can be used in enumerating slave
devices behind serial bus controllers.
In addition we are starting to see peripherals integrated in the
SoC/Chipset to appear only in ACPI namespace. These are typically devices
that are accessed through memory-mapped registers.
In order to support this and re-use the existing drivers as much as
possible we decided to do following:
o Devices that have no bus connector resource are represented as
platform devices.
o Devices behind real busses where there is a connector resource
are represented as struct spi_device or struct i2c_device
(standard UARTs are not busses so there is no struct uart_device).
As both ACPI and Device Tree represent a tree of devices (and their
resources) this implementation follows the Device Tree way as much as
possible.
The ACPI implementation enumerates devices behind busses (platform, SPI and
I2C), creates the physical devices and binds them to their ACPI handle in
the ACPI namespace.
This means that when ACPI_HANDLE(dev) returns non-NULL the device was
enumerated from ACPI namespace. This handle can be used to extract other
device-specific configuration. There is an example of this below.
Platform bus support
~~~~~~~~~~~~~~~~~~~~
Since we are using platform devices to represent devices that are not
connected to any physical bus we only need to implement a platform driver
for the device and add supported ACPI IDs. If this same IP-block is used on
some other non-ACPI platform, the driver might work out of the box or needs
some minor changes.
Adding ACPI support for an existing driver should be pretty
straightforward. Here is the simplest example:
#ifdef CONFIG_ACPI
static struct acpi_device_id mydrv_acpi_match[] = {
/* ACPI IDs here */
{ }
};
MODULE_DEVICE_TABLE(acpi, mydrv_acpi_match);
#endif
static struct platform_driver my_driver = {
...
.driver = {
.acpi_match_table = ACPI_PTR(mydrv_acpi_match),
},
};
If the driver needs to perform more complex initialization like getting and
configuring GPIOs it can get its ACPI handle and extract this information
from ACPI tables.
DMA support
~~~~~~~~~~~
DMA controllers enumerated via ACPI should be registered in the system to
provide generic access to their resources. For example, a driver that would
like to be accessible to slave devices via generic API call
dma_request_slave_channel() must register itself at the end of the probe
function like this:
err = devm_acpi_dma_controller_register(dev, xlate_func, dw);
/* Handle the error if it's not a case of !CONFIG_ACPI */
and implement custom xlate function if needed (usually acpi_dma_simple_xlate()
is enough) which converts the FixedDMA resource provided by struct
acpi_dma_spec into the corresponding DMA channel. A piece of code for that case
could look like:
#ifdef CONFIG_ACPI
struct filter_args {
/* Provide necessary information for the filter_func */
...
};
static bool filter_func(struct dma_chan *chan, void *param)
{
/* Choose the proper channel */
...
}
static struct dma_chan *xlate_func(struct acpi_dma_spec *dma_spec,
struct acpi_dma *adma)
{
dma_cap_mask_t cap;
struct filter_args args;
/* Prepare arguments for filter_func */
...
return dma_request_channel(cap, filter_func, &args);
}
#else
static struct dma_chan *xlate_func(struct acpi_dma_spec *dma_spec,
struct acpi_dma *adma)
{
return NULL;
}
#endif
dma_request_slave_channel() will call xlate_func() for each registered DMA
controller. In the xlate function the proper channel must be chosen based on
information in struct acpi_dma_spec and the properties of the controller
provided by struct acpi_dma.
Clients must call dma_request_slave_channel() with the string parameter that
corresponds to a specific FixedDMA resource. By default "tx" means the first
entry of the FixedDMA resource array, "rx" means the second entry. The table
below shows a layout:
Device (I2C0)
{
...
Method (_CRS, 0, NotSerialized)
{
Name (DBUF, ResourceTemplate ()
{
FixedDMA (0x0018, 0x0004, Width32bit, _Y48)
FixedDMA (0x0019, 0x0005, Width32bit, )
})
...
}
}
So, the FixedDMA with request line 0x0018 is "tx" and next one is "rx" in
this example.
In robust cases the client unfortunately needs to call
acpi_dma_request_slave_chan_by_index() directly and therefore choose the
specific FixedDMA resource by its index.
SPI serial bus support
~~~~~~~~~~~~~~~~~~~~~~
Slave devices behind SPI bus have SpiSerialBus resource attached to them.
This is extracted automatically by the SPI core and the slave devices are
enumerated once spi_register_master() is called by the bus driver.
Here is what the ACPI namespace for a SPI slave might look like:
Device (EEP0)
{
Name (_ADR, 1)
Name (_CID, Package() {
"ATML0025",
"AT25",
})
...
Method (_CRS, 0, NotSerialized)
{
SPISerialBus(1, PolarityLow, FourWireMode, 8,
ControllerInitiated, 1000000, ClockPolarityLow,
ClockPhaseFirst, "\\_SB.PCI0.SPI1",)
}
...
The SPI device drivers only need to add ACPI IDs in a similar way than with
the platform device drivers. Below is an example where we add ACPI support
to at25 SPI eeprom driver (this is meant for the above ACPI snippet):
#ifdef CONFIG_ACPI
static struct acpi_device_id at25_acpi_match[] = {
{ "AT25", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, at25_acpi_match);
#endif
static struct spi_driver at25_driver = {
.driver = {
...
.acpi_match_table = ACPI_PTR(at25_acpi_match),
},
};
Note that this driver actually needs more information like page size of the
eeprom etc. but at the time writing this there is no standard way of
passing those. One idea is to return this in _DSM method like:
Device (EEP0)
{
...
Method (_DSM, 4, NotSerialized)
{
Store (Package (6)
{
"byte-len", 1024,
"addr-mode", 2,
"page-size, 32
}, Local0)
// Check UUIDs etc.
Return (Local0)
}
Then the at25 SPI driver can get this configuration by calling _DSM on its
ACPI handle like:
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_object_list input;
acpi_status status;
/* Fill in the input buffer */
status = acpi_evaluate_object(ACPI_HANDLE(&spi->dev), "_DSM",
&input, &output);
if (ACPI_FAILURE(status))
/* Handle the error */
/* Extract the data here */
kfree(output.pointer);
I2C serial bus support
~~~~~~~~~~~~~~~~~~~~~~
The slaves behind I2C bus controller only need to add the ACPI IDs like
with the platform and SPI drivers. The I2C core automatically enumerates
any slave devices behind the controller device once the adapter is
registered.
Below is an example of how to add ACPI support to the existing mpu3050
input driver:
#ifdef CONFIG_ACPI
static struct acpi_device_id mpu3050_acpi_match[] = {
{ "MPU3050", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, mpu3050_acpi_match);
#endif
static struct i2c_driver mpu3050_i2c_driver = {
.driver = {
.name = "mpu3050",
.owner = THIS_MODULE,
.pm = &mpu3050_pm,
.of_match_table = mpu3050_of_match,
.acpi_match_table ACPI_PTR(mpu3050_acpi_match),
},
.probe = mpu3050_probe,
.remove = mpu3050_remove,
.id_table = mpu3050_ids,
};
GPIO support
~~~~~~~~~~~~
ACPI 5 introduced two new resources to describe GPIO connections: GpioIo
and GpioInt. These resources are used be used to pass GPIO numbers used by
the device to the driver. For example:
Method (_CRS, 0, NotSerialized)
{
Name (SBUF, ResourceTemplate()
{
...
// Used to power on/off the device
GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
0x00, ResourceConsumer,,)
{
// Pin List
0x0055
}
// Interrupt for the device
GpioInt (Edge, ActiveHigh, ExclusiveAndWake, PullNone,
0x0000, "\\_SB.PCI0.GPI0", 0x00, ResourceConsumer,,)
{
// Pin list
0x0058
}
...
}
Return (SBUF)
}
These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
specifies the path to the controller. In order to use these GPIOs in Linux
we need to translate them to the corresponding Linux GPIO descriptors.
There is a standard GPIO API for that and is documented in
Documentation/gpio/.
In the above example we can get the corresponding two GPIO descriptors with
a code like this:
#include <linux/gpio/consumer.h>
...
struct gpio_desc *irq_desc, *power_desc;
irq_desc = gpiod_get_index(dev, NULL, 1);
if (IS_ERR(irq_desc))
/* handle error */
power_desc = gpiod_get_index(dev, NULL, 0);
if (IS_ERR(power_desc))
/* handle error */
/* Now we can use the GPIO descriptors */
There are also devm_* versions of these functions which release the
descriptors once the device is released.
MFD devices
~~~~~~~~~~~
The MFD devices register their children as platform devices. For the child
devices there needs to be an ACPI handle that they can use to reference
parts of the ACPI namespace that relate to them. In the Linux MFD subsystem
we provide two ways:
o The children share the parent ACPI handle.
o The MFD cell can specify the ACPI id of the device.
For the first case, the MFD drivers do not need to do anything. The
resulting child platform device will have its ACPI_COMPANION() set to point
to the parent device.
If the ACPI namespace has a device that we can match using an ACPI id,
the id should be set like:
static struct mfd_cell my_subdevice_cell = {
.name = "my_subdevice",
/* set the resources relative to the parent */
.acpi_pnpid = "XYZ0001",
};
The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
the MFD device and if found, that ACPI companion device is bound to the
resulting child platform device.

View file

@ -0,0 +1,94 @@
Overriding ACPI tables via initrd
=================================
1) Introduction (What is this about)
2) What is this for
3) How does it work
4) References (Where to retrieve userspace tools)
1) What is this about
---------------------
If the ACPI_INITRD_TABLE_OVERRIDE compile option is true, it is possible to
override nearly any ACPI table provided by the BIOS with an instrumented,
modified one.
For a full list of ACPI tables that can be overridden, take a look at
the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/osl.c
All ACPI tables iasl (Intel's ACPI compiler and disassembler) knows should
be overridable, except:
- ACPI_SIG_RSDP (has a signature of 6 bytes)
- ACPI_SIG_FACS (does not have an ordinary ACPI table header)
Both could get implemented as well.
2) What is this for
-------------------
Please keep in mind that this is a debug option.
ACPI tables should not get overridden for productive use.
If BIOS ACPI tables are overridden the kernel will get tainted with the
TAINT_OVERRIDDEN_ACPI_TABLE flag.
Complain to your platform/BIOS vendor if you find a bug which is so sever
that a workaround is not accepted in the Linux kernel.
Still, it can and should be enabled in any kernel, because:
- There is no functional change with not instrumented initrds
- It provides a powerful feature to easily debug and test ACPI BIOS table
compatibility with the Linux kernel.
3) How does it work
-------------------
# Extract the machine's ACPI tables:
cd /tmp
acpidump >acpidump
acpixtract -a acpidump
# Disassemble, modify and recompile them:
iasl -d *.dat
# For example add this statement into a _PRT (PCI Routing Table) function
# of the DSDT:
Store("HELLO WORLD", debug)
iasl -sa dsdt.dsl
# Add the raw ACPI tables to an uncompressed cpio archive.
# They must be put into a /kernel/firmware/acpi directory inside the
# cpio archive.
# The uncompressed cpio archive must be the first.
# Other, typically compressed cpio archives, must be
# concatenated on top of the uncompressed one.
mkdir -p kernel/firmware/acpi
cp dsdt.aml kernel/firmware/acpi
# A maximum of: #define ACPI_OVERRIDE_TABLES 10
# tables are currently allowed (see osl.c):
iasl -sa facp.dsl
iasl -sa ssdt1.dsl
cp facp.aml kernel/firmware/acpi
cp ssdt1.aml kernel/firmware/acpi
# Create the uncompressed cpio archive and concatenate the original initrd
# on top:
find kernel | cpio -H newc --create > /boot/instrumented_initrd
cat /boot/initrd >>/boot/instrumented_initrd
# reboot with increased acpi debug level, e.g. boot params:
acpi.debug_level=0x2 acpi.debug_layer=0xFFFFFFFF
# and check your syslog:
[ 1.268089] ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
[ 1.272091] [ACPI Debug] String [0x0B] "HELLO WORLD"
iasl is able to disassemble and recompile quite a lot different,
also static ACPI tables.
4) Where to retrieve userspace tools
------------------------------------
iasl and acpixtract are part of Intel's ACPICA project:
http://acpica.org/
and should be packaged by distributions (for example in the acpica package
on SUSE).
acpidump can be found in Len Browns pmtools:
ftp://kernel.org/pub/linux/kernel/people/lenb/acpi/utils/pmtools/acpidump
This tool is also part of the acpica package on SUSE.
Alternatively, used ACPI tables can be retrieved via sysfs in latest kernels:
/sys/firmware/acpi/tables

View file

@ -0,0 +1,73 @@
Linux ACPI Custom Control Method How To
=======================================
Written by Zhang Rui <rui.zhang@intel.com>
Linux supports customizing ACPI control methods at runtime.
Users can use this to
1. override an existing method which may not work correctly,
or just for debugging purposes.
2. insert a completely new method in order to create a missing
method such as _OFF, _ON, _STA, _INI, etc.
For these cases, it is far simpler to dynamically install a single
control method rather than override the entire DSDT, because kernel
rebuild/reboot is not needed and test result can be got in minutes.
Note: Only ACPI METHOD can be overridden, any other object types like
"Device", "OperationRegion", are not recognized.
Note: The same ACPI control method can be overridden for many times,
and it's always the latest one that used by Linux/kernel.
Note: To get the ACPI debug object output (Store (AAAA, Debug)),
please run "echo 1 > /sys/module/acpi/parameters/aml_debug_output".
1. override an existing method
a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT,
just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat"
b) disassemble the table by running "iasl -d dsdt.dat".
c) rewrite the ASL code of the method and save it in a new file,
d) package the new file (psr.asl) to an ACPI table format.
Here is an example of a customized \_SB._AC._PSR method,
DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715)
{
External (ACON)
Method (\_SB_.AC._PSR, 0, NotSerialized)
{
Store ("In AC _PSR", Debug)
Return (ACON)
}
}
Note that the full pathname of the method in ACPI namespace
should be used.
And remember to use "External" to declare external objects.
e) assemble the file to generate the AML code of the method.
e.g. "iasl psr.asl" (psr.aml is generated as a result)
f) mount debugfs by "mount -t debugfs none /sys/kernel/debug"
g) override the old method via the debugfs by running
"cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method"
2. insert a new method
This is easier than overriding an existing method.
We just need to create the ASL code of the method we want to
insert and then follow the step c) ~ g) in section 1.
3. undo your changes
The "undo" operation is not supported for a new inserted method
right now, i.e. we can not remove a method currently.
For an overrided method, in order to undo your changes, please
save a copy of the method original ASL code in step c) section 1,
and redo step c) ~ g) to override the method with the original one.
Note: We can use a kernel with multiple custom ACPI method running,
But each individual write to debugfs can implement a SINGLE
method override. i.e. if we want to insert/override multiple
ACPI methods, we need to redo step c) ~ g) for multiple times.
Note: Be aware that root can mis-use this driver to modify arbitrary
memory and gain additional rights, if root's privileges got
restricted (for example if root is not allowed to load additional
modules after boot).

View file

@ -0,0 +1,26 @@
/sys/module/acpi/parameters/:
trace_method_name
The AML method name that the user wants to trace
trace_debug_layer
The temporary debug_layer used when tracing the method.
Using 0xffffffff by default if it is 0.
trace_debug_level
The temporary debug_level used when tracing the method.
Using 0x00ffffff by default if it is 0.
trace_state
The status of the tracing feature.
"enabled" means this feature is enabled
and the AML method is traced every time it's executed.
"1" means this feature is enabled and the AML method
will only be traced during the next execution.
"disabled" means this feature is disabled.
Users can enable/disable this debug tracing feature by
"echo string > /sys/module/acpi/parameters/trace_state".
"string" should be one of "enable", "disable" and "1".

View file

@ -0,0 +1,388 @@
ACPI Device Tree - Representation of ACPI Namespace
Copyright (C) 2013, Intel Corporation
Author: Lv Zheng <lv.zheng@intel.com>
Abstract:
The Linux ACPI subsystem converts ACPI namespace objects into a Linux
device tree under the /sys/devices/LNXSYSTEM:00 and updates it upon
receiving ACPI hotplug notification events. For each device object in this
hierarchy there is a corresponding symbolic link in the
/sys/bus/acpi/devices.
This document illustrates the structure of the ACPI device tree.
Credit:
Thanks for the help from Zhang Rui <rui.zhang@intel.com> and Rafael J.
Wysocki <rafael.j.wysocki@intel.com>.
1. ACPI Definition Blocks
The ACPI firmware sets up RSDP (Root System Description Pointer) in the
system memory address space pointing to the XSDT (Extended System
Description Table). The XSDT always points to the FADT (Fixed ACPI
Description Table) using its first entry, the data within the FADT
includes various fixed-length entries that describe fixed ACPI features
of the hardware. The FADT contains a pointer to the DSDT
(Differentiated System Descripition Table). The XSDT also contains
entries pointing to possibly multiple SSDTs (Secondary System
Description Table).
The DSDT and SSDT data is organized in data structures called definition
blocks that contain definitions of various objects, including ACPI
control methods, encoded in AML (ACPI Machine Language). The data block
of the DSDT along with the contents of SSDTs represents a hierarchical
data structure called the ACPI namespace whose topology reflects the
structure of the underlying hardware platform.
The relationships between ACPI System Definition Tables described above
are illustrated in the following diagram.
+---------+ +-------+ +--------+ +------------------------+
| RSDP | +->| XSDT | +->| FADT | | +-------------------+ |
+---------+ | +-------+ | +--------+ +-|->| DSDT | |
| Pointer | | | Entry |-+ | ...... | | | +-------------------+ |
+---------+ | +-------+ | X_DSDT |--+ | | Definition Blocks | |
| Pointer |-+ | ..... | | ...... | | +-------------------+ |
+---------+ +-------+ +--------+ | +-------------------+ |
| Entry |------------------|->| SSDT | |
+- - - -+ | +-------------------| |
| Entry | - - - - - - - -+ | | Definition Blocks | |
+- - - -+ | | +-------------------+ |
| | +- - - - - - - - - -+ |
+-|->| SSDT | |
| +-------------------+ |
| | Definition Blocks | |
| +- - - - - - - - - -+ |
+------------------------+
|
OSPM Loading |
\|/
+----------------+
| ACPI Namespace |
+----------------+
Figure 1. ACPI Definition Blocks
NOTE: RSDP can also contain a pointer to the RSDT (Root System
Description Table). Platforms provide RSDT to enable
compatibility with ACPI 1.0 operating systems. The OS is expected
to use XSDT, if present.
2. Example ACPI Namespace
All definition blocks are loaded into a single namespace. The namespace
is a hierarchy of objects identified by names and paths.
The following naming conventions apply to object names in the ACPI
namespace:
1. All names are 32 bits long.
2. The first byte of a name must be one of 'A' - 'Z', '_'.
3. Each of the remaining bytes of a name must be one of 'A' - 'Z', '0'
- '9', '_'.
4. Names starting with '_' are reserved by the ACPI specification.
5. The '\' symbol represents the root of the namespace (i.e. names
prepended with '\' are relative to the namespace root).
6. The '^' symbol represents the parent of the current namespace node
(i.e. names prepended with '^' are relative to the parent of the
current namespace node).
The figure below shows an example ACPI namespace.
+------+
| \ | Root
+------+
|
| +------+
+-| _PR | Scope(_PR): the processor namespace
| +------+
| |
| | +------+
| +-| CPU0 | Processor(CPU0): the first processor
| +------+
|
| +------+
+-| _SB | Scope(_SB): the system bus namespace
| +------+
| |
| | +------+
| +-| LID0 | Device(LID0); the lid device
| | +------+
| | |
| | | +------+
| | +-| _HID | Name(_HID, "PNP0C0D"): the hardware ID
| | | +------+
| | |
| | | +------+
| | +-| _STA | Method(_STA): the status control method
| | +------+
| |
| | +------+
| +-| PCI0 | Device(PCI0); the PCI root bridge
| +------+
| |
| | +------+
| +-| _HID | Name(_HID, "PNP0A08"): the hardware ID
| | +------+
| |
| | +------+
| +-| _CID | Name(_CID, "PNP0A03"): the compatible ID
| | +------+
| |
| | +------+
| +-| RP03 | Scope(RP03): the PCI0 power scope
| | +------+
| | |
| | | +------+
| | +-| PXP3 | PowerResource(PXP3): the PCI0 power resource
| | +------+
| |
| | +------+
| +-| GFX0 | Device(GFX0): the graphics adapter
| +------+
| |
| | +------+
| +-| _ADR | Name(_ADR, 0x00020000): the PCI bus address
| | +------+
| |
| | +------+
| +-| DD01 | Device(DD01): the LCD output device
| +------+
| |
| | +------+
| +-| _BCL | Method(_BCL): the backlight control method
| +------+
|
| +------+
+-| _TZ | Scope(_TZ): the thermal zone namespace
| +------+
| |
| | +------+
| +-| FN00 | PowerResource(FN00): the FAN0 power resource
| | +------+
| |
| | +------+
| +-| FAN0 | Device(FAN0): the FAN0 cooling device
| | +------+
| | |
| | | +------+
| | +-| _HID | Name(_HID, "PNP0A0B"): the hardware ID
| | +------+
| |
| | +------+
| +-| TZ00 | ThermalZone(TZ00); the FAN thermal zone
| +------+
|
| +------+
+-| _GPE | Scope(_GPE): the GPE namespace
+------+
Figure 2. Example ACPI Namespace
3. Linux ACPI Device Objects
The Linux kernel's core ACPI subsystem creates struct acpi_device
objects for ACPI namespace objects representing devices, power resources
processors, thermal zones. Those objects are exported to user space via
sysfs as directories in the subtree under /sys/devices/LNXSYSTM:00. The
format of their names is <bus_id:instance>, where 'bus_id' refers to the
ACPI namespace representation of the given object and 'instance' is used
for distinguishing different object of the same 'bus_id' (it is
two-digit decimal representation of an unsigned integer).
The value of 'bus_id' depends on the type of the object whose name it is
part of as listed in the table below.
+---+-----------------+-------+----------+
| | Object/Feature | Table | bus_id |
+---+-----------------+-------+----------+
| N | Root | xSDT | LNXSYSTM |
+---+-----------------+-------+----------+
| N | Device | xSDT | _HID |
+---+-----------------+-------+----------+
| N | Processor | xSDT | LNXCPU |
+---+-----------------+-------+----------+
| N | ThermalZone | xSDT | LNXTHERM |
+---+-----------------+-------+----------+
| N | PowerResource | xSDT | LNXPOWER |
+---+-----------------+-------+----------+
| N | Other Devices | xSDT | device |
+---+-----------------+-------+----------+
| F | PWR_BUTTON | FADT | LNXPWRBN |
+---+-----------------+-------+----------+
| F | SLP_BUTTON | FADT | LNXSLPBN |
+---+-----------------+-------+----------+
| M | Video Extension | xSDT | LNXVIDEO |
+---+-----------------+-------+----------+
| M | ATA Controller | xSDT | LNXIOBAY |
+---+-----------------+-------+----------+
| M | Docking Station | xSDT | LNXDOCK |
+---+-----------------+-------+----------+
Table 1. ACPI Namespace Objects Mapping
The following rules apply when creating struct acpi_device objects on
the basis of the contents of ACPI System Description Tables (as
indicated by the letter in the first column and the notation in the
second column of the table above):
N:
The object's source is an ACPI namespace node (as indicated by the
named object's type in the second column). In that case the object's
directory in sysfs will contain the 'path' attribute whose value is
the full path to the node from the namespace root.
F:
The struct acpi_device object is created for a fixed hardware
feature (as indicated by the fixed feature flag's name in the second
column), so its sysfs directory will not contain the 'path'
attribute.
M:
The struct acpi_device object is created for an ACPI namespace node
with specific control methods (as indicated by the ACPI defined
device's type in the second column). The 'path' attribute containing
its namespace path will be present in its sysfs directory. For
example, if the _BCL method is present for an ACPI namespace node, a
struct acpi_device object with LNXVIDEO 'bus_id' will be created for
it.
The third column of the above table indicates which ACPI System
Description Tables contain information used for the creation of the
struct acpi_device objects represented by the given row (xSDT means DSDT
or SSDT).
The forth column of the above table indicates the 'bus_id' generation
rule of the struct acpi_device object:
_HID:
_HID in the last column of the table means that the object's bus_id
is derived from the _HID/_CID identification objects present under
the corresponding ACPI namespace node. The object's sysfs directory
will then contain the 'hid' and 'modalias' attributes that can be
used to retrieve the _HID and _CIDs of that object.
LNXxxxxx:
The 'modalias' attribute is also present for struct acpi_device
objects having bus_id of the "LNXxxxxx" form (pseudo devices), in
which cases it contains the bus_id string itself.
device:
'device' in the last column of the table indicates that the object's
bus_id cannot be determined from _HID/_CID of the corresponding
ACPI namespace node, although that object represents a device (for
example, it may be a PCI device with _ADR defined and without _HID
or _CID). In that case the string 'device' will be used as the
object's bus_id.
4. Linux ACPI Physical Device Glue
ACPI device (i.e. struct acpi_device) objects may be linked to other
objects in the Linux' device hierarchy that represent "physical" devices
(for example, devices on the PCI bus). If that happens, it means that
the ACPI device object is a "companion" of a device otherwise
represented in a different way and is used (1) to provide configuration
information on that device which cannot be obtained by other means and
(2) to do specific things to the device with the help of its ACPI
control methods. One ACPI device object may be linked this way to
multiple "physical" devices.
If an ACPI device object is linked to a "physical" device, its sysfs
directory contains the "physical_node" symbolic link to the sysfs
directory of the target device object. In turn, the target device's
sysfs directory will then contain the "firmware_node" symbolic link to
the sysfs directory of the companion ACPI device object.
The linking mechanism relies on device identification provided by the
ACPI namespace. For example, if there's an ACPI namespace object
representing a PCI device (i.e. a device object under an ACPI namespace
object representing a PCI bridge) whose _ADR returns 0x00020000 and the
bus number of the parent PCI bridge is 0, the sysfs directory
representing the struct acpi_device object created for that ACPI
namespace object will contain the 'physical_node' symbolic link to the
/sys/devices/pci0000:00/0000:00:02:0/ sysfs directory of the
corresponding PCI device.
The linking mechanism is generally bus-specific. The core of its
implementation is located in the drivers/acpi/glue.c file, but there are
complementary parts depending on the bus types in question located
elsewhere. For example, the PCI-specific part of it is located in
drivers/pci/pci-acpi.c.
5. Example Linux ACPI Device Tree
The sysfs hierarchy of struct acpi_device objects corresponding to the
example ACPI namespace illustrated in Figure 2 with the addition of
fixed PWR_BUTTON/SLP_BUTTON devices is shown below.
+--------------+---+-----------------+
| LNXSYSTEM:00 | \ | acpi:LNXSYSTEM: |
+--------------+---+-----------------+
|
| +-------------+-----+----------------+
+-| LNXPWRBN:00 | N/A | acpi:LNXPWRBN: |
| +-------------+-----+----------------+
|
| +-------------+-----+----------------+
+-| LNXSLPBN:00 | N/A | acpi:LNXSLPBN: |
| +-------------+-----+----------------+
|
| +-----------+------------+--------------+
+-| LNXCPU:00 | \_PR_.CPU0 | acpi:LNXCPU: |
| +-----------+------------+--------------+
|
| +-------------+-------+----------------+
+-| LNXSYBUS:00 | \_SB_ | acpi:LNXSYBUS: |
| +-------------+-------+----------------+
| |
| | +- - - - - - - +- - - - - - +- - - - - - - -+
| +-| PNP0C0D:00 | \_SB_.LID0 | acpi:PNP0C0D: |
| | +- - - - - - - +- - - - - - +- - - - - - - -+
| |
| | +------------+------------+-----------------------+
| +-| PNP0A08:00 | \_SB_.PCI0 | acpi:PNP0A08:PNP0A03: |
| +------------+------------+-----------------------+
| |
| | +-----------+-----------------+-----+
| +-| device:00 | \_SB_.PCI0.RP03 | N/A |
| | +-----------+-----------------+-----+
| | |
| | | +-------------+----------------------+----------------+
| | +-| LNXPOWER:00 | \_SB_.PCI0.RP03.PXP3 | acpi:LNXPOWER: |
| | +-------------+----------------------+----------------+
| |
| | +-------------+-----------------+----------------+
| +-| LNXVIDEO:00 | \_SB_.PCI0.GFX0 | acpi:LNXVIDEO: |
| +-------------+-----------------+----------------+
| |
| | +-----------+-----------------+-----+
| +-| device:01 | \_SB_.PCI0.DD01 | N/A |
| +-----------+-----------------+-----+
|
| +-------------+-------+----------------+
+-| LNXSYBUS:01 | \_TZ_ | acpi:LNXSYBUS: |
+-------------+-------+----------------+
|
| +-------------+------------+----------------+
+-| LNXPOWER:0a | \_TZ_.FN00 | acpi:LNXPOWER: |
| +-------------+------------+----------------+
|
| +------------+------------+---------------+
+-| PNP0C0B:00 | \_TZ_.FAN0 | acpi:PNP0C0B: |
| +------------+------------+---------------+
|
| +-------------+------------+----------------+
+-| LNXTHERM:00 | \_TZ_.TZ00 | acpi:LNXTHERM: |
+-------------+------------+----------------+
Figure 3. Example Linux ACPI Device Tree
NOTE: Each node is represented as "object/path/modalias", where:
1. 'object' is the name of the object's directory in sysfs.
2. 'path' is the ACPI namespace path of the corresponding
ACPI namespace object, as returned by the object's 'path'
sysfs attribute.
3. 'modalias' is the value of the object's 'modalias' sysfs
attribute (as described earlier in this document).
NOTE: N/A indicates the device object does not have the 'path' or the
'modalias' attribute.

View file

@ -0,0 +1,77 @@
ACPI Scan Handlers
Copyright (C) 2012, Intel Corporation
Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
During system initialization and ACPI-based device hot-add, the ACPI namespace
is scanned in search of device objects that generally represent various pieces
of hardware. This causes a struct acpi_device object to be created and
registered with the driver core for every device object in the ACPI namespace
and the hierarchy of those struct acpi_device objects reflects the namespace
layout (i.e. parent device objects in the namespace are represented by parent
struct acpi_device objects and analogously for their children). Those struct
acpi_device objects are referred to as "device nodes" in what follows, but they
should not be confused with struct device_node objects used by the Device Trees
parsing code (although their role is analogous to the role of those objects).
During ACPI-based device hot-remove device nodes representing pieces of hardware
being removed are unregistered and deleted.
The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
initialization of device nodes, such as retrieving common configuration
information from the device objects represented by them and populating them with
appropriate data, but some of them require additional handling after they have
been registered. For example, if the given device node represents a PCI host
bridge, its registration should cause the PCI bus under that bridge to be
enumerated and PCI devices on that bus to be registered with the driver core.
Similarly, if the device node represents a PCI interrupt link, it is necessary
to configure that link so that the kernel can use it.
Those additional configuration tasks usually depend on the type of the hardware
component represented by the given device node which can be determined on the
basis of the device node's hardware ID (HID). They are performed by objects
called ACPI scan handlers represented by the following structure:
struct acpi_scan_handler {
const struct acpi_device_id *ids;
struct list_head list_node;
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
void (*detach)(struct acpi_device *dev);
};
where ids is the list of IDs of device nodes the given handler is supposed to
take care of, list_node is the hook to the global list of ACPI scan handlers
maintained by the ACPI core and the .attach() and .detach() callbacks are
executed, respectively, after registration of new device nodes and before
unregistration of device nodes the handler attached to previously.
The namespace scanning function, acpi_bus_scan(), first registers all of the
device nodes in the given namespace scope with the driver core. Then, it tries
to match a scan handler against each of them using the ids arrays of the
available scan handlers. If a matching scan handler is found, its .attach()
callback is executed for the given device node. If that callback returns 1,
that means that the handler has claimed the device node and is now responsible
for carrying out any additional configuration tasks related to it. It also will
be responsible for preparing the device node for unregistration in that case.
The device node's handler field is then populated with the address of the scan
handler that has claimed it.
If the .attach() callback returns 0, it means that the device node is not
interesting to the given scan handler and may be matched against the next scan
handler in the list. If it returns a (negative) error code, that means that
the namespace scan should be terminated due to a serious error. The error code
returned should then reflect the type of the error.
The namespace trimming function, acpi_bus_trim(), first executes .detach()
callbacks from the scan handlers of all device nodes in the given namespace
scope (if they have scan handlers). Next, it unregisters all of the device
nodes in that scope.
ACPI scan handlers can be added to the list maintained by the ACPI core with the
help of the acpi_scan_add_handler() function taking a pointer to the new scan
handler as an argument. The order in which scan handlers are added to the list
is the order in which they are matched against device nodes during namespace
scans.
All scan handles must be added to the list before acpi_bus_scan() is run for the
first time and they cannot be removed from it.

View file

@ -0,0 +1,106 @@
ACPI video extensions
~~~~~~~~~~~~~~~~~~~~~
This driver implement the ACPI Extensions For Display Adapters for
integrated graphics devices on motherboard, as specified in ACPI 2.0
Specification, Appendix B, allowing to perform some basic control like
defining the video POST device, retrieving EDID information or to
setup a video output, etc. Note that this is an ref. implementation
only. It may or may not work for your integrated video device.
The ACPI video driver does 3 things regarding backlight control:
1 Export a sysfs interface for user space to control backlight level
If the ACPI table has a video device, and acpi_backlight=vendor kernel
command line is not present, the driver will register a backlight device
and set the required backlight operation structure for it for the sysfs
interface control. For every registered class device, there will be a
directory named acpi_videoX under /sys/class/backlight.
The backlight sysfs interface has a standard definition here:
Documentation/ABI/stable/sysfs-class-backlight.
And what ACPI video driver does is:
actual_brightness: on read, control method _BQC will be evaluated to
get the brightness level the firmware thinks it is at;
bl_power: not implemented, will set the current brightness instead;
brightness: on write, control method _BCM will run to set the requested
brightness level;
max_brightness: Derived from the _BCL package(see below);
type: firmware
Note that ACPI video backlight driver will always use index for
brightness, actual_brightness and max_brightness. So if we have
the following _BCL package:
Method (_BCL, 0, NotSerialized)
{
Return (Package (0x0C)
{
0x64,
0x32,
0x0A,
0x14,
0x1E,
0x28,
0x32,
0x3C,
0x46,
0x50,
0x5A,
0x64
})
}
The first two levels are for when laptop are on AC or on battery and are
not used by Linux currently. The remaining 10 levels are supported levels
that we can choose from. The applicable index values are from 0 (that
corresponds to the 0x0A brightness value) to 9 (that corresponds to the
0x64 brightness value) inclusive. Each of those index values is regarded
as a "brightness level" indicator. Thus from the user space perspective
the range of available brightness levels is from 0 to 9 (max_brightness)
inclusive.
2 Notify user space about hotkey event
There are generally two cases for hotkey event reporting:
i) For some laptops, when user presses the hotkey, a scancode will be
generated and sent to user space through the input device created by
the keyboard driver as a key type input event, with proper remap, the
following key code will appear to user space:
EV_KEY, KEY_BRIGHTNESSUP
EV_KEY, KEY_BRIGHTNESSDOWN
etc.
For this case, ACPI video driver does not need to do anything(actually,
it doesn't even know this happened).
ii) For some laptops, the press of the hotkey will not generate the
scancode, instead, firmware will notify the video device ACPI node
about the event. The event value is defined in the ACPI spec. ACPI
video driver will generate an key type input event according to the
notify value it received and send the event to user space through the
input device it created:
event keycode
0x86 KEY_BRIGHTNESSUP
0x87 KEY_BRIGHTNESSDOWN
etc.
so this would lead to the same effect as case i) now.
Once user space tool receives this event, it can modify the backlight
level through the sysfs interface.
3 Change backlight level in the kernel
This works for machines covered by case ii) in Section 2. Once the driver
received a notification, it will set the backlight level accordingly. This does
not affect the sending of event to user space, they are always sent to user
space regardless of whether or not the video module controls the backlight level
directly. This behaviour can be controlled through the brightness_switch_enabled
module parameter as documented in kernel-parameters.txt. It is recommended to
disable this behaviour once a GUI environment starts up and wants to have full
control of the backlight level.