diff options
-rw-r--r-- | Documentation/acpi/enumeration.txt | 57 | ||||
-rw-r--r-- | Documentation/kernel-parameters.txt | 62 | ||||
-rw-r--r-- | drivers/acpi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/acpi/bus.c | 56 | ||||
-rw-r--r-- | drivers/acpi/internal.h | 2 | ||||
-rw-r--r-- | drivers/acpi/osl.c | 6 | ||||
-rw-r--r-- | drivers/acpi/property.c | 54 | ||||
-rw-r--r-- | drivers/acpi/resource.c | 160 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 30 | ||||
-rw-r--r-- | drivers/pnp/system.c | 35 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 3 | ||||
-rw-r--r-- | include/linux/acpi.h | 12 | ||||
-rw-r--r-- | init/main.c | 1 |
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 | |||
42 | straightforward. Here is the simplest example: | 42 | straightforward. 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 | |||
166 | to at25 SPI eeprom driver (this is meant for the above ACPI snippet): | 166 | to 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 | |||
230 | input driver: | 230 | input 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: | |||
359 | The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under | 359 | The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under |
360 | the MFD device and if found, that ACPI companion device is bound to the | 360 | the MFD device and if found, that ACPI companion device is bound to the |
361 | resulting child platform device. | 361 | resulting child platform device. |
362 | |||
363 | Device Tree namespace link device ID | ||
364 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
365 | The Device Tree protocol uses device indentification based on the "compatible" | ||
366 | property whose value is a string or an array of strings recognized as device | ||
367 | identifiers by drivers and the driver core. The set of all those strings may be | ||
368 | regarded as a device indentification namespace analogous to the ACPI/PNP device | ||
369 | ID namespace. Consequently, in principle it should not be necessary to allocate | ||
370 | a new (and arguably redundant) ACPI/PNP device ID for a devices with an existing | ||
371 | identification string in the Device Tree (DT) namespace, especially if that ID | ||
372 | is only needed to indicate that a given device is compatible with another one, | ||
373 | presumably having a matching driver in the kernel already. | ||
374 | |||
375 | In ACPI, the device identification object called _CID (Compatible ID) is used to | ||
376 | list the IDs of devices the given one is compatible with, but those IDs must | ||
377 | belong to one of the namespaces prescribed by the ACPI specification (see | ||
378 | Section 6.1.2 of ACPI 6.0 for details) and the DT namespace is not one of them. | ||
379 | Moreover, the specification mandates that either a _HID or an _ADR identificaion | ||
380 | object be present for all ACPI objects representing devices (Section 6.1 of ACPI | ||
381 | 6.0). For non-enumerable bus types that object must be _HID and its value must | ||
382 | be a device ID from one of the namespaces prescribed by the specification too. | ||
383 | |||
384 | The special DT namespace link device ID, PRP0001, provides a means to use the | ||
385 | existing DT-compatible device identification in ACPI and to satisfy the above | ||
386 | requirements following from the ACPI specification at the same time. Namely, | ||
387 | if 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 | ||
389 | property to identify the corresponding device in analogy with the original DT | ||
390 | device identification algorithm. If the "compatible" property is not present | ||
391 | or its value is not valid, the device will not be enumerated by the ACPI | ||
392 | subsystem. 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 | ||
394 | which case the ACPI core will leave the device enumeration to the parent's | ||
395 | driver) and the identification strings from the "compatible" property value will | ||
396 | be used to find a driver for the device along with the device IDs listed by _CID | ||
397 | (if present). | ||
398 | |||
399 | Analogously, if PRP0001 is present in the list of device IDs returned by _CID, | ||
400 | the identification strings listed by the "compatible" property value (if present | ||
401 | and valid) will be used to look for a driver matching the device, but in that | ||
402 | case 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. | ||
404 | Specifically, the device IDs returned by _HID and preceding PRP0001 in the _CID | ||
405 | return package will be checked first. Also in that case the bus type the device | ||
406 | will be enumerated to depends on the device ID returned by _HID. | ||
407 | |||
408 | It is valid to define device objects with a _HID returning PRP0001 and without | ||
409 | the "compatible" property in the _DSD or a _CID as long as one of their | ||
410 | ancestors provides a _DSD with a valid "compatible" property. Such device | ||
411 | objects are then simply regarded as additional "blocks" providing hierarchical | ||
412 | configuration 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 | ||
63 | config ACPI_PROCFS_POWER | 63 | config 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 | */ | ||
473 | void __init acpi_early_init(void) | 483 | void __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 | */ | ||
562 | void __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 | ||
558 | static int __init acpi_bus_init(void) | 584 | static 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 | |||
194 | void acpi_init_properties(struct acpi_device *adev); | 196 | void acpi_init_properties(struct acpi_device *adev); |
195 | void acpi_free_properties(struct acpi_device *adev); | 197 | void 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 | ||
185 | static void __init acpi_reserve_resources(void) | 181 | static 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) | |||
79 | static void acpi_init_of_compatible(struct acpi_device *adev) | 79 | static 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 | ||
115 | void acpi_init_properties(struct acpi_device *adev) | 103 | void 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 | ||
168 | void acpi_free_properties(struct acpi_device *adev) | 176 | void 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 | } |
623 | EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); | 624 | EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); |
625 | |||
626 | struct reserved_region { | ||
627 | struct list_head node; | ||
628 | u64 start; | ||
629 | u64 end; | ||
630 | }; | ||
631 | |||
632 | static LIST_HEAD(reserved_io_regions); | ||
633 | static LIST_HEAD(reserved_mem_regions); | ||
634 | |||
635 | static 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 | |||
651 | static 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(®->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 | */ | ||
692 | int 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, ®->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(®->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 | } | ||
783 | EXPORT_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 | */ |
182 | static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, | 184 | static 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 | */ |
987 | static bool acpi_of_match_device(struct acpi_device *adev, | 989 | static 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 | ||
1672 | static void acpi_wakeup_gpe_init(struct acpi_device *device) | 1674 | static 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 | ||
2407 | static const struct acpi_device_id generic_device_ids[] = { | 2409 | static 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 | ||
27 | static 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 | ||
33 | static 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 | |||
25 | static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) | 47 | static 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 | ||
55 | static void reserve_resources_of_dev(struct pnp_dev *dev) | 72 | static 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 | ||
333 | int acpi_resources_are_enforced(void); | 333 | int acpi_resources_are_enforced(void); |
334 | 334 | ||
335 | int 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 |
336 | void __init acpi_no_s4_hw_signature(void); | 339 | void __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 | ||
442 | extern void acpi_early_init(void); | 445 | extern void acpi_early_init(void); |
446 | extern void acpi_subsystem_init(void); | ||
443 | 447 | ||
444 | extern int acpi_nvs_register(__u64 start, __u64 size); | 448 | extern 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 | ||
496 | static inline void acpi_early_init(void) { } | 500 | static inline void acpi_early_init(void) { } |
501 | static inline void acpi_subsystem_init(void) { } | ||
497 | 502 | ||
498 | static inline int early_acpi_boot_init(void) | 503 | static 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 | ||
533 | static 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 | |||
528 | struct acpi_table_header; | 540 | struct acpi_table_header; |
529 | static inline int acpi_table_parse(char *id, | 541 | static 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)) { |