mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 04:34:08 +08:00
ACPI updates for 5.11-rc1
- Update ACPICA code in the kernel to upstream revision 20201113 with changes as follows: * Add 5 new UUIDs to the known UUID table (Bob Moore). * Remove extreaneous "the" in comments (Colin Ian King). * Add function trace macros to improve debugging (Erik Kaneda). * Fix interpreter memory leak (Erik Kaneda). * Handle "orphan" _REG for GPIO OpRegions (Hans de Goede). - Introduce resource_union() and resource_intersection() helpers and clean up some resource-manipulation code with the help of them (Andy Shevchenko). - Revert problematic commit related to the handling of resources in the ACPI core (Daniel Scally). - Extend the ACPI device enumeration documentation and the gpio-line-names _DSD property documentation, clean up the latter (Flavio Suligoi). - Clean up _DEP handling during device enumeration, modify the list of _DEP exceptions and the handling of it and fix up terminology related to _DEP (Hans de Goede, Rafael Wysocki). - Eliminate in_interrupt() usage from the ACPI EC driver (Sebastian Andrzej Siewior). - Clean up the advance_transaction() routine and related code in the ACPI EC driver (Rafael Wysocki). - Add new backlight quirk for GIGABYTE GB-BXBT-2807 (Jasper St. Pierre). - Make assorted janitorial changes in several ACPI-related pieces of code (Hanjun Guo, Jason Yan, Punit Agrawal). -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAl/Y80sSHHJqd0Byand5 c29ja2kubmV0AAoJEILEb/54YlRxLnsP/0B+6dSTqLp7S1UJbScta1gKnDwyFGAi eA3MqyMfF08DiwWocJoDDjttxo5d+0NV2g9LdcScdwGrKB9ddWuhA6/IT83B7YA8 K4Yie4Gm1StLR+rs+zLJy9GBQE3P/Ya058WJJ+mvaTkn4SlI1qf8ZhOEzlCArWpM 0g9+Y7n16A8/9dTTd8eVf80UrPLOuxPPIZuSsCdZCDEOLGPH+zJive0X0wEqsXvU hiq8DymH2ooIcscYXu3wEKtAfcxUjGhmrK8/M7dJ1j9Mh7JxQsIIcQIQogG2uE53 Gm71E1LkQg3FYzFCYmtSNgOnjMMDfV3r/WH4f49kK1Hajn2erYvEv5kXpF+J+Q6X rXXRk17puszq5/gvrebDFpUou7MmV4smOeXPQIobJuXnc9c48QEBqx8tshuJXsVv 5EzD6tITGl/iLu3bqH5M9G5BjIZYB9kjUPzxJ3ezl9rtJXsiMN21MkM4j3KR1rnW g3JYMuw1hwa9wVNFraMyCOtcfncCPJNzdi9TT3ZzMDLHTKbd0jmpyBKws+dI5G1z y7utKOi65utX6mTtOwhITVbSu7Gura7FRXkxo3K7kG8WViYXhDvB1mLylrpipNDl ZWgX6XMYEtRhSvvTwZM0Wcgs9p2JIgfQvbz1Q9pv5FLbf1nceRMaiiGrJTPiGYZD /maVvuddxEWM =5LZe -----END PGP SIGNATURE----- Merge tag 'acpi-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull ACPI updates from Rafael Wysocki: "These update the ACPICA code in the kernel to upstream revision 20201113, fix and clean up some resources manipulation code, extend the enumeration and gpio-line-names property documentation, clean up the handling of _DEP during device enumeration, add a new backlight DMI quirk, clean up transaction handling in the EC driver and make some assorted janitorial changes. Specifics: - Update ACPICA code in the kernel to upstream revision 20201113 with changes as follows: * Add 5 new UUIDs to the known UUID table (Bob Moore) * Remove extreaneous "the" in comments (Colin Ian King) * Add function trace macros to improve debugging (Erik Kaneda) * Fix interpreter memory leak (Erik Kaneda) * Handle "orphan" _REG for GPIO OpRegions (Hans de Goede) - Introduce resource_union() and resource_intersection() helpers and clean up some resource-manipulation code with the help of them (Andy Shevchenko) - Revert problematic commit related to the handling of resources in the ACPI core (Daniel Scally) - Extend the ACPI device enumeration documentation and the gpio-line-names _DSD property documentation, clean up the latter (Flavio Suligoi) - Clean up _DEP handling during device enumeration, modify the list of _DEP exceptions and the handling of it and fix up terminology related to _DEP (Hans de Goede, Rafael Wysocki) - Eliminate in_interrupt() usage from the ACPI EC driver (Sebastian Andrzej Siewior) - Clean up the advance_transaction() routine and related code in the ACPI EC driver (Rafael Wysocki) - Add new backlight quirk for GIGABYTE GB-BXBT-2807 (Jasper St Pierre) - Make assorted janitorial changes in several ACPI-related pieces of code (Hanjun Guo, Jason Yan, Punit Agrawal)" * tag 'acpi-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (40 commits) ACPI: scan: Fix up _DEP-related terminology with supplier/consumer ACPI: scan: Drop INT3396 from acpi_ignore_dep_ids[] ACPI: video: Add DMI quirk for GIGABYTE GB-BXBT-2807 Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources walks" ACPI: scan: Add PNP0D80 to the _DEP exceptions list ACPI: scan: Call acpi_get_object_info() from acpi_add_single_object() ACPI: scan: Add acpi_info_matches_hids() helper ACPICA: Update version to 20201113 ACPICA: Interpreter: fix memory leak by using existing buffer ACPICA: Add function trace macros to improve debugging ACPICA: Also handle "orphan" _REG methods for GPIO OpRegions ACPICA: Remove extreaneous "the" in comments ACPICA: Add 5 new UUIDs to the known UUID table resource: provide meaningful MODULE_LICENSE() in test suite ASoC: Intel: catpt: Replace open coded variant of resource_intersection() ACPI: processor: Drop duplicate setting of shared_cpu_map ACPI: EC: Clean up status flags checks in advance_transaction() ACPI: EC: Untangle error handling in advance_transaction() ACPI: EC: Simplify error handling in advance_transaction() ACPI: EC: Rename acpi_ec_is_gpe_raised() ...
This commit is contained in:
commit
aab7ce2b09
@ -90,10 +90,10 @@ where
|
||||
References
|
||||
==========
|
||||
|
||||
[1] Device tree. <URL:https://www.devicetree.org>, referenced 2019-02-21.
|
||||
[1] Device tree. https://www.devicetree.org, referenced 2019-02-21.
|
||||
|
||||
[2] Advanced Configuration and Power Interface Specification.
|
||||
<URL:https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf>,
|
||||
https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf,
|
||||
referenced 2019-02-21.
|
||||
|
||||
[3] Documentation/devicetree/bindings/leds/common.txt
|
||||
@ -101,11 +101,11 @@ References
|
||||
[4] Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
[5] Device Properties UUID For _DSD.
|
||||
<URL:https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf>,
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf,
|
||||
referenced 2019-02-21.
|
||||
|
||||
[6] Hierarchical Data Extension UUID For _DSD.
|
||||
<URL:https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf>,
|
||||
https://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf,
|
||||
referenced 2019-02-21.
|
||||
|
||||
[7] Documentation/firmware-guide/acpi/dsd/data-node-references.rst
|
||||
|
@ -461,3 +461,157 @@ Otherwise, the _DSD itself is regarded as invalid and therefore the "compatible"
|
||||
property returned by it is meaningless.
|
||||
|
||||
Refer to :doc:`DSD-properties-rules` for more information.
|
||||
|
||||
PCI hierarchy representation
|
||||
============================
|
||||
|
||||
Sometimes could be useful to enumerate a PCI device, knowing its position on the
|
||||
PCI bus.
|
||||
|
||||
For example, some systems use PCI devices soldered directly on the mother board,
|
||||
in a fixed position (ethernet, Wi-Fi, serial ports, etc.). In this conditions it
|
||||
is possible to refer to these PCI devices knowing their position on the PCI bus
|
||||
topology.
|
||||
|
||||
To identify a PCI device, a complete hierarchical description is required, from
|
||||
the chipset root port to the final device, through all the intermediate
|
||||
bridges/switches of the board.
|
||||
|
||||
For example, let us assume to have a system with a PCIe serial port, an
|
||||
Exar XR17V3521, soldered on the main board. This UART chip also includes
|
||||
16 GPIOs and we want to add the property ``gpio-line-names`` [1] to these pins.
|
||||
In this case, the ``lspci`` output for this component is::
|
||||
|
||||
07:00.0 Serial controller: Exar Corp. XR17V3521 Dual PCIe UART (rev 03)
|
||||
|
||||
The complete ``lspci`` output (manually reduced in length) is::
|
||||
|
||||
00:00.0 Host bridge: Intel Corp... Host Bridge (rev 0d)
|
||||
...
|
||||
00:13.0 PCI bridge: Intel Corp... PCI Express Port A #1 (rev fd)
|
||||
00:13.1 PCI bridge: Intel Corp... PCI Express Port A #2 (rev fd)
|
||||
00:13.2 PCI bridge: Intel Corp... PCI Express Port A #3 (rev fd)
|
||||
00:14.0 PCI bridge: Intel Corp... PCI Express Port B #1 (rev fd)
|
||||
00:14.1 PCI bridge: Intel Corp... PCI Express Port B #2 (rev fd)
|
||||
...
|
||||
05:00.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05)
|
||||
06:01.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05)
|
||||
06:02.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05)
|
||||
06:03.0 PCI bridge: Pericom Semiconductor Device 2404 (rev 05)
|
||||
07:00.0 Serial controller: Exar Corp. XR17V3521 Dual PCIe UART (rev 03) <-- Exar
|
||||
...
|
||||
|
||||
The bus topology is::
|
||||
|
||||
-[0000:00]-+-00.0
|
||||
...
|
||||
+-13.0-[01]----00.0
|
||||
+-13.1-[02]----00.0
|
||||
+-13.2-[03]--
|
||||
+-14.0-[04]----00.0
|
||||
+-14.1-[05-09]----00.0-[06-09]--+-01.0-[07]----00.0 <-- Exar
|
||||
| +-02.0-[08]----00.0
|
||||
| \-03.0-[09]--
|
||||
...
|
||||
\-1f.1
|
||||
|
||||
To describe this Exar device on the PCI bus, we must start from the ACPI name
|
||||
of the chipset bridge (also called "root port") with address::
|
||||
|
||||
Bus: 0 - Device: 14 - Function: 1
|
||||
|
||||
To find this information is necessary disassemble the BIOS ACPI tables, in
|
||||
particular the DSDT (see also [2])::
|
||||
|
||||
mkdir ~/tables/
|
||||
cd ~/tables/
|
||||
acpidump > acpidump
|
||||
acpixtract -a acpidump
|
||||
iasl -e ssdt?.* -d dsdt.dat
|
||||
|
||||
Now, in the dsdt.dsl, we have to search the device whose address is related to
|
||||
0x14 (device) and 0x01 (function). In this case we can find the following
|
||||
device::
|
||||
|
||||
Scope (_SB.PCI0)
|
||||
{
|
||||
... other definitions follow ...
|
||||
Device (RP02)
|
||||
{
|
||||
Method (_ADR, 0, NotSerialized) // _ADR: Address
|
||||
{
|
||||
If ((RPA2 != Zero))
|
||||
{
|
||||
Return (RPA2) /* \RPA2 */
|
||||
}
|
||||
Else
|
||||
{
|
||||
Return (0x00140001)
|
||||
}
|
||||
}
|
||||
... other definitions follow ...
|
||||
|
||||
and the _ADR method [3] returns exactly the device/function couple that
|
||||
we are looking for. With this information and analyzing the above ``lspci``
|
||||
output (both the devices list and the devices tree), we can write the following
|
||||
ACPI description for the Exar PCIe UART, also adding the list of its GPIO line
|
||||
names::
|
||||
|
||||
Scope (_SB.PCI0.RP02)
|
||||
{
|
||||
Device (BRG1) //Bridge
|
||||
{
|
||||
Name (_ADR, 0x0000)
|
||||
|
||||
Device (BRG2) //Bridge
|
||||
{
|
||||
Name (_ADR, 0x00010000)
|
||||
|
||||
Device (EXAR)
|
||||
{
|
||||
Name (_ADR, 0x0000)
|
||||
|
||||
Name (_DSD, Package ()
|
||||
{
|
||||
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
|
||||
Package ()
|
||||
{
|
||||
Package ()
|
||||
{
|
||||
"gpio-line-names",
|
||||
Package ()
|
||||
{
|
||||
"mode_232",
|
||||
"mode_422",
|
||||
"mode_485",
|
||||
"misc_1",
|
||||
"misc_2",
|
||||
"misc_3",
|
||||
"",
|
||||
"",
|
||||
"aux_1",
|
||||
"aux_2",
|
||||
"aux_3",
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The location "_SB.PCI0.RP02" is obtained by the above investigation in the
|
||||
dsdt.dsl table, whereas the device names "BRG1", "BRG2" and "EXAR" are
|
||||
created analyzing the position of the Exar UART in the PCI bus topology.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
[1] Documentation/firmware-guide/acpi/gpio-properties.rst
|
||||
|
||||
[2] Documentation/admin-guide/acpi/initrd_table_override.rst
|
||||
|
||||
[3] ACPI Specifications, Version 6.3 - Paragraph 6.1.1 _ADR Address)
|
||||
https://uefi.org/sites/default/files/resources/ACPI_6_3_May16.pdf,
|
||||
referenced 2020-11-18
|
||||
|
@ -133,7 +133,61 @@ Example::
|
||||
|
||||
- gpio-line-names
|
||||
|
||||
Example::
|
||||
The ``gpio-line-names`` declaration is a list of strings ("names"), which
|
||||
describes each line/pin of a GPIO controller/expander. This list, contained in
|
||||
a package, must be inserted inside the GPIO controller declaration of an ACPI
|
||||
table (typically inside the DSDT). The ``gpio-line-names`` list must respect the
|
||||
following rules (see also the examples):
|
||||
|
||||
- the first name in the list corresponds with the first line/pin of the GPIO
|
||||
controller/expander
|
||||
- the names inside the list must be consecutive (no "holes" are permitted)
|
||||
- the list can be incomplete and can end before the last GPIO line: in
|
||||
other words, it is not mandatory to fill all the GPIO lines
|
||||
- empty names are allowed (two quotation marks ``""`` correspond to an empty
|
||||
name)
|
||||
|
||||
Example of a GPIO controller of 16 lines, with an incomplete list with two
|
||||
empty names::
|
||||
|
||||
Package () {
|
||||
"gpio-line-names",
|
||||
Package () {
|
||||
"pin_0",
|
||||
"pin_1",
|
||||
"",
|
||||
"",
|
||||
"pin_3",
|
||||
"pin_4_push_button",
|
||||
}
|
||||
}
|
||||
|
||||
At runtime, the above declaration produces the following result (using the
|
||||
"libgpiod" tools)::
|
||||
|
||||
root@debian:~# gpioinfo gpiochip4
|
||||
gpiochip4 - 16 lines:
|
||||
line 0: "pin_0" unused input active-high
|
||||
line 1: "pin_1" unused input active-high
|
||||
line 2: unnamed unused input active-high
|
||||
line 3: unnamed unused input active-high
|
||||
line 4: "pin_3" unused input active-high
|
||||
line 5: "pin_4_push_button" unused input active-high
|
||||
line 6: unnamed unused input active-high
|
||||
line 7 unnamed unused input active-high
|
||||
line 8: unnamed unused input active-high
|
||||
line 9: unnamed unused input active-high
|
||||
line 10: unnamed unused input active-high
|
||||
line 11: unnamed unused input active-high
|
||||
line 12: unnamed unused input active-high
|
||||
line 13: unnamed unused input active-high
|
||||
line 14: unnamed unused input active-high
|
||||
line 15: unnamed unused input active-high
|
||||
root@debian:~# gpiofind pin_4_push_button
|
||||
gpiochip4 5
|
||||
root@debian:~#
|
||||
|
||||
Another example::
|
||||
|
||||
Package () {
|
||||
"gpio-line-names",
|
||||
|
@ -117,13 +117,6 @@ static inline bool __acpi_aml_busy(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __acpi_aml_opened(void)
|
||||
{
|
||||
if (acpi_aml_io.flags & ACPI_AML_OPEN)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool __acpi_aml_used(void)
|
||||
{
|
||||
return acpi_aml_io.usages ? true : false;
|
||||
|
@ -151,11 +151,7 @@ void __init acpi_watchdog_init(void)
|
||||
found = false;
|
||||
resource_list_for_each_entry(rentry, &resource_list) {
|
||||
if (rentry->res->flags == res.flags &&
|
||||
resource_overlaps(rentry->res, &res)) {
|
||||
if (res.start < rentry->res->start)
|
||||
rentry->res->start = res.start;
|
||||
if (res.end > rentry->res->end)
|
||||
rentry->res->end = res.end;
|
||||
resource_union(rentry->res, &res, rentry->res)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
/*
|
||||
* Common set of includes for all ACPICA source files.
|
||||
* We put them here because we don't want to duplicate them
|
||||
* in the the source code again and again.
|
||||
* in the source code again and again.
|
||||
*
|
||||
* Note: The order of these include files is important.
|
||||
*/
|
||||
|
@ -21,7 +21,8 @@ extern u8 acpi_gbl_default_address_spaces[];
|
||||
/* Local prototypes */
|
||||
|
||||
static void
|
||||
acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node);
|
||||
acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node,
|
||||
acpi_adr_space_type space_id);
|
||||
|
||||
static acpi_status
|
||||
acpi_ev_reg_run(acpi_handle obj_handle,
|
||||
@ -684,10 +685,12 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
|
||||
ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL,
|
||||
&info, NULL);
|
||||
|
||||
/* Special case for EC: handle "orphan" _REG methods with no region */
|
||||
|
||||
if (space_id == ACPI_ADR_SPACE_EC) {
|
||||
acpi_ev_orphan_ec_reg_method(node);
|
||||
/*
|
||||
* Special case for EC and GPIO: handle "orphan" _REG methods with
|
||||
* no region.
|
||||
*/
|
||||
if (space_id == ACPI_ADR_SPACE_EC || space_id == ACPI_ADR_SPACE_GPIO) {
|
||||
acpi_ev_execute_orphan_reg_method(node, space_id);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
|
||||
@ -760,31 +763,28 @@ acpi_ev_reg_run(acpi_handle obj_handle,
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ev_orphan_ec_reg_method
|
||||
* FUNCTION: acpi_ev_execute_orphan_reg_method
|
||||
*
|
||||
* PARAMETERS: ec_device_node - Namespace node for an EC device
|
||||
* PARAMETERS: device_node - Namespace node for an ACPI device
|
||||
* space_id - The address space ID
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
|
||||
* DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI
|
||||
* device. This is a _REG method that has no corresponding region
|
||||
* within the EC device scope. The orphan _REG method appears to
|
||||
* have been enabled by the description of the ECDT in the ACPI
|
||||
* specification: "The availability of the region space can be
|
||||
* detected by providing a _REG method object underneath the
|
||||
* Embedded Controller device."
|
||||
*
|
||||
* To quickly access the EC device, we use the ec_device_node used
|
||||
* during EC handler installation. Otherwise, we would need to
|
||||
* perform a time consuming namespace walk, executing _HID
|
||||
* methods to find the EC device.
|
||||
* within the device's scope. ACPI tables depending on these
|
||||
* "orphan" _REG methods have been seen for both EC and GPIO
|
||||
* Operation Regions. Presumably the Windows ACPI implementation
|
||||
* always calls the _REG method independent of the presence of
|
||||
* an actual Operation Region with the correct address space ID.
|
||||
*
|
||||
* MUTEX: Assumes the namespace is locked
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
|
||||
acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node,
|
||||
acpi_adr_space_type space_id)
|
||||
{
|
||||
acpi_handle reg_method;
|
||||
struct acpi_namespace_node *next_node;
|
||||
@ -792,9 +792,9 @@ acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
|
||||
struct acpi_object_list args;
|
||||
union acpi_object objects[2];
|
||||
|
||||
ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
|
||||
ACPI_FUNCTION_TRACE(ev_execute_orphan_reg_method);
|
||||
|
||||
if (!ec_device_node) {
|
||||
if (!device_node) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
@ -804,7 +804,7 @@ acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
|
||||
|
||||
/* Get a handle to a _REG method immediately under the EC device */
|
||||
|
||||
status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method);
|
||||
status = acpi_get_handle(device_node, METHOD_NAME__REG, ®_method);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto exit; /* There is no _REG method present */
|
||||
}
|
||||
@ -816,23 +816,23 @@ acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node)
|
||||
* with other space IDs to be present; but the code below will then
|
||||
* execute the _REG method with the embedded_control space_ID argument.
|
||||
*/
|
||||
next_node = acpi_ns_get_next_node(ec_device_node, NULL);
|
||||
next_node = acpi_ns_get_next_node(device_node, NULL);
|
||||
while (next_node) {
|
||||
if ((next_node->type == ACPI_TYPE_REGION) &&
|
||||
(next_node->object) &&
|
||||
(next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
|
||||
(next_node->object->region.space_id == space_id)) {
|
||||
goto exit; /* Do not execute the _REG */
|
||||
}
|
||||
|
||||
next_node = acpi_ns_get_next_node(ec_device_node, next_node);
|
||||
next_node = acpi_ns_get_next_node(device_node, next_node);
|
||||
}
|
||||
|
||||
/* Evaluate the _REG(embedded_control,Connect) method */
|
||||
/* Evaluate the _REG(space_id,Connect) method */
|
||||
|
||||
args.count = 2;
|
||||
args.pointer = objects;
|
||||
objects[0].type = ACPI_TYPE_INTEGER;
|
||||
objects[0].integer.value = ACPI_ADR_SPACE_EC;
|
||||
objects[0].integer.value = space_id;
|
||||
objects[1].type = ACPI_TYPE_INTEGER;
|
||||
objects[1].integer.value = ACPI_REG_CONNECT;
|
||||
|
||||
|
@ -71,11 +71,13 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node,
|
||||
acpi_status status;
|
||||
const union acpi_predefined_info *predefined;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_check_return_value);
|
||||
|
||||
/* If not a predefined name, we cannot validate the return object */
|
||||
|
||||
predefined = info->predefined;
|
||||
if (!predefined) {
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -83,7 +85,7 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node,
|
||||
* validate the return object
|
||||
*/
|
||||
if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) {
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -102,7 +104,7 @@ acpi_ns_check_return_value(struct acpi_namespace_node *node,
|
||||
if (acpi_gbl_disable_auto_repair ||
|
||||
(!predefined->info.expected_btypes) ||
|
||||
(predefined->info.expected_btypes == ACPI_RTYPE_ALL)) {
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -163,7 +165,7 @@ exit:
|
||||
node->flags |= ANOBJ_EVALUATED;
|
||||
}
|
||||
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -59,7 +59,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
u32 count;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_check_package);
|
||||
ACPI_FUNCTION_TRACE(ns_check_package);
|
||||
|
||||
/* The package info for this name is in the next table entry */
|
||||
|
||||
@ -88,14 +88,14 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
*/
|
||||
if (!count) {
|
||||
if (package->ret_info.type == ACPI_PTYPE1_VAR) {
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
|
||||
info->node_flags,
|
||||
"Return Package has no elements (empty)"));
|
||||
|
||||
return (AE_AML_OPERAND_VALUE);
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -152,7 +152,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
package->ret_info.
|
||||
object_type1, i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
elements++;
|
||||
@ -186,7 +186,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
object_type[i],
|
||||
i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
} else {
|
||||
/* These are the optional package elements */
|
||||
@ -198,7 +198,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
tail_object_type,
|
||||
i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
acpi_ns_check_object_type(info, elements,
|
||||
ACPI_RTYPE_INTEGER, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
elements++;
|
||||
@ -234,7 +234,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
acpi_ns_check_object_type(info, elements,
|
||||
ACPI_RTYPE_INTEGER, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -279,7 +279,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
acpi_ns_wrap_with_package(info, return_object,
|
||||
return_object_ptr);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Update locals to point to the new package (of 1 element) */
|
||||
@ -316,7 +316,7 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
package->ret_info.
|
||||
object_type1, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Validate length of the UUID buffer */
|
||||
@ -326,14 +326,14 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
info->full_pathname,
|
||||
info->node_flags,
|
||||
"Invalid length for UUID Buffer"));
|
||||
return (AE_AML_OPERAND_VALUE);
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
status = acpi_ns_check_object_type(info, elements + 1,
|
||||
package->ret_info.
|
||||
object_type2, 0);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
elements += 2;
|
||||
@ -350,10 +350,10 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
|
||||
"Invalid internal return type in table entry: %X",
|
||||
package->ret_info.type));
|
||||
|
||||
return (AE_AML_INTERNAL);
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
package_too_small:
|
||||
|
||||
@ -363,7 +363,7 @@ package_too_small:
|
||||
"Return Package is too small - found %u elements, expected %u",
|
||||
count, expected_count));
|
||||
|
||||
return (AE_AML_OPERAND_VALUE);
|
||||
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -708,6 +708,8 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_check_package_elements);
|
||||
|
||||
/*
|
||||
* Up to two groups of package elements are supported by the data
|
||||
* structure. All elements in each group must be of the same type.
|
||||
@ -717,7 +719,7 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
|
||||
status = acpi_ns_check_object_type(info, this_element,
|
||||
type1, i + start_index);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
this_element++;
|
||||
@ -728,11 +730,11 @@ acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
|
||||
type2,
|
||||
(i + count1 + start_index));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
this_element++;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
@ -155,15 +155,17 @@ acpi_ns_complex_repairs(struct acpi_evaluate_info *info,
|
||||
const struct acpi_repair_info *predefined;
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_complex_repairs);
|
||||
|
||||
/* Check if this name is in the list of repairable names */
|
||||
|
||||
predefined = acpi_ns_match_complex_repair(node);
|
||||
if (!predefined) {
|
||||
return (validate_status);
|
||||
return_ACPI_STATUS(validate_status);
|
||||
}
|
||||
|
||||
status = predefined->repair_function(info, return_object_ptr);
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -344,17 +346,19 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
||||
u16 original_ref_count;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ns_repair_CID);
|
||||
|
||||
/* Check for _CID as a simple string */
|
||||
|
||||
if (return_object->common.type == ACPI_TYPE_STRING) {
|
||||
status = acpi_ns_repair_HID(info, return_object_ptr);
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/* Exit if not a Package */
|
||||
|
||||
if (return_object->common.type != ACPI_TYPE_PACKAGE) {
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/* Examine each element of the _CID package */
|
||||
@ -366,7 +370,7 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
||||
|
||||
status = acpi_ns_repair_HID(info, element_ptr);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
if (original_element != *element_ptr) {
|
||||
@ -380,7 +384,7 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
|
||||
element_ptr++;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -491,16 +495,15 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info,
|
||||
union acpi_operand_object **return_object_ptr)
|
||||
{
|
||||
union acpi_operand_object *return_object = *return_object_ptr;
|
||||
union acpi_operand_object *new_string;
|
||||
char *source;
|
||||
char *dest;
|
||||
char *source;
|
||||
|
||||
ACPI_FUNCTION_NAME(ns_repair_HID);
|
||||
|
||||
/* We only care about string _HID objects (not integers) */
|
||||
|
||||
if (return_object->common.type != ACPI_TYPE_STRING) {
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
if (return_object->string.length == 0) {
|
||||
@ -511,14 +514,7 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info,
|
||||
/* Return AE_OK anyway, let driver handle it */
|
||||
|
||||
info->return_flags |= ACPI_OBJECT_REPAIRED;
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/* It is simplest to always create a new string object */
|
||||
|
||||
new_string = acpi_ut_create_string_object(return_object->string.length);
|
||||
if (!new_string) {
|
||||
return (AE_NO_MEMORY);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -530,7 +526,7 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info,
|
||||
source = return_object->string.pointer;
|
||||
if (*source == '*') {
|
||||
source++;
|
||||
new_string->string.length--;
|
||||
return_object->string.length--;
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
|
||||
"%s: Removed invalid leading asterisk\n",
|
||||
@ -545,13 +541,12 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info,
|
||||
* "NNNN####" where N is an uppercase letter or decimal digit, and
|
||||
* # is a hex digit.
|
||||
*/
|
||||
for (dest = new_string->string.pointer; *source; dest++, source++) {
|
||||
for (dest = return_object->string.pointer; *source; dest++, source++) {
|
||||
*dest = (char)toupper((int)*source);
|
||||
}
|
||||
return_object->string.pointer[return_object->string.length] = 0;
|
||||
|
||||
acpi_ut_remove_reference(return_object);
|
||||
*return_object_ptr = new_string;
|
||||
return (AE_OK);
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -287,7 +287,7 @@ struct apei_res {
|
||||
};
|
||||
|
||||
/* Collect all resources requested, to avoid conflict */
|
||||
struct apei_resources apei_resources_all = {
|
||||
static struct apei_resources apei_resources_all = {
|
||||
.iomem = LIST_HEAD_INIT(apei_resources_all.iomem),
|
||||
.ioport = LIST_HEAD_INIT(apei_resources_all.ioport),
|
||||
};
|
||||
|
@ -169,7 +169,7 @@ struct acpi_ec_query {
|
||||
};
|
||||
|
||||
static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
|
||||
static void advance_transaction(struct acpi_ec *ec);
|
||||
static void advance_transaction(struct acpi_ec *ec, bool interrupt);
|
||||
static void acpi_ec_event_handler(struct work_struct *work);
|
||||
static void acpi_ec_event_processor(struct work_struct *work);
|
||||
|
||||
@ -335,12 +335,12 @@ static const char *acpi_ec_cmd_string(u8 cmd)
|
||||
* GPE Registers
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
static inline bool acpi_ec_is_gpe_raised(struct acpi_ec *ec)
|
||||
static inline bool acpi_ec_gpe_status_set(struct acpi_ec *ec)
|
||||
{
|
||||
acpi_event_status gpe_status = 0;
|
||||
|
||||
(void)acpi_get_gpe_status(NULL, ec->gpe, &gpe_status);
|
||||
return (gpe_status & ACPI_EVENT_FLAG_STATUS_SET) ? true : false;
|
||||
return !!(gpe_status & ACPI_EVENT_FLAG_STATUS_SET);
|
||||
}
|
||||
|
||||
static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open)
|
||||
@ -351,14 +351,14 @@ static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open)
|
||||
BUG_ON(ec->reference_count < 1);
|
||||
acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
|
||||
}
|
||||
if (acpi_ec_is_gpe_raised(ec)) {
|
||||
if (acpi_ec_gpe_status_set(ec)) {
|
||||
/*
|
||||
* On some platforms, EN=1 writes cannot trigger GPE. So
|
||||
* software need to manually trigger a pseudo GPE event on
|
||||
* EN=1 writes.
|
||||
*/
|
||||
ec_dbg_raw("Polling quirk");
|
||||
advance_transaction(ec);
|
||||
advance_transaction(ec, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,23 +372,6 @@ static inline void acpi_ec_disable_gpe(struct acpi_ec *ec, bool close)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void acpi_ec_clear_gpe(struct acpi_ec *ec)
|
||||
{
|
||||
/*
|
||||
* GPE STS is a W1C register, which means:
|
||||
* 1. Software can clear it without worrying about clearing other
|
||||
* GPEs' STS bits when the hardware sets them in parallel.
|
||||
* 2. As long as software can ensure only clearing it when it is
|
||||
* set, hardware won't set it in parallel.
|
||||
* So software can clear GPE in any contexts.
|
||||
* Warning: do not move the check into advance_transaction() as the
|
||||
* EC commands will be sent without GPE raised.
|
||||
*/
|
||||
if (!acpi_ec_is_gpe_raised(ec))
|
||||
return;
|
||||
acpi_clear_gpe(NULL, ec->gpe);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* Transaction Management
|
||||
* -------------------------------------------------------------------------- */
|
||||
@ -488,7 +471,7 @@ static inline void __acpi_ec_enable_event(struct acpi_ec *ec)
|
||||
* Unconditionally invoke this once after enabling the event
|
||||
* handling mechanism to detect the pending events.
|
||||
*/
|
||||
advance_transaction(ec);
|
||||
advance_transaction(ec, false);
|
||||
}
|
||||
|
||||
static inline void __acpi_ec_disable_event(struct acpi_ec *ec)
|
||||
@ -632,24 +615,41 @@ static inline void ec_transaction_transition(struct acpi_ec *ec, unsigned long f
|
||||
}
|
||||
}
|
||||
|
||||
static void advance_transaction(struct acpi_ec *ec)
|
||||
static void acpi_ec_spurious_interrupt(struct acpi_ec *ec, struct transaction *t)
|
||||
{
|
||||
struct transaction *t;
|
||||
u8 status;
|
||||
bool wakeup = false;
|
||||
if (t->irq_count < ec_storm_threshold)
|
||||
++t->irq_count;
|
||||
|
||||
/* Trigger if the threshold is 0 too. */
|
||||
if (t->irq_count == ec_storm_threshold)
|
||||
acpi_ec_mask_events(ec);
|
||||
}
|
||||
|
||||
static void advance_transaction(struct acpi_ec *ec, bool interrupt)
|
||||
{
|
||||
struct transaction *t = ec->curr;
|
||||
bool wakeup = false;
|
||||
u8 status;
|
||||
|
||||
ec_dbg_stm("%s (%d)", interrupt ? "IRQ" : "TASK", smp_processor_id());
|
||||
|
||||
ec_dbg_stm("%s (%d)", in_interrupt() ? "IRQ" : "TASK",
|
||||
smp_processor_id());
|
||||
/*
|
||||
* By always clearing STS before handling all indications, we can
|
||||
* ensure a hardware STS 0->1 change after this clearing can always
|
||||
* trigger a GPE interrupt.
|
||||
* Clear GPE_STS upfront to allow subsequent hardware GPE_STS 0->1
|
||||
* changes to always trigger a GPE interrupt.
|
||||
*
|
||||
* GPE STS is a W1C register, which means:
|
||||
*
|
||||
* 1. Software can clear it without worrying about clearing the other
|
||||
* GPEs' STS bits when the hardware sets them in parallel.
|
||||
*
|
||||
* 2. As long as software can ensure only clearing it when it is set,
|
||||
* hardware won't set it in parallel.
|
||||
*/
|
||||
if (ec->gpe >= 0)
|
||||
acpi_ec_clear_gpe(ec);
|
||||
if (ec->gpe >= 0 && acpi_ec_gpe_status_set(ec))
|
||||
acpi_clear_gpe(NULL, ec->gpe);
|
||||
|
||||
status = acpi_ec_read_status(ec);
|
||||
t = ec->curr;
|
||||
|
||||
/*
|
||||
* Another IRQ or a guarded polling mode advancement is detected,
|
||||
* the next QR_EC submission is then allowed.
|
||||
@ -661,56 +661,43 @@ static void advance_transaction(struct acpi_ec *ec)
|
||||
clear_bit(EC_FLAGS_QUERY_GUARDING, &ec->flags);
|
||||
acpi_ec_complete_query(ec);
|
||||
}
|
||||
if (!t)
|
||||
goto out;
|
||||
}
|
||||
if (!t)
|
||||
goto err;
|
||||
|
||||
if (t->flags & ACPI_EC_COMMAND_POLL) {
|
||||
if (t->wlen > t->wi) {
|
||||
if ((status & ACPI_EC_FLAG_IBF) == 0)
|
||||
if (!(status & ACPI_EC_FLAG_IBF))
|
||||
acpi_ec_write_data(ec, t->wdata[t->wi++]);
|
||||
else
|
||||
goto err;
|
||||
else if (interrupt && !(status & ACPI_EC_FLAG_SCI))
|
||||
acpi_ec_spurious_interrupt(ec, t);
|
||||
} else if (t->rlen > t->ri) {
|
||||
if ((status & ACPI_EC_FLAG_OBF) == 1) {
|
||||
if (status & ACPI_EC_FLAG_OBF) {
|
||||
t->rdata[t->ri++] = acpi_ec_read_data(ec);
|
||||
if (t->rlen == t->ri) {
|
||||
ec_transaction_transition(ec, ACPI_EC_COMMAND_COMPLETE);
|
||||
wakeup = true;
|
||||
if (t->command == ACPI_EC_COMMAND_QUERY)
|
||||
ec_dbg_evt("Command(%s) completed by hardware",
|
||||
acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
|
||||
wakeup = true;
|
||||
}
|
||||
} else
|
||||
goto err;
|
||||
} else if (t->wlen == t->wi &&
|
||||
(status & ACPI_EC_FLAG_IBF) == 0) {
|
||||
} else if (interrupt && !(status & ACPI_EC_FLAG_SCI)) {
|
||||
acpi_ec_spurious_interrupt(ec, t);
|
||||
}
|
||||
} else if (t->wlen == t->wi && !(status & ACPI_EC_FLAG_IBF)) {
|
||||
ec_transaction_transition(ec, ACPI_EC_COMMAND_COMPLETE);
|
||||
wakeup = true;
|
||||
}
|
||||
goto out;
|
||||
} else if (!(status & ACPI_EC_FLAG_IBF)) {
|
||||
acpi_ec_write_cmd(ec, t->command);
|
||||
ec_transaction_transition(ec, ACPI_EC_COMMAND_POLL);
|
||||
goto out;
|
||||
}
|
||||
err:
|
||||
/*
|
||||
* If SCI bit is set, then don't think it's a false IRQ
|
||||
* otherwise will take a not handled IRQ as a false one.
|
||||
*/
|
||||
if (!(status & ACPI_EC_FLAG_SCI)) {
|
||||
if (in_interrupt() && t) {
|
||||
if (t->irq_count < ec_storm_threshold)
|
||||
++t->irq_count;
|
||||
/* Allow triggering on 0 threshold */
|
||||
if (t->irq_count == ec_storm_threshold)
|
||||
acpi_ec_mask_events(ec);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (status & ACPI_EC_FLAG_SCI)
|
||||
acpi_ec_submit_query(ec);
|
||||
if (wakeup && in_interrupt())
|
||||
|
||||
if (wakeup && interrupt)
|
||||
wake_up(&ec->wait);
|
||||
}
|
||||
|
||||
@ -767,7 +754,7 @@ static int ec_poll(struct acpi_ec *ec)
|
||||
if (!ec_guard(ec))
|
||||
return 0;
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
advance_transaction(ec);
|
||||
advance_transaction(ec, false);
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
} while (time_before(jiffies, delay));
|
||||
pr_debug("controller reset, restart transaction\n");
|
||||
@ -1216,7 +1203,7 @@ static void acpi_ec_check_event(struct acpi_ec *ec)
|
||||
* taking care of it.
|
||||
*/
|
||||
if (!ec->curr)
|
||||
advance_transaction(ec);
|
||||
advance_transaction(ec, false);
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
}
|
||||
}
|
||||
@ -1259,7 +1246,7 @@ static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ec->lock, flags);
|
||||
advance_transaction(ec);
|
||||
advance_transaction(ec, true);
|
||||
spin_unlock_irqrestore(&ec->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,8 @@ struct acpi_device_bus_id {
|
||||
int acpi_device_add(struct acpi_device *device,
|
||||
void (*release)(struct device *));
|
||||
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
int type, unsigned long long sta);
|
||||
int type, unsigned long long sta,
|
||||
struct acpi_device_info *info);
|
||||
int acpi_device_setup_files(struct acpi_device *dev);
|
||||
void acpi_device_remove_files(struct acpi_device *dev);
|
||||
void acpi_device_add_finalize(struct acpi_device *device);
|
||||
|
@ -722,9 +722,7 @@ static void acpi_pci_root_validate_resources(struct device *dev,
|
||||
* our resources no longer match the ACPI _CRS, but
|
||||
* the kernel resource tree doesn't allow overlaps.
|
||||
*/
|
||||
if (resource_overlaps(res1, res2)) {
|
||||
res2->start = min(res1->start, res2->start);
|
||||
res2->end = max(res1->end, res2->end);
|
||||
if (resource_union(res1, res2, res2)) {
|
||||
dev_info(dev, "host bridge window expanded to %pR; %pR ignored\n",
|
||||
res2, res1);
|
||||
free = true;
|
||||
|
@ -939,7 +939,7 @@ int acpi_add_power_resource(acpi_handle handle)
|
||||
|
||||
device = &resource->device;
|
||||
acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER,
|
||||
ACPI_STA_DEFAULT);
|
||||
ACPI_STA_DEFAULT, NULL);
|
||||
mutex_init(&resource->resource_lock);
|
||||
INIT_LIST_HEAD(&resource->list_node);
|
||||
INIT_LIST_HEAD(&resource->dependents);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <asm/apic.h>
|
||||
#endif
|
||||
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_idle");
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_perflib");
|
||||
@ -616,7 +615,6 @@ int acpi_processor_preregister_performance(
|
||||
continue;
|
||||
|
||||
pr->performance = per_cpu_ptr(performance, i);
|
||||
cpumask_set_cpu(i, pr->performance->shared_cpu_map);
|
||||
pdomain = &(pr->performance->domain_info);
|
||||
if (acpi_processor_get_psd(pr->handle, pdomain)) {
|
||||
retval = -EINVAL;
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
|
||||
/* If a passive cooling situation is detected, primarily CPUfreq is used, as it
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#define PREFIX "ACPI: "
|
||||
|
||||
#define ACPI_PROCESSOR_CLASS "processor"
|
||||
#define _COMPONENT ACPI_PROCESSOR_COMPONENT
|
||||
ACPI_MODULE_NAME("processor_throttling");
|
||||
|
||||
|
@ -534,7 +534,7 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
|
||||
ret = c->preproc(ares, c->preproc_data);
|
||||
if (ret < 0) {
|
||||
c->error = ret;
|
||||
return AE_CTRL_TERMINATE;
|
||||
return AE_ABORT_METHOD;
|
||||
} else if (ret > 0) {
|
||||
return AE_OK;
|
||||
}
|
||||
|
@ -711,26 +711,4 @@ static struct acpi_driver acpi_sbs_driver = {
|
||||
},
|
||||
.drv.pm = &acpi_sbs_pm,
|
||||
};
|
||||
|
||||
static int __init acpi_sbs_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (acpi_disabled)
|
||||
return -ENODEV;
|
||||
|
||||
result = acpi_bus_register_driver(&acpi_sbs_driver);
|
||||
if (result < 0)
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit acpi_sbs_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&acpi_sbs_driver);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(acpi_sbs_init);
|
||||
module_exit(acpi_sbs_exit);
|
||||
module_acpi_driver(acpi_sbs_driver);
|
||||
|
@ -51,8 +51,8 @@ static u64 spcr_uart_addr;
|
||||
|
||||
struct acpi_dep_data {
|
||||
struct list_head node;
|
||||
acpi_handle master;
|
||||
acpi_handle slave;
|
||||
acpi_handle supplier;
|
||||
acpi_handle consumer;
|
||||
};
|
||||
|
||||
void acpi_scan_lock_acquire(void)
|
||||
@ -719,6 +719,42 @@ int acpi_device_add(struct acpi_device *device,
|
||||
/* --------------------------------------------------------------------------
|
||||
Device Enumeration
|
||||
-------------------------------------------------------------------------- */
|
||||
static bool acpi_info_matches_ids(struct acpi_device_info *info,
|
||||
const char * const ids[])
|
||||
{
|
||||
struct acpi_pnp_device_id_list *cid_list = NULL;
|
||||
int i;
|
||||
|
||||
if (!(info->valid & ACPI_VALID_HID))
|
||||
return false;
|
||||
|
||||
if (info->valid & ACPI_VALID_CID)
|
||||
cid_list = &info->compatible_id_list;
|
||||
|
||||
for (i = 0; ids[i]; i++) {
|
||||
int j;
|
||||
|
||||
if (!strcmp(info->hardware_id.string, ids[i]))
|
||||
return true;
|
||||
|
||||
if (!cid_list)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < cid_list->count; j++) {
|
||||
if (!strcmp(cid_list->ids[j].string, ids[i]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* List of HIDs for which we ignore matching ACPI devices, when checking _DEP lists. */
|
||||
static const char * const acpi_ignore_dep_ids[] = {
|
||||
"PNP0D80", /* Windows-compatible System Power Management Controller */
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
|
||||
{
|
||||
struct acpi_device *device = NULL;
|
||||
@ -1236,10 +1272,8 @@ static bool acpi_object_is_system_bus(acpi_handle handle)
|
||||
}
|
||||
|
||||
static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
|
||||
int device_type)
|
||||
int device_type, struct acpi_device_info *info)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_pnp_device_id_list *cid_list;
|
||||
int i;
|
||||
|
||||
@ -1250,8 +1284,7 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
|
||||
break;
|
||||
}
|
||||
|
||||
status = acpi_get_object_info(handle, &info);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (!info) {
|
||||
pr_err(PREFIX "%s: Error reading device info\n",
|
||||
__func__);
|
||||
return;
|
||||
@ -1276,8 +1309,6 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp,
|
||||
if (info->valid & ACPI_VALID_CLS)
|
||||
acpi_add_id(pnp, info->class_code.string);
|
||||
|
||||
kfree(info);
|
||||
|
||||
/*
|
||||
* Some devices don't reliably have _HIDs & _CIDs, so add
|
||||
* synthetic HIDs to make sure drivers can find them.
|
||||
@ -1583,7 +1614,8 @@ static bool acpi_device_enumeration_by_parent(struct acpi_device *device)
|
||||
}
|
||||
|
||||
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
int type, unsigned long long sta)
|
||||
int type, unsigned long long sta,
|
||||
struct acpi_device_info *info)
|
||||
{
|
||||
INIT_LIST_HEAD(&device->pnp.ids);
|
||||
device->device_type = type;
|
||||
@ -1592,7 +1624,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
|
||||
fwnode_init(&device->fwnode, &acpi_device_fwnode_ops);
|
||||
acpi_set_device_status(device, sta);
|
||||
acpi_device_get_busid(device);
|
||||
acpi_set_pnp_ids(handle, &device->pnp, type);
|
||||
acpi_set_pnp_ids(handle, &device->pnp, type, info);
|
||||
acpi_init_properties(device);
|
||||
acpi_bus_get_flags(device);
|
||||
device->flags.match_driver = false;
|
||||
@ -1620,14 +1652,20 @@ static int acpi_add_single_object(struct acpi_device **child,
|
||||
int result;
|
||||
struct acpi_device *device;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_device_info *info = NULL;
|
||||
|
||||
if (handle != ACPI_ROOT_OBJECT && type == ACPI_BUS_TYPE_DEVICE)
|
||||
acpi_get_object_info(handle, &info);
|
||||
|
||||
device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
|
||||
if (!device) {
|
||||
printk(KERN_ERR PREFIX "Memory allocation error\n");
|
||||
kfree(info);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
acpi_init_device_object(device, handle, type, sta);
|
||||
acpi_init_device_object(device, handle, type, sta, info);
|
||||
kfree(info);
|
||||
/*
|
||||
* For ACPI_BUS_TYPE_DEVICE getting the status is delayed till here so
|
||||
* that we can call acpi_bus_get_status() and use its quirk handling.
|
||||
@ -1833,13 +1871,7 @@ static void acpi_device_dep_initialize(struct acpi_device *adev)
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip the dependency of Windows System Power
|
||||
* Management Controller
|
||||
*/
|
||||
skip = info->valid & ACPI_VALID_HID &&
|
||||
!strcmp(info->hardware_id.string, "INT3396");
|
||||
|
||||
skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
|
||||
kfree(info);
|
||||
|
||||
if (skip)
|
||||
@ -1849,8 +1881,8 @@ static void acpi_device_dep_initialize(struct acpi_device *adev)
|
||||
if (!dep)
|
||||
return;
|
||||
|
||||
dep->master = dep_devices.handles[i];
|
||||
dep->slave = adev->handle;
|
||||
dep->supplier = dep_devices.handles[i];
|
||||
dep->consumer = adev->handle;
|
||||
adev->dep_unmet++;
|
||||
|
||||
mutex_lock(&acpi_dep_list_lock);
|
||||
@ -2026,8 +2058,8 @@ void acpi_walk_dep_device_list(acpi_handle handle)
|
||||
|
||||
mutex_lock(&acpi_dep_list_lock);
|
||||
list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) {
|
||||
if (dep->master == handle) {
|
||||
acpi_bus_get_device(dep->slave, &adev);
|
||||
if (dep->supplier == handle) {
|
||||
acpi_bus_get_device(dep->consumer, &adev);
|
||||
if (!adev)
|
||||
continue;
|
||||
|
||||
|
@ -40,6 +40,4 @@ static struct acpi_driver acpi_tiny_power_button_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
module_driver(acpi_tiny_power_button_driver,
|
||||
acpi_bus_register_driver,
|
||||
acpi_bus_unregister_driver);
|
||||
module_acpi_driver(acpi_tiny_power_button_driver);
|
||||
|
@ -140,6 +140,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
.callback = video_detect_force_vendor,
|
||||
.ident = "GIGABYTE GB-BXBT-2807",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Sony VPCEH3U1E",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
|
||||
|
@ -64,14 +64,14 @@
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* ACPI PCI Interrupt Link (pci_link.c) */
|
||||
/* ACPI PCI Interrupt Link */
|
||||
|
||||
int acpi_irq_penalty_init(void);
|
||||
int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
|
||||
int *polarity, char **name);
|
||||
int acpi_pci_link_free_irq(acpi_handle handle);
|
||||
|
||||
/* ACPI PCI Device Binding (pci_bind.c) */
|
||||
/* ACPI PCI Device Binding */
|
||||
|
||||
struct pci_bus;
|
||||
|
||||
@ -94,14 +94,6 @@ void pci_acpi_crs_quirks(void);
|
||||
static inline void pci_acpi_crs_quirks(void) { }
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Processor
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
#define ACPI_PROCESSOR_LIMIT_NONE 0x00
|
||||
#define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01
|
||||
#define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
Dock Station
|
||||
-------------------------------------------------------------------------- */
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
/* Current ACPICA subsystem version in YYYYMMDD format */
|
||||
|
||||
#define ACPI_CA_VERSION 0x20200925
|
||||
#define ACPI_CA_VERSION 0x20201113
|
||||
|
||||
#include <acpi/acconfig.h>
|
||||
#include <acpi/actypes.h>
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
/* NVDIMM - NFIT table */
|
||||
|
||||
#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
|
||||
#define UUID_VOLATILE_MEMORY "7305944f-fdda-44e3-b16c-3f22d252e5d0"
|
||||
#define UUID_PERSISTENT_MEMORY "66f0d379-b4f3-4074-ac43-0d3318b78cdb"
|
||||
#define UUID_CONTROL_REGION "92f701f6-13b4-405d-910b-299367e8234c"
|
||||
@ -47,6 +48,10 @@
|
||||
#define UUID_VOLATILE_VIRTUAL_CD "3d5abd30-4175-87ce-6d64-d2ade523c4bb"
|
||||
#define UUID_PERSISTENT_VIRTUAL_DISK "5cea02c9-4d07-69d3-269f-4496fbe096f9"
|
||||
#define UUID_PERSISTENT_VIRTUAL_CD "08018188-42cd-bb48-100f-5387d53ded3d"
|
||||
#define UUID_NFIT_DIMM_N_MSFT "1ee68b36-d4bd-4a1a-9a16-4f8e53d46e05"
|
||||
#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6"
|
||||
#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e"
|
||||
#define UUID_NFIT_DIMM_N_HYPERV "5746c5f2-a9a2-4264-ad0e-e4ddc9e09e80"
|
||||
|
||||
/* Processor Properties (ACPI 6.2) */
|
||||
|
||||
|
@ -10,9 +10,10 @@
|
||||
#define _LINUX_IOPORT_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/types.h>
|
||||
/*
|
||||
* Resources are tree-like, allowing
|
||||
* nesting etc..
|
||||
@ -229,6 +230,31 @@ static inline bool resource_contains(struct resource *r1, struct resource *r2)
|
||||
return r1->start <= r2->start && r1->end >= r2->end;
|
||||
}
|
||||
|
||||
/* True if any part of r1 overlaps r2 */
|
||||
static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
|
||||
{
|
||||
return r1->start <= r2->end && r1->end >= r2->start;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
resource_intersection(struct resource *r1, struct resource *r2, struct resource *r)
|
||||
{
|
||||
if (!resource_overlaps(r1, r2))
|
||||
return false;
|
||||
r->start = max(r1->start, r2->start);
|
||||
r->end = min(r1->end, r2->end);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
resource_union(struct resource *r1, struct resource *r2, struct resource *r)
|
||||
{
|
||||
if (!resource_overlaps(r1, r2))
|
||||
return false;
|
||||
r->start = min(r1->start, r2->start);
|
||||
r->end = max(r1->end, r2->end);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Convenience shorthand with allocation */
|
||||
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)
|
||||
@ -296,12 +322,6 @@ extern int
|
||||
walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end,
|
||||
void *arg, int (*func)(struct resource *, void *));
|
||||
|
||||
/* True if any part of r1 overlaps r2 */
|
||||
static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
|
||||
{
|
||||
return (r1->start <= r2->end && r1->end >= r2->start);
|
||||
}
|
||||
|
||||
struct resource *devm_request_free_mem_region(struct device *dev,
|
||||
struct resource *base, unsigned long size);
|
||||
struct resource *request_free_mem_region(struct resource *base,
|
||||
|
@ -122,6 +122,7 @@ obj-$(CONFIG_HAS_IOMEM) += iomem.o
|
||||
obj-$(CONFIG_RSEQ) += rseq.o
|
||||
obj-$(CONFIG_WATCH_QUEUE) += watch_queue.o
|
||||
|
||||
obj-$(CONFIG_RESOURCE_KUNIT_TEST) += resource_kunit.o
|
||||
obj-$(CONFIG_SYSCTL_KUNIT_TEST) += sysctl-test.o
|
||||
|
||||
CFLAGS_stackleak.o += $(DISABLE_STACKLEAK_PLUGIN)
|
||||
|
@ -557,13 +557,13 @@ int region_intersects(resource_size_t start, size_t size, unsigned long flags,
|
||||
}
|
||||
read_unlock(&resource_lock);
|
||||
|
||||
if (type == 0)
|
||||
return REGION_DISJOINT;
|
||||
|
||||
if (other == 0)
|
||||
return type ? REGION_INTERSECTS : REGION_DISJOINT;
|
||||
return REGION_INTERSECTS;
|
||||
|
||||
if (type)
|
||||
return REGION_MIXED;
|
||||
|
||||
return REGION_DISJOINT;
|
||||
return REGION_MIXED;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(region_intersects);
|
||||
|
||||
|
152
kernel/resource_kunit.c
Normal file
152
kernel/resource_kunit.c
Normal file
@ -0,0 +1,152 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Test cases for API provided by resource.c and ioport.h
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
#define R0_START 0x0000
|
||||
#define R0_END 0xffff
|
||||
#define R1_START 0x1234
|
||||
#define R1_END 0x2345
|
||||
#define R2_START 0x4567
|
||||
#define R2_END 0x5678
|
||||
#define R3_START 0x6789
|
||||
#define R3_END 0x789a
|
||||
#define R4_START 0x2000
|
||||
#define R4_END 0x7000
|
||||
|
||||
static struct resource r0 = { .start = R0_START, .end = R0_END };
|
||||
static struct resource r1 = { .start = R1_START, .end = R1_END };
|
||||
static struct resource r2 = { .start = R2_START, .end = R2_END };
|
||||
static struct resource r3 = { .start = R3_START, .end = R3_END };
|
||||
static struct resource r4 = { .start = R4_START, .end = R4_END };
|
||||
|
||||
struct result {
|
||||
struct resource *r1;
|
||||
struct resource *r2;
|
||||
struct resource r;
|
||||
bool ret;
|
||||
};
|
||||
|
||||
static struct result results_for_union[] = {
|
||||
{
|
||||
.r1 = &r1, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r3, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r4, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r1, .ret = false,
|
||||
}, {
|
||||
.r1 = &r3, .r2 = &r1, .ret = false,
|
||||
}, {
|
||||
.r1 = &r4, .r2 = &r1, .r.start = R1_START, .r.end = R4_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r3, .ret = false,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r4, .r.start = R4_START, .r.end = R4_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r3, .r2 = &r4, .r.start = R4_START, .r.end = R3_END, .ret = true,
|
||||
},
|
||||
};
|
||||
|
||||
static struct result results_for_intersection[] = {
|
||||
{
|
||||
.r1 = &r1, .r2 = &r0, .r.start = R1_START, .r.end = R1_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r0, .r.start = R2_START, .r.end = R2_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r3, .r2 = &r0, .r.start = R3_START, .r.end = R3_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r4, .r2 = &r0, .r.start = R4_START, .r.end = R4_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r1, .ret = false,
|
||||
}, {
|
||||
.r1 = &r3, .r2 = &r1, .ret = false,
|
||||
}, {
|
||||
.r1 = &r4, .r2 = &r1, .r.start = R4_START, .r.end = R1_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r3, .ret = false,
|
||||
}, {
|
||||
.r1 = &r2, .r2 = &r4, .r.start = R2_START, .r.end = R2_END, .ret = true,
|
||||
}, {
|
||||
.r1 = &r3, .r2 = &r4, .r.start = R3_START, .r.end = R4_END, .ret = true,
|
||||
},
|
||||
};
|
||||
|
||||
static void resource_do_test(struct kunit *test, bool ret, struct resource *r,
|
||||
bool exp_ret, struct resource *exp_r,
|
||||
struct resource *r1, struct resource *r2)
|
||||
{
|
||||
KUNIT_EXPECT_EQ_MSG(test, ret, exp_ret, "Resources %pR %pR", r1, r2);
|
||||
KUNIT_EXPECT_EQ_MSG(test, r->start, exp_r->start, "Start elements are not equal");
|
||||
KUNIT_EXPECT_EQ_MSG(test, r->end, exp_r->end, "End elements are not equal");
|
||||
}
|
||||
|
||||
static void resource_do_union_test(struct kunit *test, struct result *r)
|
||||
{
|
||||
struct resource result;
|
||||
bool ret;
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
ret = resource_union(r->r1, r->r2, &result);
|
||||
resource_do_test(test, ret, &result, r->ret, &r->r, r->r1, r->r2);
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
ret = resource_union(r->r2, r->r1, &result);
|
||||
resource_do_test(test, ret, &result, r->ret, &r->r, r->r2, r->r1);
|
||||
}
|
||||
|
||||
static void resource_test_union(struct kunit *test)
|
||||
{
|
||||
struct result *r = results_for_union;
|
||||
unsigned int i = 0;
|
||||
|
||||
do {
|
||||
resource_do_union_test(test, &r[i]);
|
||||
} while (++i < ARRAY_SIZE(results_for_union));
|
||||
}
|
||||
|
||||
static void resource_do_intersection_test(struct kunit *test, struct result *r)
|
||||
{
|
||||
struct resource result;
|
||||
bool ret;
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
ret = resource_intersection(r->r1, r->r2, &result);
|
||||
resource_do_test(test, ret, &result, r->ret, &r->r, r->r1, r->r2);
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
ret = resource_intersection(r->r2, r->r1, &result);
|
||||
resource_do_test(test, ret, &result, r->ret, &r->r, r->r2, r->r1);
|
||||
}
|
||||
|
||||
static void resource_test_intersection(struct kunit *test)
|
||||
{
|
||||
struct result *r = results_for_intersection;
|
||||
unsigned int i = 0;
|
||||
|
||||
do {
|
||||
resource_do_intersection_test(test, &r[i]);
|
||||
} while (++i < ARRAY_SIZE(results_for_intersection));
|
||||
}
|
||||
|
||||
static struct kunit_case resource_test_cases[] = {
|
||||
KUNIT_CASE(resource_test_union),
|
||||
KUNIT_CASE(resource_test_intersection),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite resource_test_suite = {
|
||||
.name = "resource",
|
||||
.test_cases = resource_test_cases,
|
||||
};
|
||||
kunit_test_suite(resource_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
@ -2257,6 +2257,17 @@ config BITFIELD_KUNIT
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config RESOURCE_KUNIT_TEST
|
||||
tristate "KUnit test for resource API"
|
||||
depends on KUNIT
|
||||
help
|
||||
This builds the resource API unit test.
|
||||
Tests the logic of API provided by resource.c and ioport.h.
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config SYSCTL_KUNIT_TEST
|
||||
tristate "KUnit test for sysctl" if !KUNIT_ALL_TESTS
|
||||
depends on KUNIT
|
||||
|
@ -22,17 +22,6 @@ void catpt_sram_free(struct resource *sram);
|
||||
struct resource *
|
||||
catpt_request_region(struct resource *root, resource_size_t size);
|
||||
|
||||
static inline bool catpt_resource_overlapping(struct resource *r1,
|
||||
struct resource *r2,
|
||||
struct resource *ret)
|
||||
{
|
||||
if (!resource_overlaps(r1, r2))
|
||||
return false;
|
||||
ret->start = max(r1->start, r2->start);
|
||||
ret->end = min(r1->end, r2->end);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct catpt_ipc_msg {
|
||||
union {
|
||||
u32 header;
|
||||
|
@ -267,7 +267,7 @@ static int catpt_restore_fwimage(struct catpt_dev *cdev,
|
||||
r2.start = off;
|
||||
r2.end = r2.start + info->size - 1;
|
||||
|
||||
if (!catpt_resource_overlapping(&r2, &r1, &common))
|
||||
if (!resource_intersection(&r2, &r1, &common))
|
||||
continue;
|
||||
/* calculate start offset of common data area */
|
||||
off = common.start - r1.start;
|
||||
|
Loading…
Reference in New Issue
Block a user