aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/enumeration.txt57
-rw-r--r--Documentation/kernel-parameters.txt62
-rw-r--r--drivers/acpi/Kconfig2
-rw-r--r--drivers/acpi/bus.c56
-rw-r--r--drivers/acpi/internal.h2
-rw-r--r--drivers/acpi/osl.c6
-rw-r--r--drivers/acpi/property.c54
-rw-r--r--drivers/acpi/resource.c160
-rw-r--r--drivers/acpi/scan.c30
-rw-r--r--drivers/pnp/system.c35
-rw-r--r--include/acpi/acpi_bus.h3
-rw-r--r--include/linux/acpi.h12
-rw-r--r--init/main.c1
13 files changed, 378 insertions, 102 deletions
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index 15dfce708ebf..b731b292e812 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -42,7 +42,7 @@ Adding ACPI support for an existing driver should be pretty
42straightforward. Here is the simplest example: 42straightforward. Here is the simplest example:
43 43
44 #ifdef CONFIG_ACPI 44 #ifdef CONFIG_ACPI
45 static struct acpi_device_id mydrv_acpi_match[] = { 45 static const struct acpi_device_id mydrv_acpi_match[] = {
46 /* ACPI IDs here */ 46 /* ACPI IDs here */
47 { } 47 { }
48 }; 48 };
@@ -166,7 +166,7 @@ the platform device drivers. Below is an example where we add ACPI support
166to at25 SPI eeprom driver (this is meant for the above ACPI snippet): 166to at25 SPI eeprom driver (this is meant for the above ACPI snippet):
167 167
168 #ifdef CONFIG_ACPI 168 #ifdef CONFIG_ACPI
169 static struct acpi_device_id at25_acpi_match[] = { 169 static const struct acpi_device_id at25_acpi_match[] = {
170 { "AT25", 0 }, 170 { "AT25", 0 },
171 { }, 171 { },
172 }; 172 };
@@ -230,7 +230,7 @@ Below is an example of how to add ACPI support to the existing mpu3050
230input driver: 230input driver:
231 231
232 #ifdef CONFIG_ACPI 232 #ifdef CONFIG_ACPI
233 static struct acpi_device_id mpu3050_acpi_match[] = { 233 static const struct acpi_device_id mpu3050_acpi_match[] = {
234 { "MPU3050", 0 }, 234 { "MPU3050", 0 },
235 { }, 235 { },
236 }; 236 };
@@ -359,3 +359,54 @@ the id should be set like:
359The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under 359The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
360the MFD device and if found, that ACPI companion device is bound to the 360the MFD device and if found, that ACPI companion device is bound to the
361resulting child platform device. 361resulting child platform device.
362
363Device Tree namespace link device ID
364~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
365The Device Tree protocol uses device indentification based on the "compatible"
366property whose value is a string or an array of strings recognized as device
367identifiers by drivers and the driver core. The set of all those strings may be
368regarded as a device indentification namespace analogous to the ACPI/PNP device
369ID namespace. Consequently, in principle it should not be necessary to allocate
370a new (and arguably redundant) ACPI/PNP device ID for a devices with an existing
371identification string in the Device Tree (DT) namespace, especially if that ID
372is only needed to indicate that a given device is compatible with another one,
373presumably having a matching driver in the kernel already.
374
375In ACPI, the device identification object called _CID (Compatible ID) is used to
376list the IDs of devices the given one is compatible with, but those IDs must
377belong to one of the namespaces prescribed by the ACPI specification (see
378Section 6.1.2 of ACPI 6.0 for details) and the DT namespace is not one of them.
379Moreover, the specification mandates that either a _HID or an _ADR identificaion
380object be present for all ACPI objects representing devices (Section 6.1 of ACPI
3816.0). For non-enumerable bus types that object must be _HID and its value must
382be a device ID from one of the namespaces prescribed by the specification too.
383
384The special DT namespace link device ID, PRP0001, provides a means to use the
385existing DT-compatible device identification in ACPI and to satisfy the above
386requirements following from the ACPI specification at the same time. Namely,
387if PRP0001 is returned by _HID, the ACPI subsystem will look for the
388"compatible" property in the device object's _DSD and will use the value of that
389property to identify the corresponding device in analogy with the original DT
390device identification algorithm. If the "compatible" property is not present
391or its value is not valid, the device will not be enumerated by the ACPI
392subsystem. Otherwise, it will be enumerated automatically as a platform device
393(except when an I2C or SPI link from the device to its parent is present, in
394which case the ACPI core will leave the device enumeration to the parent's
395driver) and the identification strings from the "compatible" property value will
396be used to find a driver for the device along with the device IDs listed by _CID
397(if present).
398
399Analogously, if PRP0001 is present in the list of device IDs returned by _CID,
400the identification strings listed by the "compatible" property value (if present
401and valid) will be used to look for a driver matching the device, but in that
402case their relative priority with respect to the other device IDs listed by
403_HID and _CID depends on the position of PRP0001 in the _CID return package.
404Specifically, the device IDs returned by _HID and preceding PRP0001 in the _CID
405return package will be checked first. Also in that case the bus type the device
406will be enumerated to depends on the device ID returned by _HID.
407
408It is valid to define device objects with a _HID returning PRP0001 and without
409the "compatible" property in the _DSD or a _CID as long as one of their
410ancestors provides a _DSD with a valid "compatible" property. Such device
411objects are then simply regarded as additional "blocks" providing hierarchical
412configuration information to the driver of the composite ancestor device.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 6726139bd289..10f879221821 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -179,11 +179,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
179 179
180 See also Documentation/power/runtime_pm.txt, pci=noacpi 180 See also Documentation/power/runtime_pm.txt, pci=noacpi
181 181
182 acpi_rsdp= [ACPI,EFI,KEXEC]
183 Pass the RSDP address to the kernel, mostly used
184 on machines running EFI runtime service to boot the
185 second kernel for kdump.
186
187 acpi_apic_instance= [ACPI, IOAPIC] 182 acpi_apic_instance= [ACPI, IOAPIC]
188 Format: <int> 183 Format: <int>
189 2: use 2nd APIC table, if available 184 2: use 2nd APIC table, if available
@@ -197,6 +192,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
197 (e.g. thinkpad_acpi, sony_acpi, etc.) instead 192 (e.g. thinkpad_acpi, sony_acpi, etc.) instead
198 of the ACPI video.ko driver. 193 of the ACPI video.ko driver.
199 194
195 acpica_no_return_repair [HW, ACPI]
196 Disable AML predefined validation mechanism
197 This mechanism can repair the evaluation result to make
198 the return objects more ACPI specification compliant.
199 This option is useful for developers to identify the
200 root cause of an AML interpreter issue when the issue
201 has something to do with the repair mechanism.
202
200 acpi.debug_layer= [HW,ACPI,ACPI_DEBUG] 203 acpi.debug_layer= [HW,ACPI,ACPI_DEBUG]
201 acpi.debug_level= [HW,ACPI,ACPI_DEBUG] 204 acpi.debug_level= [HW,ACPI,ACPI_DEBUG]
202 Format: <int> 205 Format: <int>
@@ -225,6 +228,22 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
225 unusable. The "log_buf_len" parameter may be useful 228 unusable. The "log_buf_len" parameter may be useful
226 if you need to capture more output. 229 if you need to capture more output.
227 230
231 acpi_enforce_resources= [ACPI]
232 { strict | lax | no }
233 Check for resource conflicts between native drivers
234 and ACPI OperationRegions (SystemIO and SystemMemory
235 only). IO ports and memory declared in ACPI might be
236 used by the ACPI subsystem in arbitrary AML code and
237 can interfere with legacy drivers.
238 strict (default): access to resources claimed by ACPI
239 is denied; legacy drivers trying to access reserved
240 resources will fail to bind to device using them.
241 lax: access to resources claimed by ACPI is allowed;
242 legacy drivers trying to access reserved resources
243 will bind successfully but a warning message is logged.
244 no: ACPI OperationRegions are not marked as reserved,
245 no further checks are performed.
246
228 acpi_force_table_verification [HW,ACPI] 247 acpi_force_table_verification [HW,ACPI]
229 Enable table checksum verification during early stage. 248 Enable table checksum verification during early stage.
230 By default, this is disabled due to x86 early mapping 249 By default, this is disabled due to x86 early mapping
@@ -253,6 +272,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
253 This feature is enabled by default. 272 This feature is enabled by default.
254 This option allows to turn off the feature. 273 This option allows to turn off the feature.
255 274
275 acpi_no_memhotplug [ACPI] Disable memory hotplug. Useful for kdump
276 kernels.
277
256 acpi_no_static_ssdt [HW,ACPI] 278 acpi_no_static_ssdt [HW,ACPI]
257 Disable installation of static SSDTs at early boot time 279 Disable installation of static SSDTs at early boot time
258 By default, SSDTs contained in the RSDT/XSDT will be 280 By default, SSDTs contained in the RSDT/XSDT will be
@@ -263,13 +285,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
263 dynamic table installation which will install SSDT 285 dynamic table installation which will install SSDT
264 tables to /sys/firmware/acpi/tables/dynamic. 286 tables to /sys/firmware/acpi/tables/dynamic.
265 287
266 acpica_no_return_repair [HW, ACPI] 288 acpi_rsdp= [ACPI,EFI,KEXEC]
267 Disable AML predefined validation mechanism 289 Pass the RSDP address to the kernel, mostly used
268 This mechanism can repair the evaluation result to make 290 on machines running EFI runtime service to boot the
269 the return objects more ACPI specification compliant. 291 second kernel for kdump.
270 This option is useful for developers to identify the
271 root cause of an AML interpreter issue when the issue
272 has something to do with the repair mechanism.
273 292
274 acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS 293 acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
275 Format: To spoof as Windows 98: ="Microsoft Windows" 294 Format: To spoof as Windows 98: ="Microsoft Windows"
@@ -365,25 +384,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
365 Use timer override. For some broken Nvidia NF5 boards 384 Use timer override. For some broken Nvidia NF5 boards
366 that require a timer override, but don't have HPET 385 that require a timer override, but don't have HPET
367 386
368 acpi_enforce_resources= [ACPI]
369 { strict | lax | no }
370 Check for resource conflicts between native drivers
371 and ACPI OperationRegions (SystemIO and SystemMemory
372 only). IO ports and memory declared in ACPI might be
373 used by the ACPI subsystem in arbitrary AML code and
374 can interfere with legacy drivers.
375 strict (default): access to resources claimed by ACPI
376 is denied; legacy drivers trying to access reserved
377 resources will fail to bind to device using them.
378 lax: access to resources claimed by ACPI is allowed;
379 legacy drivers trying to access reserved resources
380 will bind successfully but a warning message is logged.
381 no: ACPI OperationRegions are not marked as reserved,
382 no further checks are performed.
383
384 acpi_no_memhotplug [ACPI] Disable memory hotplug. Useful for kdump
385 kernels.
386
387 add_efi_memmap [EFI; X86] Include EFI memory map in 387 add_efi_memmap [EFI; X86] Include EFI memory map in
388 kernel's map of available physical RAM. 388 kernel's map of available physical RAM.
389 389
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb51c6aa..16da18597def 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -62,7 +62,7 @@ config ACPI_SLEEP
62 62
63config ACPI_PROCFS_POWER 63config ACPI_PROCFS_POWER
64 bool "Deprecated power /proc/acpi directories" 64 bool "Deprecated power /proc/acpi directories"
65 depends on PROC_FS 65 depends on X86 && PROC_FS
66 help 66 help
67 For backwards compatibility, this option allows 67 For backwards compatibility, this option allows
68 deprecated power /proc/acpi/ directories to exist, even when 68 deprecated power /proc/acpi/ directories to exist, even when
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index c412fdb28d34..513e7230e3d0 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -470,6 +470,16 @@ static int __init acpi_bus_init_irq(void)
470 return 0; 470 return 0;
471} 471}
472 472
473/**
474 * acpi_early_init - Initialize ACPICA and populate the ACPI namespace.
475 *
476 * The ACPI tables are accessible after this, but the handling of events has not
477 * been initialized and the global lock is not available yet, so AML should not
478 * be executed at this point.
479 *
480 * Doing this before switching the EFI runtime services to virtual mode allows
481 * the EfiBootServices memory to be freed slightly earlier on boot.
482 */
473void __init acpi_early_init(void) 483void __init acpi_early_init(void)
474{ 484{
475 acpi_status status; 485 acpi_status status;
@@ -533,26 +543,42 @@ void __init acpi_early_init(void)
533 acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi; 543 acpi_gbl_FADT.sci_interrupt = acpi_sci_override_gsi;
534 } 544 }
535#endif 545#endif
546 return;
547
548 error0:
549 disable_acpi();
550}
551
552/**
553 * acpi_subsystem_init - Finalize the early initialization of ACPI.
554 *
555 * Switch over the platform to the ACPI mode (if possible), initialize the
556 * handling of ACPI events, install the interrupt and global lock handlers.
557 *
558 * Doing this too early is generally unsafe, but at the same time it needs to be
559 * done before all things that really depend on ACPI. The right spot appears to
560 * be before finalizing the EFI initialization.
561 */
562void __init acpi_subsystem_init(void)
563{
564 acpi_status status;
565
566 if (acpi_disabled)
567 return;
536 568
537 status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE); 569 status = acpi_enable_subsystem(~ACPI_NO_ACPI_ENABLE);
538 if (ACPI_FAILURE(status)) { 570 if (ACPI_FAILURE(status)) {
539 printk(KERN_ERR PREFIX "Unable to enable ACPI\n"); 571 printk(KERN_ERR PREFIX "Unable to enable ACPI\n");
540 goto error0; 572 disable_acpi();
573 } else {
574 /*
575 * If the system is using ACPI then we can be reasonably
576 * confident that any regulators are managed by the firmware
577 * so tell the regulator core it has everything it needs to
578 * know.
579 */
580 regulator_has_full_constraints();
541 } 581 }
542
543 /*
544 * If the system is using ACPI then we can be reasonably
545 * confident that any regulators are managed by the firmware
546 * so tell the regulator core it has everything it needs to
547 * know.
548 */
549 regulator_has_full_constraints();
550
551 return;
552
553 error0:
554 disable_acpi();
555 return;
556} 582}
557 583
558static int __init acpi_bus_init(void) 584static int __init acpi_bus_init(void)
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index ba4a61e964be..d93628c65661 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -191,6 +191,8 @@ bool acpi_osi_is_win8(void);
191/*-------------------------------------------------------------------------- 191/*--------------------------------------------------------------------------
192 Device properties 192 Device properties
193 -------------------------------------------------------------------------- */ 193 -------------------------------------------------------------------------- */
194#define ACPI_DT_NAMESPACE_HID "PRP0001"
195
194void acpi_init_properties(struct acpi_device *adev); 196void acpi_init_properties(struct acpi_device *adev);
195void acpi_free_properties(struct acpi_device *adev); 197void acpi_free_properties(struct acpi_device *adev);
196 198
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 7ccba395c9dd..5226a8b921ae 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -175,11 +175,7 @@ static void __init acpi_request_region (struct acpi_generic_address *gas,
175 if (!addr || !length) 175 if (!addr || !length)
176 return; 176 return;
177 177
178 /* Resources are never freed */ 178 acpi_reserve_region(addr, length, gas->space_id, 0, desc);
179 if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO)
180 request_region(addr, length, desc);
181 else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
182 request_mem_region(addr, length, desc);
183} 179}
184 180
185static void __init acpi_reserve_resources(void) 181static void __init acpi_reserve_resources(void)
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 0d083736e25b..7836e2e980f4 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -79,50 +79,51 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
79static void acpi_init_of_compatible(struct acpi_device *adev) 79static void acpi_init_of_compatible(struct acpi_device *adev)
80{ 80{
81 const union acpi_object *of_compatible; 81 const union acpi_object *of_compatible;
82 struct acpi_hardware_id *hwid;
83 bool acpi_of = false;
84 int ret; 82 int ret;
85 83
86 /*
87 * Check if the special PRP0001 ACPI ID is present and in that
88 * case we fill in Device Tree compatible properties for this
89 * device.
90 */
91 list_for_each_entry(hwid, &adev->pnp.ids, list) {
92 if (!strcmp(hwid->id, "PRP0001")) {
93 acpi_of = true;
94 break;
95 }
96 }
97
98 if (!acpi_of)
99 return;
100
101 ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, 84 ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
102 &of_compatible); 85 &of_compatible);
103 if (ret) { 86 if (ret) {
104 ret = acpi_dev_get_property(adev, "compatible", 87 ret = acpi_dev_get_property(adev, "compatible",
105 ACPI_TYPE_STRING, &of_compatible); 88 ACPI_TYPE_STRING, &of_compatible);
106 if (ret) { 89 if (ret) {
107 acpi_handle_warn(adev->handle, 90 if (adev->parent
108 "PRP0001 requires compatible property\n"); 91 && adev->parent->flags.of_compatible_ok)
92 goto out;
93
109 return; 94 return;
110 } 95 }
111 } 96 }
112 adev->data.of_compatible = of_compatible; 97 adev->data.of_compatible = of_compatible;
98
99 out:
100 adev->flags.of_compatible_ok = 1;
113} 101}
114 102
115void acpi_init_properties(struct acpi_device *adev) 103void acpi_init_properties(struct acpi_device *adev)
116{ 104{
117 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; 105 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
106 bool acpi_of = false;
107 struct acpi_hardware_id *hwid;
118 const union acpi_object *desc; 108 const union acpi_object *desc;
119 acpi_status status; 109 acpi_status status;
120 int i; 110 int i;
121 111
112 /*
113 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
114 * Device Tree compatible properties for this device.
115 */
116 list_for_each_entry(hwid, &adev->pnp.ids, list) {
117 if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
118 acpi_of = true;
119 break;
120 }
121 }
122
122 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, 123 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
123 ACPI_TYPE_PACKAGE); 124 ACPI_TYPE_PACKAGE);
124 if (ACPI_FAILURE(status)) 125 if (ACPI_FAILURE(status))
125 return; 126 goto out;
126 127
127 desc = buf.pointer; 128 desc = buf.pointer;
128 if (desc->package.count % 2) 129 if (desc->package.count % 2)
@@ -156,13 +157,20 @@ void acpi_init_properties(struct acpi_device *adev)
156 adev->data.pointer = buf.pointer; 157 adev->data.pointer = buf.pointer;
157 adev->data.properties = properties; 158 adev->data.properties = properties;
158 159
159 acpi_init_of_compatible(adev); 160 if (acpi_of)
160 return; 161 acpi_init_of_compatible(adev);
162
163 goto out;
161 } 164 }
162 165
163 fail: 166 fail:
164 dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n"); 167 dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n");
165 ACPI_FREE(buf.pointer); 168 ACPI_FREE(buf.pointer);
169
170 out:
171 if (acpi_of && !adev->flags.of_compatible_ok)
172 acpi_handle_info(adev->handle,
173 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
166} 174}
167 175
168void acpi_free_properties(struct acpi_device *adev) 176void acpi_free_properties(struct acpi_device *adev)
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 8244f013f210..fcb7807ea8b7 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -26,6 +26,7 @@
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/export.h> 27#include <linux/export.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/list.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
30 31
31#ifdef CONFIG_X86 32#ifdef CONFIG_X86
@@ -621,3 +622,162 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares,
621 return (type & types) ? 0 : 1; 622 return (type & types) ? 0 : 1;
622} 623}
623EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); 624EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
625
626struct reserved_region {
627 struct list_head node;
628 u64 start;
629 u64 end;
630};
631
632static LIST_HEAD(reserved_io_regions);
633static LIST_HEAD(reserved_mem_regions);
634
635static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags,
636 char *desc)
637{
638 unsigned int length = end - start + 1;
639 struct resource *res;
640
641 res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ?
642 request_region(start, length, desc) :
643 request_mem_region(start, length, desc);
644 if (!res)
645 return -EIO;
646
647 res->flags &= ~flags;
648 return 0;
649}
650
651static int add_region_before(u64 start, u64 end, u8 space_id,
652 unsigned long flags, char *desc,
653 struct list_head *head)
654{
655 struct reserved_region *reg;
656 int error;
657
658 reg = kmalloc(sizeof(*reg), GFP_KERNEL);
659 if (!reg)
660 return -ENOMEM;
661
662 error = request_range(start, end, space_id, flags, desc);
663 if (error)
664 return error;
665
666 reg->start = start;
667 reg->end = end;
668 list_add_tail(&reg->node, head);
669 return 0;
670}
671
672/**
673 * acpi_reserve_region - Reserve an I/O or memory region as a system resource.
674 * @start: Starting address of the region.
675 * @length: Length of the region.
676 * @space_id: Identifier of address space to reserve the region from.
677 * @flags: Resource flags to clear for the region after requesting it.
678 * @desc: Region description (for messages).
679 *
680 * Reserve an I/O or memory region as a system resource to prevent others from
681 * using it. If the new region overlaps with one of the regions (in the given
682 * address space) already reserved by this routine, only the non-overlapping
683 * parts of it will be reserved.
684 *
685 * Returned is either 0 (success) or a negative error code indicating a resource
686 * reservation problem. It is the code of the first encountered error, but the
687 * routine doesn't abort until it has attempted to request all of the parts of
688 * the new region that don't overlap with other regions reserved previously.
689 *
690 * The resources requested by this routine are never released.
691 */
692int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
693 unsigned long flags, char *desc)
694{
695 struct list_head *regions;
696 struct reserved_region *reg;
697 u64 end = start + length - 1;
698 int ret = 0, error = 0;
699
700 if (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
701 regions = &reserved_io_regions;
702 else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
703 regions = &reserved_mem_regions;
704 else
705 return -EINVAL;
706
707 if (list_empty(regions))
708 return add_region_before(start, end, space_id, flags, desc, regions);
709
710 list_for_each_entry(reg, regions, node)
711 if (reg->start == end + 1) {
712 /* The new region can be prepended to this one. */
713 ret = request_range(start, end, space_id, flags, desc);
714 if (!ret)
715 reg->start = start;
716
717 return ret;
718 } else if (reg->start > end) {
719 /* No overlap. Add the new region here and get out. */
720 return add_region_before(start, end, space_id, flags,
721 desc, &reg->node);
722 } else if (reg->end == start - 1) {
723 goto combine;
724 } else if (reg->end >= start) {
725 goto overlap;
726 }
727
728 /* The new region goes after the last existing one. */
729 return add_region_before(start, end, space_id, flags, desc, regions);
730
731 overlap:
732 /*
733 * The new region overlaps an existing one.
734 *
735 * The head part of the new region immediately preceding the existing
736 * overlapping one can be combined with it right away.
737 */
738 if (reg->start > start) {
739 error = request_range(start, reg->start - 1, space_id, flags, desc);
740 if (error)
741 ret = error;
742 else
743 reg->start = start;
744 }
745
746 combine:
747 /*
748 * The new region is adjacent to an existing one. If it extends beyond
749 * that region all the way to the next one, it is possible to combine
750 * all three of them.
751 */
752 while (reg->end < end) {
753 struct reserved_region *next = NULL;
754 u64 a = reg->end + 1, b = end;
755
756 if (!list_is_last(&reg->node, regions)) {
757 next = list_next_entry(reg, node);
758 if (next->start <= end)
759 b = next->start - 1;
760 }
761 error = request_range(a, b, space_id, flags, desc);
762 if (!error) {
763 if (next && next->start == b + 1) {
764 reg->end = next->end;
765 list_del(&next->node);
766 kfree(next);
767 } else {
768 reg->end = end;
769 break;
770 }
771 } else if (next) {
772 if (!ret)
773 ret = error;
774
775 reg = next;
776 } else {
777 break;
778 }
779 }
780
781 return ret ? ret : error;
782}
783EXPORT_SYMBOL_GPL(acpi_reserve_region);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 03141aa4ea95..0a099917a006 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -135,12 +135,13 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
135 struct acpi_hardware_id *id; 135 struct acpi_hardware_id *id;
136 136
137 /* 137 /*
138 * Since we skip PRP0001 from the modalias below, 0 should be returned 138 * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
139 * if PRP0001 is the only ACPI/PNP ID in the device's list. 139 * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
140 * device's list.
140 */ 141 */
141 count = 0; 142 count = 0;
142 list_for_each_entry(id, &acpi_dev->pnp.ids, list) 143 list_for_each_entry(id, &acpi_dev->pnp.ids, list)
143 if (strcmp(id->id, "PRP0001")) 144 if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
144 count++; 145 count++;
145 146
146 if (!count) 147 if (!count)
@@ -153,7 +154,7 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
153 size -= len; 154 size -= len;
154 155
155 list_for_each_entry(id, &acpi_dev->pnp.ids, list) { 156 list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
156 if (!strcmp(id->id, "PRP0001")) 157 if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
157 continue; 158 continue;
158 159
159 count = snprintf(&modalias[len], size, "%s:", id->id); 160 count = snprintf(&modalias[len], size, "%s:", id->id);
@@ -177,7 +178,8 @@ static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
177 * @size: Size of the buffer. 178 * @size: Size of the buffer.
178 * 179 *
179 * Expose DT compatible modalias as of:NnameTCcompatible. This function should 180 * Expose DT compatible modalias as of:NnameTCcompatible. This function should
180 * only be called for devices having PRP0001 in their list of ACPI/PNP IDs. 181 * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
182 * ACPI/PNP IDs.
181 */ 183 */
182static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, 184static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
183 int size) 185 int size)
@@ -980,9 +982,9 @@ static void acpi_device_remove_files(struct acpi_device *dev)
980 * @adev: ACPI device object to match. 982 * @adev: ACPI device object to match.
981 * @of_match_table: List of device IDs to match against. 983 * @of_match_table: List of device IDs to match against.
982 * 984 *
983 * If @dev has an ACPI companion which has the special PRP0001 device ID in its 985 * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
984 * list of identifiers and a _DSD object with the "compatible" property, use 986 * identifiers and a _DSD object with the "compatible" property, use that
985 * that property to match against the given list of identifiers. 987 * property to match against the given list of identifiers.
986 */ 988 */
987static bool acpi_of_match_device(struct acpi_device *adev, 989static bool acpi_of_match_device(struct acpi_device *adev,
988 const struct of_device_id *of_match_table) 990 const struct of_device_id *of_match_table)
@@ -1038,14 +1040,14 @@ static const struct acpi_device_id *__acpi_match_device(
1038 return id; 1040 return id;
1039 1041
1040 /* 1042 /*
1041 * Next, check the special "PRP0001" ID and try to match the 1043 * Next, check ACPI_DT_NAMESPACE_HID and try to match the
1042 * "compatible" property if found. 1044 * "compatible" property if found.
1043 * 1045 *
1044 * The id returned by the below is not valid, but the only 1046 * The id returned by the below is not valid, but the only
1045 * caller passing non-NULL of_ids here is only interested in 1047 * caller passing non-NULL of_ids here is only interested in
1046 * whether or not the return value is NULL. 1048 * whether or not the return value is NULL.
1047 */ 1049 */
1048 if (!strcmp("PRP0001", hwid->id) 1050 if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
1049 && acpi_of_match_device(device, of_ids)) 1051 && acpi_of_match_device(device, of_ids))
1050 return id; 1052 return id;
1051 } 1053 }
@@ -1671,7 +1673,7 @@ static int acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
1671 1673
1672static void acpi_wakeup_gpe_init(struct acpi_device *device) 1674static void acpi_wakeup_gpe_init(struct acpi_device *device)
1673{ 1675{
1674 struct acpi_device_id button_device_ids[] = { 1676 static const struct acpi_device_id button_device_ids[] = {
1675 {"PNP0C0C", 0}, 1677 {"PNP0C0C", 0},
1676 {"PNP0C0D", 0}, 1678 {"PNP0C0D", 0},
1677 {"PNP0C0E", 0}, 1679 {"PNP0C0E", 0},
@@ -2405,7 +2407,7 @@ static void acpi_default_enumeration(struct acpi_device *device)
2405} 2407}
2406 2408
2407static const struct acpi_device_id generic_device_ids[] = { 2409static const struct acpi_device_id generic_device_ids[] = {
2408 {"PRP0001", }, 2410 {ACPI_DT_NAMESPACE_HID, },
2409 {"", }, 2411 {"", },
2410}; 2412};
2411 2413
@@ -2413,8 +2415,8 @@ static int acpi_generic_device_attach(struct acpi_device *adev,
2413 const struct acpi_device_id *not_used) 2415 const struct acpi_device_id *not_used)
2414{ 2416{
2415 /* 2417 /*
2416 * Since PRP0001 is the only ID handled here, the test below can be 2418 * Since ACPI_DT_NAMESPACE_HID is the only ID handled here, the test
2417 * unconditional. 2419 * below can be unconditional.
2418 */ 2420 */
2419 if (adev->data.of_compatible) 2421 if (adev->data.of_compatible)
2420 acpi_default_enumeration(adev); 2422 acpi_default_enumeration(adev);
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 49c1720df59a..515f33882ab8 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -7,6 +7,7 @@
7 * Bjorn Helgaas <bjorn.helgaas@hp.com> 7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
8 */ 8 */
9 9
10#include <linux/acpi.h>
10#include <linux/pnp.h> 11#include <linux/pnp.h>
11#include <linux/device.h> 12#include <linux/device.h>
12#include <linux/init.h> 13#include <linux/init.h>
@@ -22,25 +23,41 @@ static const struct pnp_device_id pnp_dev_table[] = {
22 {"", 0} 23 {"", 0}
23}; 24};
24 25
26#ifdef CONFIG_ACPI
27static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc)
28{
29 u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY;
30 return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc);
31}
32#else
33static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc)
34{
35 struct resource *res;
36
37 res = io ? request_region(start, length, desc) :
38 request_mem_region(start, length, desc);
39 if (res) {
40 res->flags &= ~IORESOURCE_BUSY;
41 return true;
42 }
43 return false;
44}
45#endif
46
25static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) 47static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
26{ 48{
27 char *regionid; 49 char *regionid;
28 const char *pnpid = dev_name(&dev->dev); 50 const char *pnpid = dev_name(&dev->dev);
29 resource_size_t start = r->start, end = r->end; 51 resource_size_t start = r->start, end = r->end;
30 struct resource *res; 52 bool reserved;
31 53
32 regionid = kmalloc(16, GFP_KERNEL); 54 regionid = kmalloc(16, GFP_KERNEL);
33 if (!regionid) 55 if (!regionid)
34 return; 56 return;
35 57
36 snprintf(regionid, 16, "pnp %s", pnpid); 58 snprintf(regionid, 16, "pnp %s", pnpid);
37 if (port) 59 reserved = __reserve_range(start, end - start + 1, !!port, regionid);
38 res = request_region(start, end - start + 1, regionid); 60 if (!reserved)
39 else
40 res = request_mem_region(start, end - start + 1, regionid);
41 if (res)
42 res->flags &= ~IORESOURCE_BUSY;
43 else
44 kfree(regionid); 61 kfree(regionid);
45 62
46 /* 63 /*
@@ -49,7 +66,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port)
49 * have double reservations. 66 * have double reservations.
50 */ 67 */
51 dev_info(&dev->dev, "%pR %s reserved\n", r, 68 dev_info(&dev->dev, "%pR %s reserved\n", r,
52 res ? "has been" : "could not be"); 69 reserved ? "has been" : "could not be");
53} 70}
54 71
55static void reserve_resources_of_dev(struct pnp_dev *dev) 72static void reserve_resources_of_dev(struct pnp_dev *dev)
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 8de4fa90e8c4..da079976971f 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -208,7 +208,8 @@ struct acpi_device_flags {
208 u32 visited:1; 208 u32 visited:1;
209 u32 hotplug_notify:1; 209 u32 hotplug_notify:1;
210 u32 is_dock_station:1; 210 u32 is_dock_station:1;
211 u32 reserved:23; 211 u32 of_compatible_ok:1;
212 u32 reserved:22;
212}; 213};
213 214
214/* File System */ 215/* File System */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index e4da5e35e29c..5da2d2e9d38e 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -332,6 +332,9 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
332 332
333int acpi_resources_are_enforced(void); 333int acpi_resources_are_enforced(void);
334 334
335int acpi_reserve_region(u64 start, unsigned int length, u8 space_id,
336 unsigned long flags, char *desc);
337
335#ifdef CONFIG_HIBERNATION 338#ifdef CONFIG_HIBERNATION
336void __init acpi_no_s4_hw_signature(void); 339void __init acpi_no_s4_hw_signature(void);
337#endif 340#endif
@@ -440,6 +443,7 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
440#define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82 443#define ACPI_OST_SC_INSERT_NOT_SUPPORTED 0x82
441 444
442extern void acpi_early_init(void); 445extern void acpi_early_init(void);
446extern void acpi_subsystem_init(void);
443 447
444extern int acpi_nvs_register(__u64 start, __u64 size); 448extern int acpi_nvs_register(__u64 start, __u64 size);
445 449
@@ -494,6 +498,7 @@ static inline const char *acpi_dev_name(struct acpi_device *adev)
494} 498}
495 499
496static inline void acpi_early_init(void) { } 500static inline void acpi_early_init(void) { }
501static inline void acpi_subsystem_init(void) { }
497 502
498static inline int early_acpi_boot_init(void) 503static inline int early_acpi_boot_init(void)
499{ 504{
@@ -525,6 +530,13 @@ static inline int acpi_check_region(resource_size_t start, resource_size_t n,
525 return 0; 530 return 0;
526} 531}
527 532
533static inline int acpi_reserve_region(u64 start, unsigned int length,
534 u8 space_id, unsigned long flags,
535 char *desc)
536{
537 return -ENXIO;
538}
539
528struct acpi_table_header; 540struct acpi_table_header;
529static inline int acpi_table_parse(char *id, 541static inline int acpi_table_parse(char *id,
530 int (*handler)(struct acpi_table_header *)) 542 int (*handler)(struct acpi_table_header *))
diff --git a/init/main.c b/init/main.c
index 2115055faeac..2a89545e0a5d 100644
--- a/init/main.c
+++ b/init/main.c
@@ -664,6 +664,7 @@ asmlinkage __visible void __init start_kernel(void)
664 664
665 check_bugs(); 665 check_bugs();
666 666
667 acpi_subsystem_init();
667 sfi_init_late(); 668 sfi_init_late();
668 669
669 if (efi_enabled(EFI_RUNTIME_SERVICES)) { 670 if (efi_enabled(EFI_RUNTIME_SERVICES)) {