mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
Merge branches 'acpi-init', 'acpi-pnp', 'acpi-scan', 'acpi-proc' and 'acpi-doc'
* acpi-init: ACPI / init: Switch over platform to the ACPI mode later * acpi-pnp: ACPI / PNP: Avoid conflicting resource reservations * acpi-scan: ACPI / scan: constify ACPI device ids ACPI / property: Define a symbol for PRP0001 ACPI / property: Refine consistency check for PRP0001 * acpi-proc: ACPI / proc: make ACPI_PROCFS_POWER X86 only * acpi-doc: ACPI: Constify ACPI device IDs in documentation ACPI / enumeration: Document the rules regarding the PRP0001 device ID ACPI: fix kernel-parameters ordering in Documentation
This commit is contained in:
commit
3a5cf05adf
@ -42,7 +42,7 @@ 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[] = {
|
||||
static const struct acpi_device_id mydrv_acpi_match[] = {
|
||||
/* ACPI IDs here */
|
||||
{ }
|
||||
};
|
||||
@ -166,7 +166,7 @@ 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[] = {
|
||||
static const struct acpi_device_id at25_acpi_match[] = {
|
||||
{ "AT25", 0 },
|
||||
{ },
|
||||
};
|
||||
@ -230,7 +230,7 @@ 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[] = {
|
||||
static const struct acpi_device_id mpu3050_acpi_match[] = {
|
||||
{ "MPU3050", 0 },
|
||||
{ },
|
||||
};
|
||||
@ -359,3 +359,54 @@ the id should be set like:
|
||||
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.
|
||||
|
||||
Device Tree namespace link device ID
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The Device Tree protocol uses device indentification based on the "compatible"
|
||||
property whose value is a string or an array of strings recognized as device
|
||||
identifiers by drivers and the driver core. The set of all those strings may be
|
||||
regarded as a device indentification namespace analogous to the ACPI/PNP device
|
||||
ID namespace. Consequently, in principle it should not be necessary to allocate
|
||||
a new (and arguably redundant) ACPI/PNP device ID for a devices with an existing
|
||||
identification string in the Device Tree (DT) namespace, especially if that ID
|
||||
is only needed to indicate that a given device is compatible with another one,
|
||||
presumably having a matching driver in the kernel already.
|
||||
|
||||
In ACPI, the device identification object called _CID (Compatible ID) is used to
|
||||
list the IDs of devices the given one is compatible with, but those IDs must
|
||||
belong to one of the namespaces prescribed by the ACPI specification (see
|
||||
Section 6.1.2 of ACPI 6.0 for details) and the DT namespace is not one of them.
|
||||
Moreover, the specification mandates that either a _HID or an _ADR identificaion
|
||||
object be present for all ACPI objects representing devices (Section 6.1 of ACPI
|
||||
6.0). For non-enumerable bus types that object must be _HID and its value must
|
||||
be a device ID from one of the namespaces prescribed by the specification too.
|
||||
|
||||
The special DT namespace link device ID, PRP0001, provides a means to use the
|
||||
existing DT-compatible device identification in ACPI and to satisfy the above
|
||||
requirements following from the ACPI specification at the same time. Namely,
|
||||
if PRP0001 is returned by _HID, the ACPI subsystem will look for the
|
||||
"compatible" property in the device object's _DSD and will use the value of that
|
||||
property to identify the corresponding device in analogy with the original DT
|
||||
device identification algorithm. If the "compatible" property is not present
|
||||
or its value is not valid, the device will not be enumerated by the ACPI
|
||||
subsystem. Otherwise, it will be enumerated automatically as a platform device
|
||||
(except when an I2C or SPI link from the device to its parent is present, in
|
||||
which case the ACPI core will leave the device enumeration to the parent's
|
||||
driver) and the identification strings from the "compatible" property value will
|
||||
be used to find a driver for the device along with the device IDs listed by _CID
|
||||
(if present).
|
||||
|
||||
Analogously, if PRP0001 is present in the list of device IDs returned by _CID,
|
||||
the identification strings listed by the "compatible" property value (if present
|
||||
and valid) will be used to look for a driver matching the device, but in that
|
||||
case their relative priority with respect to the other device IDs listed by
|
||||
_HID and _CID depends on the position of PRP0001 in the _CID return package.
|
||||
Specifically, the device IDs returned by _HID and preceding PRP0001 in the _CID
|
||||
return package will be checked first. Also in that case the bus type the device
|
||||
will be enumerated to depends on the device ID returned by _HID.
|
||||
|
||||
It is valid to define device objects with a _HID returning PRP0001 and without
|
||||
the "compatible" property in the _DSD or a _CID as long as one of their
|
||||
ancestors provides a _DSD with a valid "compatible" property. Such device
|
||||
objects are then simply regarded as additional "blocks" providing hierarchical
|
||||
configuration information to the driver of the composite ancestor device.
|
||||
|
@ -179,11 +179,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
|
||||
See also Documentation/power/runtime_pm.txt, pci=noacpi
|
||||
|
||||
acpi_rsdp= [ACPI,EFI,KEXEC]
|
||||
Pass the RSDP address to the kernel, mostly used
|
||||
on machines running EFI runtime service to boot the
|
||||
second kernel for kdump.
|
||||
|
||||
acpi_apic_instance= [ACPI, IOAPIC]
|
||||
Format: <int>
|
||||
2: use 2nd APIC table, if available
|
||||
@ -197,6 +192,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
(e.g. thinkpad_acpi, sony_acpi, etc.) instead
|
||||
of the ACPI video.ko driver.
|
||||
|
||||
acpica_no_return_repair [HW, ACPI]
|
||||
Disable AML predefined validation mechanism
|
||||
This mechanism can repair the evaluation result to make
|
||||
the return objects more ACPI specification compliant.
|
||||
This option is useful for developers to identify the
|
||||
root cause of an AML interpreter issue when the issue
|
||||
has something to do with the repair mechanism.
|
||||
|
||||
acpi.debug_layer= [HW,ACPI,ACPI_DEBUG]
|
||||
acpi.debug_level= [HW,ACPI,ACPI_DEBUG]
|
||||
Format: <int>
|
||||
@ -225,6 +228,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
unusable. The "log_buf_len" parameter may be useful
|
||||
if you need to capture more output.
|
||||
|
||||
acpi_enforce_resources= [ACPI]
|
||||
{ strict | lax | no }
|
||||
Check for resource conflicts between native drivers
|
||||
and ACPI OperationRegions (SystemIO and SystemMemory
|
||||
only). IO ports and memory declared in ACPI might be
|
||||
used by the ACPI subsystem in arbitrary AML code and
|
||||
can interfere with legacy drivers.
|
||||
strict (default): access to resources claimed by ACPI
|
||||
is denied; legacy drivers trying to access reserved
|
||||
resources will fail to bind to device using them.
|
||||
lax: access to resources claimed by ACPI is allowed;
|
||||
legacy drivers trying to access reserved resources
|
||||
will bind successfully but a warning message is logged.
|
||||
no: ACPI OperationRegions are not marked as reserved,
|
||||
no further checks are performed.
|
||||
|
||||
acpi_force_table_verification [HW,ACPI]
|
||||
Enable table checksum verification during early stage.
|
||||
By default, this is disabled due to x86 early mapping
|
||||
@ -253,6 +272,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
This feature is enabled by default.
|
||||
This option allows to turn off the feature.
|
||||
|
||||
acpi_no_memhotplug [ACPI] Disable memory hotplug. Useful for kdump
|
||||
kernels.
|
||||
|
||||
acpi_no_static_ssdt [HW,ACPI]
|
||||
Disable installation of static SSDTs at early boot time
|
||||
By default, SSDTs contained in the RSDT/XSDT will be
|
||||
@ -263,13 +285,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
dynamic table installation which will install SSDT
|
||||
tables to /sys/firmware/acpi/tables/dynamic.
|
||||
|
||||
acpica_no_return_repair [HW, ACPI]
|
||||
Disable AML predefined validation mechanism
|
||||
This mechanism can repair the evaluation result to make
|
||||
the return objects more ACPI specification compliant.
|
||||
This option is useful for developers to identify the
|
||||
root cause of an AML interpreter issue when the issue
|
||||
has something to do with the repair mechanism.
|
||||
acpi_rsdp= [ACPI,EFI,KEXEC]
|
||||
Pass the RSDP address to the kernel, mostly used
|
||||
on machines running EFI runtime service to boot the
|
||||
second kernel for kdump.
|
||||
|
||||
acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
|
||||
Format: To spoof as Windows 98: ="Microsoft Windows"
|
||||
@ -365,25 +384,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
Use timer override. For some broken Nvidia NF5 boards
|
||||
that require a timer override, but don't have HPET
|
||||
|
||||
acpi_enforce_resources= [ACPI]
|
||||
{ strict | lax | no }
|
||||
Check for resource conflicts between native drivers
|
||||
and ACPI OperationRegions (SystemIO and SystemMemory
|
||||
only). IO ports and memory declared in ACPI might be
|
||||
used by the ACPI subsystem in arbitrary AML code and
|
||||
can interfere with legacy drivers.
|
||||
strict (default): access to resources claimed by ACPI
|
||||
is denied; legacy drivers trying to access reserved
|
||||
resources will fail to bind to device using them.
|
||||
lax: access to resources claimed by ACPI is allowed;
|
||||
legacy drivers trying to access reserved resources
|
||||
will bind successfully but a warning message is logged.
|
||||
no: ACPI OperationRegions are not marked as reserved,
|
||||
no further checks are performed.
|
||||
|
||||
acpi_no_memhotplug [ACPI] Disable memory hotplug. Useful for kdump
|
||||
kernels.
|
||||
|
||||
add_efi_memmap [EFI; X86] Include EFI memory map in
|
||||
kernel's map of available physical RAM.
|
||||
|
||||
|
@ -62,7 +62,7 @@ config ACPI_SLEEP
|
||||
|
||||
config ACPI_PROCFS_POWER
|
||||
bool "Deprecated power /proc/acpi directories"
|
||||
depends on PROC_FS
|
||||
depends on X86 && PROC_FS
|
||||
help
|
||||
For backwards compatibility, this option allows
|
||||
deprecated power /proc/acpi/ directories to exist, even when
|
||||
|
@ -470,6 +470,16 @@ static int __init acpi_bus_init_irq(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_early_init - Initialize ACPICA and populate the ACPI namespace.
|
||||
*
|
||||
* The ACPI tables are accessible after this, but the handling of events has not
|
||||
* been initialized and the global lock is not available yet, so AML should not
|
||||
* be executed at this point.
|
||||
*
|
||||
* Doing this before switching the EFI runtime services to virtual mode allows
|
||||
* the EfiBootServices memory to be freed slightly earlier on boot.
|
||||
*/
|
||||
void __init acpi_early_init(void)
|
||||
{
|
||||
acpi_status status;
|
||||
@ -533,26 +543,42 @@ void __init acpi_early_init(void)
|
||||
acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi;
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
|
||||
error0:
|
||||
disable_acpi();
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_subsystem_init - Finalize the early initialization of ACPI.
|
||||
*
|
||||
* Switch over the platform to the ACPI mode (if possible), initialize the
|
||||
* handling of ACPI events, install the interrupt and global lock handlers.
|
||||
*
|
||||
* Doing this too early is generally unsafe, but at the same time it needs to be
|
||||
* done before all things that really depend on ACPI. The right spot appears to
|
||||
* be before finalizing the EFI initialization.
|
||||
*/
|
||||
void __init acpi_subsystem_init(void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
if (acpi_disabled)
|
||||
return;
|
||||
|
||||
status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
|
||||
goto error0;
|
||||
disable_acpi();
|
||||
} else {
|
||||
/*
|
||||
* If the system is using ACPI then we can be reasonably
|
||||
* confident that any regulators are managed by the firmware
|
||||
* so tell the regulator core it has everything it needs to
|
||||
* know.
|
||||
*/
|
||||
regulator_has_full_constraints();
|
||||
}
|
||||
|
||||
/*
|
||||
* If the system is using ACPI then we can be reasonably
|
||||
* confident that any regulators are managed by the firmware
|
||||
* so tell the regulator core it has everything it needs to
|
||||
* know.
|
||||
*/
|
||||
regulator_has_full_constraints();
|
||||
|
||||
return;
|
||||
|
||||
error0:
|
||||
disable_acpi();
|
||||
return;
|
||||
}
|
||||
|
||||
static int __init acpi_bus_init(void)
|
||||
|
@ -191,6 +191,8 @@ bool acpi_osi_is_win8(void);
|
||||
/*--------------------------------------------------------------------------
|
||||
Device properties
|
||||
-------------------------------------------------------------------------- */
|
||||
#define ACPI_DT_NAMESPACE_HID "PRP0001"
|
||||
|
||||
void acpi_init_properties(struct acpi_device *adev);
|
||||
void acpi_free_properties(struct acpi_device *adev);
|
||||
|
||||
|
@ -175,11 +175,7 @@ static void __init acpi_request_region (struct acpi_generic_address *gas,
|
||||
if (!addr || !length)
|
||||
return;
|
||||
|
||||
/* Resources are never freed */
|
||||
if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
||||
request_region(addr, length, desc);
|
||||
else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||
request_mem_region(addr, length, desc);
|
||||
acpi_reserve_region(addr, length, gas->space_id, 0, desc);
|
||||
}
|
||||
|
||||
static void __init acpi_reserve_resources(void)
|
||||
|
@ -79,50 +79,51 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
|
||||
static void acpi_init_of_compatible(struct acpi_device *adev)
|
||||
{
|
||||
const union acpi_object *of_compatible;
|
||||
struct acpi_hardware_id *hwid;
|
||||
bool acpi_of = false;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Check if the special PRP0001 ACPI ID is present and in that
|
||||
* case we fill in Device Tree compatible properties for this
|
||||
* device.
|
||||
*/
|
||||
list_for_each_entry(hwid, &adev->pnp.ids, list) {
|
||||
if (!strcmp(hwid->id, "PRP0001")) {
|
||||
acpi_of = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!acpi_of)
|
||||
return;
|
||||
|
||||
ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
|
||||
&of_compatible);
|
||||
if (ret) {
|
||||
ret = acpi_dev_get_property(adev, "compatible",
|
||||
ACPI_TYPE_STRING, &of_compatible);
|
||||
if (ret) {
|
||||
acpi_handle_warn(adev->handle,
|
||||
"PRP0001 requires compatible property\n");
|
||||
if (adev->parent
|
||||
&& adev->parent->flags.of_compatible_ok)
|
||||
goto out;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
adev->data.of_compatible = of_compatible;
|
||||
|
||||
out:
|
||||
adev->flags.of_compatible_ok = 1;
|
||||
}
|
||||
|
||||
void acpi_init_properties(struct acpi_device *adev)
|
||||
{
|
||||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
|
||||
bool acpi_of = false;
|
||||
struct acpi_hardware_id *hwid;
|
||||
const union acpi_object *desc;
|
||||
acpi_status status;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
|
||||
* Device Tree compatible properties for this device.
|
||||
*/
|
||||
list_for_each_entry(hwid, &adev->pnp.ids, list) {
|
||||
if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
|
||||
acpi_of = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
|
||||
ACPI_TYPE_PACKAGE);
|
||||
if (ACPI_FAILURE(status))
|
||||
return;
|
||||
goto out;
|
||||
|
||||
desc = buf.pointer;
|
||||
if (desc->package.count % 2)
|
||||
@ -156,13 +157,20 @@ void acpi_init_properties(struct acpi_device *adev)
|
||||
adev->data.pointer = buf.pointer;
|
||||
adev->data.properties = properties;
|
||||
|
||||
acpi_init_of_compatible(adev);
|
||||
return;
|
||||
if (acpi_of)
|
||||
acpi_init_of_compatible(adev);
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
fail:
|
||||
dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
|
||||
dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n");
|
||||
ACPI_FREE(buf.pointer);
|
||||
|
||||
out:
|
||||
if (acpi_of && !adev->flags.of_compatible_ok)
|
||||
acpi_handle_info(adev->handle,
|
||||
ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
|
||||
}
|
||||
|
||||
void acpi_free_properties(struct acpi_device *adev)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
@ -621,3 +622,162 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
|
||||
return (type & types) ? 0 : 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
|
||||
|
||||
struct reserved_region {
|
||||
struct list_head node;
|
||||
u64 start;
|
||||
u64 end;
|
||||
};
|
||||
|
||||
static LIST_HEAD(reserved_io_regions);
|
||||
static LIST_HEAD(reserved_mem_regions);
|
||||
|
||||
static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags,
|
||||
char *desc)
|
||||
{
|
||||
unsigned int length = end - start + 1;
|
||||
struct resource *res;
|
||||
|
||||
res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ?
|
||||
request_region(start, length, desc) :
|
||||
request_mem_region(start, length, desc);
|
||||
if (!res)
|
||||
return -EIO;
|
||||
|
||||
res->flags &= ~flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_region_before(u64 start, u64 end, u8 space_id,
|
||||
unsigned long flags, char *desc,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct reserved_region *reg;
|
||||
int error;
|
||||
|
||||
reg = kmalloc(sizeof(*reg), GFP_KERNEL);
|
||||
if (!reg)
|
||||
return -ENOMEM;
|
||||
|
||||
error = request_range(start, end, space_id, flags, desc);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
reg->start = start;
|
||||
reg->end = end;
|
||||
list_add_tail(®->node, head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* acpi_reserve_region - Reserve an I/O or memory region as a system resource.
|
||||
* @start: Starting address of the region.
|
||||
* @length: Length of the region.
|
||||
* @space_id: Identifier of address space to reserve the region from.
|
||||
* @flags: Resource flags to clear for the region after requesting it.
|
||||
* @desc: Region description (for messages).
|
||||
*
|
||||
* Reserve an I/O or memory region as a system resource to prevent others from
|
||||
* using it. If the new region overlaps with one of the regions (in the given
|
||||
* address space) already reserved by this routine, only the non-overlapping
|
||||
* parts of it will be reserved.
|
||||
*
|
||||
* Returned is either 0 (success) or a negative error code indicating a resource
|
||||
* reservation problem. It is the code of the first encountered error, but the
|
||||
* routine doesn't abort until it has attempted to request all of the parts of
|
||||
* the new region that don't overlap with other regions reserved previously.
|
||||
*
|
||||
* The resources requested by this routine are never released.
|
||||
*/
|
||||
int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
|
||||
unsigned long flags, char *desc)
|
||||
{
|
||||
struct list_head *regions;
|
||||
struct reserved_region *reg;
|
||||
u64 end = start + length - 1;
|
||||
int ret = 0, error = 0;
|
||||
|
||||
if (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
|
||||
regions = &reserved_io_regions;
|
||||
else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
|
||||
regions = &reserved_mem_regions;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (list_empty(regions))
|
||||
return add_region_before(start, end, space_id, flags, desc, regions);
|
||||
|
||||
list_for_each_entry(reg, regions, node)
|
||||
if (reg->start == end + 1) {
|
||||
/* The new region can be prepended to this one. */
|
||||
ret = request_range(start, end, space_id, flags, desc);
|
||||
if (!ret)
|
||||
reg->start = start;
|
||||
|
||||
return ret;
|
||||
} else if (reg->start > end) {
|
||||
/* No overlap. Add the new region here and get out. */
|
||||
return add_region_before(start, end, space_id, flags,
|
||||
desc, ®->node);
|
||||
} else if (reg->end == start - 1) {
|
||||
goto combine;
|
||||
} else if (reg->end >= start) {
|
||||
goto overlap;
|
||||
}
|
||||
|
||||
/* The new region goes after the last existing one. */
|
||||
return add_region_before(start, end, space_id, flags, desc, regions);
|
||||
|
||||
overlap:
|
||||
/*
|
||||
* The new region overlaps an existing one.
|
||||
*
|
||||
* The head part of the new region immediately preceding the existing
|
||||
* overlapping one can be combined with it right away.
|
||||
*/
|
||||
if (reg->start > start) {
|
||||
error = request_range(start, reg->start - 1, space_id, flags, desc);
|
||||
if (error)
|
||||
ret = error;
|
||||
else
|
||||
reg->start = start;
|
||||
}
|
||||
|
||||
combine:
|
||||
/*
|
||||
* The new region is adjacent to an existing one. If it extends beyond
|
||||
* that region all the way to the next one, it is possible to combine
|
||||
* all three of them.
|
||||
*/
|
||||
while (reg->end < end) {
|
||||
struct reserved_region *next = NULL;
|
||||
u64 a = reg->end + 1, b = end;
|
||||
|
||||
if (!list_is_last(®->node, regions)) {
|
||||
next = list_next_entry(reg, node);
|
||||
if (next->start <= end)
|
||||
b = next->start - 1;
|
||||
}
|
||||
error = request_range(a, b, space_id, flags, desc);
|
||||
if (!error) {
|
||||
if (next && next->start == b + 1) {
|
||||
reg->end = next->end;
|
||||
list_del(&next->node);
|
||||
kfree(next);
|
||||
} else {
|
||||
reg->end = end;
|
||||
break;
|
||||
}
|
||||
} else if (next) {
|
||||
if (!ret)
|
||||
ret = error;
|
||||
|
||||
reg = next;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret ? ret : error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_reserve_region);
|
||||
|
@ -135,12 +135,13 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
struct acpi_hardware_id *id;
|
||||
|
||||
/*
|
||||
* Since we skip PRP0001 from the modalias below, 0 should be returned
|
||||
* if PRP0001 is the only ACPI/PNP ID in the device's list.
|
||||
* Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
|
||||
* be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
|
||||
* device's list.
|
||||
*/
|
||||
count = 0;
|
||||
list_for_each_entry(id, &acpi_dev->pnp.ids, list)
|
||||
if (strcmp(id->id, "PRP0001"))
|
||||
if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
|
||||
count++;
|
||||
|
||||
if (!count)
|
||||
@ -153,7 +154,7 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
size -= len;
|
||||
|
||||
list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
|
||||
if (!strcmp(id->id, "PRP0001"))
|
||||
if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
|
||||
continue;
|
||||
|
||||
count = snprintf(&modalias[len], size, "%s:", id->id);
|
||||
@ -177,7 +178,8 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
* @size: Size of the buffer.
|
||||
*
|
||||
* Expose DT compatible modalias as of:NnameTCcompatible. This function should
|
||||
* only be called for devices having PRP0001 in their list of ACPI/PNP IDs.
|
||||
* only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
|
||||
* ACPI/PNP IDs.
|
||||
*/
|
||||
static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
|
||||
int size)
|
||||
@ -980,9 +982,9 @@ static void acpi_device_remove_files(struct acpi_device *dev)
|
||||
* @adev: ACPI device object to match.
|
||||
* @of_match_table: List of device IDs to match against.
|
||||
*
|
||||
* If @dev has an ACPI companion which has the special PRP0001 device ID in its
|
||||
* list of identifiers and a _DSD object with the "compatible" property, use
|
||||
* that property to match against the given list of identifiers.
|
||||
* If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
|
||||
* identifiers and a _DSD object with the "compatible" property, use that
|
||||
* property to match against the given list of identifiers.
|
||||
*/
|
||||
static bool acpi_of_match_device(struct acpi_device *adev,
|
||||
const struct of_device_id *of_match_table)
|
||||
@ -1038,14 +1040,14 @@ static const struct acpi_device_id *__acpi_match_device(
|
||||
return id;
|
||||
|
||||
/*
|
||||
* Next, check the special "PRP0001" ID and try to match the
|
||||
* Next, check ACPI_DT_NAMESPACE_HID and try to match the
|
||||
* "compatible" property if found.
|
||||
*
|
||||
* The id returned by the below is not valid, but the only
|
||||
* caller passing non-NULL of_ids here is only interested in
|
||||
* whether or not the return value is NULL.
|
||||
*/
|
||||
if (!strcmp("PRP0001", hwid->id)
|
||||
if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
|
||||
&& acpi_of_match_device(device, of_ids))
|
||||
return id;
|
||||
}
|
||||
@ -1671,7 +1673,7 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
|
||||
|
||||
static void acpi_wakeup_gpe_init(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_device_id button_device_ids[] = {
|
||||
static const struct acpi_device_id button_device_ids[] = {
|
||||
{"PNP0C0C", 0},
|
||||
{"PNP0C0D", 0},
|
||||
{"PNP0C0E", 0},
|
||||
@ -2405,7 +2407,7 @@ static void acpi_default_enumeration(struct acpi_device *device)
|
||||
}
|
||||
|
||||
static const struct acpi_device_id generic_device_ids[] = {
|
||||
{"PRP0001", },
|
||||
{ACPI_DT_NAMESPACE_HID, },
|
||||
{"", },
|
||||
};
|
||||
|
||||
@ -2413,8 +2415,8 @@ static int acpi_generic_device_attach(struct acpi_device *adev,
|
||||
const struct acpi_device_id *not_used)
|
||||
{
|
||||
/*
|
||||
* Since PRP0001 is the only ID handled here, the test below can be
|
||||
* unconditional.
|
||||
* Since ACPI_DT_NAMESPACE_HID is the only ID handled here, the test
|
||||
* below can be unconditional.
|
||||
*/
|
||||
if (adev->data.of_compatible)
|
||||
acpi_default_enumeration(adev);
|
||||
|
@ -7,6 +7,7 @@
|
||||
* Bjorn Helgaas <bjorn.helgaas@hp.com>
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/pnp.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
@ -22,25 +23,41 @@ static const struct pnp_device_id pnp_dev_table[] = {
|
||||
{"", 0}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc)
|
||||
{
|
||||
u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY;
|
||||
return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc);
|
||||
}
|
||||
#else
|
||||
static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
res = io ? request_region(start, length, desc) :
|
||||
request_mem_region(start, length, desc);
|
||||
if (res) {
|
||||
res->flags &= ~IORESOURCE_BUSY;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
|
||||
{
|
||||
char *regionid;
|
||||
const char *pnpid = dev_name(&dev->dev);
|
||||
resource_size_t start = r->start, end = r->end;
|
||||
struct resource *res;
|
||||
bool reserved;
|
||||
|
||||
regionid = kmalloc(16, GFP_KERNEL);
|
||||
if (!regionid)
|
||||
return;
|
||||
|
||||
snprintf(regionid, 16, "pnp %s", pnpid);
|
||||
if (port)
|
||||
res = request_region(start, end - start + 1, regionid);
|
||||
else
|
||||
res = request_mem_region(start, end - start + 1, regionid);
|
||||
if (res)
|
||||
res->flags &= ~IORESOURCE_BUSY;
|
||||
else
|
||||
reserved = __reserve_range(start, end - start + 1, !!port, regionid);
|
||||
if (!reserved)
|
||||
kfree(regionid);
|
||||
|
||||
/*
|
||||
@ -49,7 +66,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
|
||||
* have double reservations.
|
||||
*/
|
||||
dev_info(&dev->dev, "%pR %s reserved\n", r,
|
||||
res ? "has been" : "could not be");
|
||||
reserved ? "has been" : "could not be");
|
||||
}
|
||||
|
||||
static void reserve_resources_of_dev(struct pnp_dev *dev)
|
||||
|
@ -208,7 +208,8 @@ struct acpi_device_flags {
|
||||
u32 visited:1;
|
||||
u32 hotplug_notify:1;
|
||||
u32 is_dock_station:1;
|
||||
u32 reserved:23;
|
||||
u32 of_compatible_ok:1;
|
||||
u32 reserved:22;
|
||||
};
|
||||
|
||||
/* File System */
|
||||
|
@ -332,6 +332,9 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
|
||||
|
||||
int acpi_resources_are_enforced(void);
|
||||
|
||||
int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
|
||||
unsigned long flags, char *desc);
|
||||
|
||||
#ifdef CONFIG_HIBERNATION
|
||||
void __init acpi_no_s4_hw_signature(void);
|
||||
#endif
|
||||
@ -440,6 +443,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
|
||||
#define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82
|
||||
|
||||
extern void acpi_early_init(void);
|
||||
extern void acpi_subsystem_init(void);
|
||||
|
||||
extern int acpi_nvs_register(__u64 start, __u64 size);
|
||||
|
||||
@ -494,6 +498,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev)
|
||||
}
|
||||
|
||||
static inline void acpi_early_init(void) { }
|
||||
static inline void acpi_subsystem_init(void) { }
|
||||
|
||||
static inline int early_acpi_boot_init(void)
|
||||
{
|
||||
@ -525,6 +530,13 @@ static inline int acpi_check_region(resource_size_t start, resource_size_t n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int acpi_reserve_region(u64 start, unsigned int length,
|
||||
u8 space_id, unsigned long flags,
|
||||
char *desc)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
struct acpi_table_header;
|
||||
static inline int acpi_table_parse(char *id,
|
||||
int (*handler)(struct acpi_table_header *))
|
||||
|
@ -664,6 +664,7 @@ asmlinkage __visible void __init start_kernel(void)
|
||||
|
||||
check_bugs();
|
||||
|
||||
acpi_subsystem_init();
|
||||
sfi_init_late();
|
||||
|
||||
if (efi_enabled(EFI_RUNTIME_SERVICES)) {
|
||||
|
Loading…
Reference in New Issue
Block a user