Commit 7397e1e8 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'acpi-4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI fixes from Rafael Wysocki:
 "These fix a device enumeration problem related to _ADR matching and an
  IOMMU initialization issue related to the DMAR table missing, remove
  an excessive function call from the core ACPI code, update an error
  message in the ACPI WDAT watchdog driver and add a way to work around
  problems with unhandled GPE notifications.

  Specifics:

   - Fix a device enumeration issue leading to incorrect associations
     between ACPI device objects and platform device objects
     representing physical devices if the given device object has both
     _ADR and _HID (Rafael Wysocki).

   - Avoid passing NULL to acpi_put_table() during IOMMU initialization
     which triggers a (rightful) warning from ACPICA (Rafael Wysocki).

   - Drop an excessive call to acpi_dma_deconfigure() from the core code
     that binds ACPI device objects to device objects representing
     physical devices (Lorenzo Pieralisi).

   - Update an error message in the ACPI WDAT watchdog driver to make it
     provide more useful information (Mika Westerberg).

   - Add a mechanism to work around issues with unhandled GPE
     notifications that occur during system initialization and cannot be
     prevented by means of sysfs (Lv Zheng)"

* tag 'acpi-4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI / DMAR: Avoid passing NULL to acpi_put_table()
  ACPI / scan: Prefer devices without _HID/_CID for _ADR matching
  ACPI / watchdog: Print out error number when device creation fails
  ACPI / sysfs: Provide quirk mechanism to prevent GPE flooding
  ACPI: Drop misplaced acpi_dma_deconfigure() call from acpi_bind_one()
parents b937a869 f1dabf0b
...@@ -106,6 +106,16 @@ ...@@ -106,6 +106,16 @@
use by PCI use by PCI
Format: <irq>,<irq>... Format: <irq>,<irq>...
acpi_mask_gpe= [HW,ACPI]
Due to the existence of _Lxx/_Exx, some GPEs triggered
by unsupported hardware/firmware features can result in
GPE floodings that cannot be automatically disabled by
the GPE dispatcher.
This facility can be used to prevent such uncontrolled
GPE floodings.
Format: <int>
Support masking of GPEs numbered from 0x00 to 0x7f.
acpi_no_auto_serialize [HW,ACPI] acpi_no_auto_serialize [HW,ACPI]
Disable auto-serialization of AML methods Disable auto-serialization of AML methods
AML control methods that contain the opcodes to create AML control methods that contain the opcodes to create
......
...@@ -114,7 +114,7 @@ void __init acpi_watchdog_init(void) ...@@ -114,7 +114,7 @@ void __init acpi_watchdog_init(void)
pdev = platform_device_register_simple("wdat_wdt", PLATFORM_DEVID_NONE, pdev = platform_device_register_simple("wdat_wdt", PLATFORM_DEVID_NONE,
resources, nresources); resources, nresources);
if (IS_ERR(pdev)) if (IS_ERR(pdev))
pr_err("Failed to create platform device\n"); pr_err("Device creation failed: %ld\n", PTR_ERR(pdev));
kfree(resources); kfree(resources);
......
...@@ -98,7 +98,15 @@ static int find_child_checks(struct acpi_device *adev, bool check_children) ...@@ -98,7 +98,15 @@ static int find_child_checks(struct acpi_device *adev, bool check_children)
if (check_children && list_empty(&adev->children)) if (check_children && list_empty(&adev->children))
return -ENODEV; return -ENODEV;
return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; /*
* If the device has a _HID (or _CID) returning a valid ACPI/PNP
* device ID, it is better to make it look less attractive here, so that
* the other device with the same _ADR value (that may not have a valid
* device ID) can be matched going forward. [This means a second spec
* violation in a row, so whatever we do here is best effort anyway.]
*/
return sta_present && list_empty(&adev->pnp.ids) ?
FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
} }
struct acpi_device *acpi_find_child_device(struct acpi_device *parent, struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
...@@ -250,7 +258,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev) ...@@ -250,7 +258,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
return 0; return 0;
err: err:
acpi_dma_deconfigure(dev);
ACPI_COMPANION_SET(dev, NULL); ACPI_COMPANION_SET(dev, NULL);
put_device(dev); put_device(dev);
put_device(&acpi_dev->dev); put_device(&acpi_dev->dev);
......
...@@ -37,6 +37,7 @@ void acpi_amba_init(void); ...@@ -37,6 +37,7 @@ void acpi_amba_init(void);
static inline void acpi_amba_init(void) {} static inline void acpi_amba_init(void) {}
#endif #endif
int acpi_sysfs_init(void); int acpi_sysfs_init(void);
void acpi_gpe_apply_masked_gpes(void);
void acpi_container_init(void); void acpi_container_init(void);
void acpi_memory_hotplug_init(void); void acpi_memory_hotplug_init(void);
#ifdef CONFIG_ACPI_HOTPLUG_IOAPIC #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
......
...@@ -2074,6 +2074,7 @@ int __init acpi_scan_init(void) ...@@ -2074,6 +2074,7 @@ int __init acpi_scan_init(void)
} }
} }
acpi_gpe_apply_masked_gpes();
acpi_update_all_gpes(); acpi_update_all_gpes();
acpi_ec_ecdt_start(); acpi_ec_ecdt_start();
......
...@@ -708,6 +708,62 @@ static ssize_t counter_set(struct kobject *kobj, ...@@ -708,6 +708,62 @@ static ssize_t counter_set(struct kobject *kobj,
return result ? result : size; return result ? result : size;
} }
/*
* A Quirk Mechanism for GPE Flooding Prevention:
*
* Quirks may be needed to prevent GPE flooding on a specific GPE. The
* flooding typically cannot be detected and automatically prevented by
* ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
* the AML tables. This normally indicates a feature gap in Linux, thus
* instead of providing endless quirk tables, we provide a boot parameter
* for those who want this quirk. For example, if the users want to prevent
* the GPE flooding for GPE 00, they need to specify the following boot
* parameter:
* acpi_mask_gpe=0x00
* The masking status can be modified by the following runtime controlling
* interface:
* echo unmask > /sys/firmware/acpi/interrupts/gpe00
*/
/*
* Currently, the GPE flooding prevention only supports to mask the GPEs
* numbered from 00 to 7f.
*/
#define ACPI_MASKABLE_GPE_MAX 0x80
static u64 __initdata acpi_masked_gpes;
static int __init acpi_gpe_set_masked_gpes(char *val)
{
u8 gpe;
if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
return -EINVAL;
acpi_masked_gpes |= ((u64)1<<gpe);
return 1;
}
__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
void __init acpi_gpe_apply_masked_gpes(void)
{
acpi_handle handle;
acpi_status status;
u8 gpe;
for (gpe = 0;
gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
gpe++) {
if (acpi_masked_gpes & ((u64)1<<gpe)) {
status = acpi_get_gpe_device(gpe, &handle);
if (ACPI_SUCCESS(status)) {
pr_info("Masking GPE 0x%x.\n", gpe);
(void)acpi_mask_gpe(handle, gpe, TRUE);
}
}
}
}
void acpi_irq_stats_init(void) void acpi_irq_stats_init(void)
{ {
acpi_status status; acpi_status status;
......
...@@ -903,8 +903,10 @@ int __init detect_intel_iommu(void) ...@@ -903,8 +903,10 @@ int __init detect_intel_iommu(void)
x86_init.iommu.iommu_init = intel_iommu_init; x86_init.iommu.iommu_init = intel_iommu_init;
#endif #endif
if (dmar_tbl) {
acpi_put_table(dmar_tbl); acpi_put_table(dmar_tbl);
dmar_tbl = NULL; dmar_tbl = NULL;
}
up_write(&dmar_global_lock); up_write(&dmar_global_lock);
return ret ? 1 : -ENODEV; return ret ? 1 : -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment