diff --git a/CREDITS b/CREDITS index 32abf67ee1fa..f8a33916e2a5 100644 --- a/CREDITS +++ b/CREDITS @@ -2919,6 +2919,10 @@ N: Thomas Molina E: tmolina@cablespeed.com D: bug fixes, documentation, minor hackery +N: Bob Moore +E: robert.moore@intel.com +D: ACPI Component Architecture (ACPICA) + N: Paul Moore E: paul@paul-moore.com W: https://www.paul-moore.com diff --git a/Documentation/driver-api/acpi/linuxized-acpica.rst b/Documentation/driver-api/acpi/linuxized-acpica.rst index cc234353d2c4..317a68ed3b66 100644 --- a/Documentation/driver-api/acpi/linuxized-acpica.rst +++ b/Documentation/driver-api/acpi/linuxized-acpica.rst @@ -117,7 +117,7 @@ ACPICA Release ============== The ACPICA project maintains its code base at the following repository URL: -https://github.com/acpica/acpica.git. As a rule, a release is made every +https://github.com/open-acpica/acpica.git. As a rule, a release is made every month. As the coding style adopted by the ACPICA project is not acceptable by @@ -173,7 +173,7 @@ illustrated in the following figure:: utility located in source/tools/acpisrc folder and a number of scripts located in generate/linux folder. B. acpica / master - "master" branch of the git repository at - . + . C. linux-pm / linux-next - "linux-next" branch of the git repository at . D. linux / master - "master" branch of the git repository at @@ -244,7 +244,7 @@ before they become available from the ACPICA release process. Then the gen-patch.sh command can help to cherry-pick an ACPICA commit from the ACPICA local repository:: - $ git clone https://github.com/acpica/acpica + $ git clone https://github.com/open-acpica/acpica $ cd acpica $ generate/linux/gen-patch.sh -u [commit ID] @@ -259,7 +259,7 @@ before they become available from the ACPICA release process. You can generate the ACPICA release series yourself and rebase your code on top of the generated ACPICA release patches:: - $ git clone https://github.com/acpica/acpica + $ git clone https://github.com/open-acpica/acpica $ cd acpica $ generate/linux/make-patches.sh -u [commit ID] @@ -273,7 +273,7 @@ before they become available from the ACPICA release process. If you have local copies of both Linux and upstream ACPICA, you can generate a diff file indicating the state of the current divergences:: - # git clone https://github.com/acpica/acpica + # git clone https://github.com/open-acpica/acpica # git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git # cd acpica # generate/linux/divergence.sh -s ../linux diff --git a/MAINTAINERS b/MAINTAINERS index 7e44f413d9d9..55b3c2d7a78a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -313,15 +313,15 @@ F: drivers/firmware/efi/cper* ACPI COMPONENT ARCHITECTURE (ACPICA) M: "Rafael J. Wysocki" -M: Saket Dumbre +M: Maciej Wieczor-Retman +M: Pawel Chmielewski L: linux-acpi@vger.kernel.org L: acpica-devel@lists.linux.dev S: Supported W: https://acpica.org/ -W: https://github.com/acpica/acpica/ +W: https://github.com/open-acpica/acpica/ Q: https://patchwork.kernel.org/project/linux-acpi/list/ B: https://bugzilla.kernel.org -B: https://bugs.acpica.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm F: drivers/acpi/acpica/ F: include/acpi/ diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index 008bd0552cb7..e7366fcb76ee 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "internal.h" @@ -110,17 +111,17 @@ static int fch_misc_setup(struct apd_private_data *pdata) static const struct apd_device_desc cz_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 133000000, + .fixed_clk_rate = 133 * HZ_PER_MHZ, }; static const struct apd_device_desc wt_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 150000000, + .fixed_clk_rate = 150 * HZ_PER_MHZ, }; static const struct apd_device_desc wt_i3c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 125000000, + .fixed_clk_rate = 125 * HZ_PER_MHZ, }; static struct property_entry uart_properties[] = { @@ -132,7 +133,7 @@ static struct property_entry uart_properties[] = { static const struct apd_device_desc cz_uart_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 48000000, + .fixed_clk_rate = 48 * HZ_PER_MHZ, .properties = uart_properties, }; @@ -144,52 +145,57 @@ static const struct apd_device_desc fch_misc_desc = { #ifdef CONFIG_ARM64 static const struct apd_device_desc xgene_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 100000000, + .fixed_clk_rate = 100 * HZ_PER_MHZ, }; static const struct apd_device_desc vulcan_spi_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 133000000, + .fixed_clk_rate = 133 * HZ_PER_MHZ, }; static const struct apd_device_desc hip07_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 200000000, + .fixed_clk_rate = 200 * HZ_PER_MHZ, }; static const struct apd_device_desc hip08_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 250000000, + .fixed_clk_rate = 250 * HZ_PER_MHZ, }; static const struct apd_device_desc hip08_lite_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 125000000, + .fixed_clk_rate = 125 * HZ_PER_MHZ, }; static const struct apd_device_desc thunderx2_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 125000000, + .fixed_clk_rate = 125 * HZ_PER_MHZ, }; static const struct apd_device_desc nxp_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 350000000, + .fixed_clk_rate = 350 * HZ_PER_MHZ, }; static const struct apd_device_desc hip08_spi_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 250000000, + .fixed_clk_rate = 250 * HZ_PER_MHZ, }; static const struct apd_device_desc leca_spi_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 400000000, + .fixed_clk_rate = 400 * HZ_PER_MHZ, }; static const struct apd_device_desc leca_i2c_desc = { .setup = acpi_apd_setup, - .fixed_clk_rate = 250000000, + .fixed_clk_rate = 250 * HZ_PER_MHZ, +}; + +static const struct apd_device_desc hjmc_i2c_desc = { + .setup = acpi_apd_setup, + .fixed_clk_rate = 200 * HZ_PER_MHZ, }; #endif /* CONFIG_ARM64 */ @@ -262,6 +268,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { { "HISI02A2", APD_ADDR(hip08_i2c_desc) }, { "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) }, { "HISI0173", APD_ADDR(hip08_spi_desc) }, + { "HJMC3001", APD_ADDR(hjmc_i2c_desc) }, { "LECA0002", APD_ADDR(leca_spi_desc) }, { "LECA0003", APD_ADDR(leca_i2c_desc) }, { "NXP0001", APD_ADDR(nxp_i2c_desc) }, diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 373c94de7590..80ea7121744d 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -85,7 +85,13 @@ static unsigned int acpi_platform_adjust_resources(struct acpi_device *adev, for (i = 0; i < count; ) { struct resource *res = &resources[i]; - if (resource_type(new_res) != resource_type(res) || + /* + * Look for overlaps of resources of the same type that would + * cause resource insertion to fail down the road. + */ + if (__resource_contains_unbound(res, new_res) || + __resource_contains_unbound(new_res, res) || + resource_type(new_res) != resource_type(res) || !resource_union(new_res, res, new_res)) { i++; continue; @@ -102,18 +108,15 @@ static unsigned int acpi_platform_adjust_resources(struct acpi_device *adev, return count; } -static void acpi_platform_fill_resource(struct acpi_device *adev, - const struct resource *src, struct resource *dest) +static void acpi_platform_fill_resource(struct device *parent, + const struct resource *src, + struct resource *dest) { - struct device *parent; - *dest = *src; - /* * If the device has parent we need to take its resources into * account as well because this device might consume part of those. */ - parent = acpi_get_first_physical_node(acpi_dev_parent(adev)); if (parent && dev_is_pci(parent)) dest->parent = pci_find_resource(to_pci_dev(parent), dest); } @@ -141,7 +144,8 @@ static unsigned int acpi_platform_resource_count(struct acpi_resource *ares, voi struct platform_device *acpi_create_platform_device(struct acpi_device *adev, const struct property_entry *properties) { - struct acpi_device *parent = acpi_dev_parent(adev); + struct acpi_device *p = acpi_dev_parent(adev); + struct device *parent __free(put_device) = acpi_bus_get_primary_device(p); struct platform_device *pdev = NULL; struct platform_device_info pdevinfo; const struct acpi_device_id *match; @@ -187,7 +191,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, rentry->res, resources, count); - acpi_platform_fill_resource(adev, rentry->res, + acpi_platform_fill_resource(parent, rentry->res, &resources[count++]); } acpi_dev_free_resource_list(&resource_list); @@ -200,7 +204,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, * attached to it, that physical device should be the parent of the * platform device we are about to create. */ - pdevinfo.parent = parent ? acpi_get_first_physical_node(parent) : NULL; + pdevinfo.parent = parent; pdevinfo.name = dev_name(&adev->dev); pdevinfo.id = PLATFORM_DEVID_NONE; pdevinfo.res = resources; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 0084f308b790..670853ec3a4d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -105,6 +106,9 @@ struct acpi_battery { struct delayed_work acpi_notif_dwork; struct notifier_block pm_nb; struct list_head list; + unsigned long flags; + + struct mutex property_lock; /* Protects properties below. */ unsigned long update_time; int revision; int rate_now; @@ -131,7 +135,6 @@ struct acpi_battery { char oem_info[MAX_STRING_LENGTH]; int state; int power_unit; - unsigned long flags; }; #define to_acpi_battery(x) power_supply_get_drvdata(x) @@ -189,20 +192,6 @@ static bool acpi_battery_is_degraded(struct acpi_battery *battery) battery->full_charge_capacity < battery->design_capacity; } -static int acpi_battery_handle_discharging(struct acpi_battery *battery) -{ - /* - * Some devices wrongly report discharging if the battery's charge level - * was above the device's start charging threshold atm the AC adapter - * was plugged in and the device thus did not start a new charge cycle. - */ - if ((battery_ac_is_broken || power_supply_is_system_supplied()) && - battery->rate_now == 0) - return POWER_SUPPLY_STATUS_NOT_CHARGING; - - return POWER_SUPPLY_STATUS_DISCHARGING; -} - static int acpi_battery_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) @@ -210,15 +199,41 @@ static int acpi_battery_get_property(struct power_supply *psy, int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0; struct acpi_battery *battery = to_acpi_battery(psy); - if (acpi_battery_present(battery)) { - /* run battery update only if it is present */ - acpi_battery_get_state(battery); - } else if (psp != POWER_SUPPLY_PROP_PRESENT) - return -ENODEV; + /* run battery update only if it is present */ + if (!acpi_battery_present(battery)) { + switch (psp) { + case POWER_SUPPLY_PROP_PRESENT: + val->intval = 0; + return 0; + default: + return -ENODEV; + } + } + + mutex_lock(&battery->property_lock); + + acpi_battery_get_state(battery); + switch (psp) { case POWER_SUPPLY_PROP_STATUS: + /* + * Some devices wrongly report discharging if the battery's charge level + * was above the device's start charging threshold atm the AC adapter + * was plugged in and the device thus did not start a new charge cycle. + */ if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) - val->intval = acpi_battery_handle_discharging(battery); + if (battery->rate_now != 0) { + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + } else if (battery_ac_is_broken) { + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + } else { + mutex_unlock(&battery->property_lock); + + val->intval = power_supply_is_system_supplied() + ? POWER_SUPPLY_STATUS_NOT_CHARGING + : POWER_SUPPLY_STATUS_DISCHARGING; + return 0; + } else if (battery->state & ACPI_BATTERY_STATE_CHARGING) /* Check the rate and capacity to validate the status. */ if (!acpi_battery_is_full(battery) || @@ -321,6 +336,8 @@ static int acpi_battery_get_property(struct power_supply *psy, default: ret = -EINVAL; } + + mutex_unlock(&battery->property_lock); return ret; } @@ -556,6 +573,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) int use_bix; int result = -ENODEV; + lockdep_assert_held(&battery->property_lock); + if (!acpi_battery_present(battery)) return 0; @@ -595,6 +614,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery) acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + lockdep_assert_held(&battery->property_lock); + if (!acpi_battery_present(battery)) return 0; @@ -648,6 +669,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) { acpi_status status = 0; + lockdep_assert_held(&battery->property_lock); + if (!acpi_battery_present(battery) || !test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags)) return -ENODEV; @@ -665,6 +688,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) static int acpi_battery_init_alarm(struct acpi_battery *battery) { + lockdep_assert_held(&battery->property_lock); + /* See if alarms are supported, and if so, set default */ if (!acpi_has_method(battery->device->handle, "_BTP")) { clear_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags); @@ -682,6 +707,8 @@ static ssize_t acpi_battery_alarm_show(struct device *dev, { struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + guard(mutex)(&battery->property_lock); + return sysfs_emit(buf, "%d\n", battery->alarm * 1000); } @@ -697,6 +724,8 @@ static ssize_t acpi_battery_alarm_store(struct device *dev, if (err) return err; + guard(mutex)(&battery->property_lock); + battery->alarm = x / 1000; if (acpi_battery_present(battery)) acpi_battery_set_alarm(battery); @@ -881,12 +910,17 @@ static int sysfs_add_battery(struct acpi_battery *battery) .no_wakeup_source = true, }; bool full_cap_broken = false; + int power_unit; - if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) && - !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity)) - full_cap_broken = true; + scoped_guard(mutex, &battery->property_lock) { + power_unit = battery->power_unit; - if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) { + if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) && + !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity)) + full_cap_broken = true; + } + + if (power_unit == ACPI_BATTERY_POWER_UNIT_MA) { if (full_cap_broken) { battery->bat_desc.properties = charge_battery_full_cap_broken_props; @@ -940,6 +974,9 @@ static void sysfs_remove_battery(struct acpi_battery *battery) static void find_battery(const struct dmi_header *dm, void *private) { struct acpi_battery *battery = (struct acpi_battery *)private; + + lockdep_assert_held(&battery->property_lock); + /* Note: the hardcoded offsets below have been extracted from * the source code of dmidecode. */ @@ -971,6 +1008,8 @@ static void find_battery(const struct dmi_header *dm, void *private) */ static void acpi_battery_quirks(struct acpi_battery *battery) { + lockdep_assert_held(&battery->property_lock); + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) return; @@ -1023,30 +1062,38 @@ static void acpi_battery_quirks(struct acpi_battery *battery) static int acpi_battery_update(struct acpi_battery *battery, bool resume) { int result = acpi_battery_get_status(battery); + bool wakeup; if (result) return result; if (!acpi_battery_present(battery)) { sysfs_remove_battery(battery); - battery->update_time = 0; + scoped_guard(mutex, &battery->property_lock) + battery->update_time = 0; return 0; } if (resume) return 0; - if (!battery->update_time) { - result = acpi_battery_get_info(battery); + scoped_guard(mutex, &battery->property_lock) { + if (!battery->update_time) { + result = acpi_battery_get_info(battery); + if (result) + return result; + acpi_battery_init_alarm(battery); + } + + result = acpi_battery_get_state(battery); if (result) return result; - acpi_battery_init_alarm(battery); - } + acpi_battery_quirks(battery); - result = acpi_battery_get_state(battery); - if (result) - return result; - acpi_battery_quirks(battery); + wakeup = ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || + (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && + (battery->capacity_now <= battery->alarm))); + } if (!battery->bat) { result = sysfs_add_battery(battery); @@ -1058,9 +1105,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume) * Wakeup the system if battery is critical low * or lower than the alarm level */ - if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) || - (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) && - (battery->capacity_now <= battery->alarm))) + if (wakeup) acpi_pm_wakeup_event(battery->phys_dev); return result; @@ -1073,12 +1118,14 @@ static void acpi_battery_refresh(struct acpi_battery *battery) if (!battery->bat) return; - power_unit = battery->power_unit; + scoped_guard(mutex, &battery->property_lock) { + power_unit = battery->power_unit; - acpi_battery_get_info(battery); + acpi_battery_get_info(battery); - if (power_unit == battery->power_unit) - return; + if (power_unit == battery->power_unit) + return; + } /* The battery has changed its reporting units. */ sysfs_remove_battery(battery); @@ -1170,17 +1217,21 @@ static int battery_notify(struct notifier_block *nb, } else { int result; - result = acpi_battery_get_info(battery); - if (result) - return result; + scoped_guard(mutex, &battery->property_lock) { + result = acpi_battery_get_info(battery); + if (result) + return result; + } result = sysfs_add_battery(battery); if (result) return result; } - acpi_battery_init_alarm(battery); - acpi_battery_get_state(battery); + scoped_guard(mutex, &battery->property_lock) { + acpi_battery_init_alarm(battery); + acpi_battery_get_state(battery); + } } return 0; @@ -1345,6 +1396,10 @@ static int acpi_battery_probe(struct platform_device *pdev) if (result) return result; + result = devm_mutex_init(&pdev->dev, &battery->property_lock); + if (result) + return result; + if (acpi_has_method(battery->device->handle, "_BIX")) set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index beb51151a660..808c6746be14 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -774,30 +774,52 @@ static int __init acpi_setup_sb_notify_handler(void) Device Matching -------------------------------------------------------------------------- */ + +static struct device *primary_physical_device(struct acpi_device *adev) +{ + struct acpi_device_physical_node *pn; + + pn = list_first_entry_or_null(&adev->physical_node_list, + struct acpi_device_physical_node, node); + if (pn) + return pn->dev; + + return NULL; +} + /** - * acpi_get_first_physical_node - Get first physical node of an ACPI device + * acpi_bus_get_primary_device - Get first physical device for a given ACPI one + * @adev: ACPI device to get the first physical device for. + * + * Find the first physical device for which @adev is the ACPI companion and + * reference count it if present. + * + * Return: Pointer to the first physical counterpart of @adev or NULL if there + * are none. Callers are responsible for invoking put_device() on the returned + * device. + */ +struct device *acpi_bus_get_primary_device(struct acpi_device *adev) +{ + if (!adev) + return NULL; + + guard(mutex)(&adev->physical_node_lock); + + return get_device(primary_physical_device(adev)); +} +EXPORT_SYMBOL_GPL(acpi_bus_get_primary_device); + +/** + * acpi_get_first_physical_node - Find first physical node of an ACPI device * @adev: ACPI device in question * * Return: First physical node of ACPI device @adev */ struct device *acpi_get_first_physical_node(struct acpi_device *adev) { - struct mutex *physical_node_lock = &adev->physical_node_lock; - struct device *phys_dev; + guard(mutex)(&adev->physical_node_lock); - mutex_lock(physical_node_lock); - if (list_empty(&adev->physical_node_list)) { - phys_dev = NULL; - } else { - const struct acpi_device_physical_node *node; - - node = list_first_entry(&adev->physical_node_list, - struct acpi_device_physical_node, node); - - phys_dev = node->dev; - } - mutex_unlock(physical_node_lock); - return phys_dev; + return primary_physical_device(adev); } EXPORT_SYMBOL_GPL(acpi_get_first_physical_node); diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 3836ee75dd66..cdbb1023a8ee 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -133,6 +133,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = { }, .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, }, + { + /* + * Razer Blade Pro 17 early 2020, notification of the LID device + * only happens on close, not on open and _LID keeps returning closed. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Razer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Blade Pro 17 (Early 2020) - RZ09-0329"), + }, + .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, + }, { /* * Samsung galaxybook2 ,initial _LID device notification returns diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c index 6283105bb0e8..9afd2c52fdbd 100644 --- a/drivers/acpi/pfr_update.c +++ b/drivers/acpi/pfr_update.c @@ -120,7 +120,7 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr, struct pfru_device *pfru_dev) { acpi_handle handle = ACPI_HANDLE(pfru_dev->parent_dev); - union acpi_object *out_obj; + union acpi_object *out_obj, *elem; int ret = -EINVAL; out_obj = acpi_evaluate_dsm_typed(handle, &pfru_guid, @@ -150,7 +150,9 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr, goto free_acpi_buffer; } - cap_hdr->status = out_obj->package.elements[CAP_STATUS_IDX].integer.value; + elem = out_obj->package.elements; + + cap_hdr->status = elem[CAP_STATUS_IDX].integer.value; if (cap_hdr->status != DSM_SUCCEED) { ret = -EBUSY; dev_dbg(pfru_dev->parent_dev, "Query cap Error Status:%d\n", @@ -158,29 +160,30 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr, goto free_acpi_buffer; } - cap_hdr->update_cap = out_obj->package.elements[CAP_UPDATE_IDX].integer.value; + if (elem[CAP_CODE_TYPE_IDX].buffer.length > sizeof(cap_hdr->code_type) || + elem[CAP_DRV_TYPE_IDX].buffer.length > sizeof(cap_hdr->drv_type) || + elem[CAP_PLAT_ID_IDX].buffer.length > sizeof(cap_hdr->platform_id) || + elem[CAP_OEM_ID_IDX].buffer.length > sizeof(cap_hdr->oem_id)) + goto free_acpi_buffer; + + cap_hdr->update_cap = elem[CAP_UPDATE_IDX].integer.value; memcpy(&cap_hdr->code_type, - out_obj->package.elements[CAP_CODE_TYPE_IDX].buffer.pointer, - out_obj->package.elements[CAP_CODE_TYPE_IDX].buffer.length); - cap_hdr->fw_version = - out_obj->package.elements[CAP_FW_VER_IDX].integer.value; - cap_hdr->code_rt_version = - out_obj->package.elements[CAP_CODE_RT_VER_IDX].integer.value; + elem[CAP_CODE_TYPE_IDX].buffer.pointer, + elem[CAP_CODE_TYPE_IDX].buffer.length); + cap_hdr->fw_version = elem[CAP_FW_VER_IDX].integer.value; + cap_hdr->code_rt_version = elem[CAP_CODE_RT_VER_IDX].integer.value; memcpy(&cap_hdr->drv_type, - out_obj->package.elements[CAP_DRV_TYPE_IDX].buffer.pointer, - out_obj->package.elements[CAP_DRV_TYPE_IDX].buffer.length); - cap_hdr->drv_rt_version = - out_obj->package.elements[CAP_DRV_RT_VER_IDX].integer.value; - cap_hdr->drv_svn = - out_obj->package.elements[CAP_DRV_SVN_IDX].integer.value; + elem[CAP_DRV_TYPE_IDX].buffer.pointer, + elem[CAP_DRV_TYPE_IDX].buffer.length); + cap_hdr->drv_rt_version = elem[CAP_DRV_RT_VER_IDX].integer.value; + cap_hdr->drv_svn = elem[CAP_DRV_SVN_IDX].integer.value; memcpy(&cap_hdr->platform_id, - out_obj->package.elements[CAP_PLAT_ID_IDX].buffer.pointer, - out_obj->package.elements[CAP_PLAT_ID_IDX].buffer.length); + elem[CAP_PLAT_ID_IDX].buffer.pointer, + elem[CAP_PLAT_ID_IDX].buffer.length); memcpy(&cap_hdr->oem_id, - out_obj->package.elements[CAP_OEM_ID_IDX].buffer.pointer, - out_obj->package.elements[CAP_OEM_ID_IDX].buffer.length); - cap_hdr->oem_info_len = - out_obj->package.elements[CAP_OEM_INFO_IDX].buffer.length; + elem[CAP_OEM_ID_IDX].buffer.pointer, + elem[CAP_OEM_ID_IDX].buffer.length); + cap_hdr->oem_info_len = elem[CAP_OEM_INFO_IDX].buffer.length; ret = 0; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 23a4e207a01e..922ba9803a93 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -954,6 +954,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) INIT_LIST_HEAD(&resource->list_node); INIT_LIST_HEAD(&resource->dependents); device->power.state = ACPI_STATE_UNKNOWN; + device->flags.initialized = true; /* Evaluate the object to get the system level and resource order. */ status = acpi_evaluate_object(handle, NULL, NULL, &buffer); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9df1d76fbf2b..7dcf784199fa 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -520,12 +520,10 @@ static void acpi_device_release(struct device *dev) kfree(acpi_dev); } -static void acpi_device_del(struct acpi_device *device) +static void acpi_device_cleanup(struct acpi_device *device) { struct acpi_device_bus_id *acpi_device_bus_id; - mutex_lock(&acpi_device_lock); - list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) if (!strcmp(acpi_device_bus_id->bus_id, acpi_device_hid(device))) { @@ -540,6 +538,13 @@ static void acpi_device_del(struct acpi_device *device) } list_del(&device->wakeup_list); +} + +static void acpi_device_del(struct acpi_device *device) +{ + mutex_lock(&acpi_device_lock); + + acpi_device_cleanup(device); mutex_unlock(&acpi_device_lock); @@ -799,7 +804,7 @@ int acpi_device_add(struct acpi_device *device) err: mutex_lock(&acpi_device_lock); - list_del(&device->wakeup_list); + acpi_device_cleanup(device); err_unlock: mutex_unlock(&acpi_device_lock); @@ -1139,9 +1144,6 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources)) device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1; } - - if (acpi_bus_init_power(device)) - device->flags.power_manageable = 0; } static void acpi_bus_get_flags(struct acpi_device *device) @@ -1823,7 +1825,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, acpi_set_pnp_ids(handle, &device->pnp, type); acpi_init_properties(device); acpi_bus_get_flags(device); - device->flags.initialized = true; device->flags.enumeration_by_parent = acpi_device_enumeration_by_parent(device); acpi_device_clear_enumerated(device); @@ -2209,29 +2210,27 @@ static void acpi_create_video_bus_device(struct acpi_device *adev, struct auxiliary_device *aux_dev; static unsigned int aux_dev_id; + struct device *phys_parent __free(put_device) = acpi_bus_get_primary_device(parent); + if (!phys_parent) + return; + aux_dev = kzalloc_obj(*aux_dev); if (!aux_dev) return; aux_dev->id = aux_dev_id++; aux_dev->name = "video_bus"; - aux_dev->dev.parent = acpi_get_first_physical_node(parent); - if (!aux_dev->dev.parent) - goto err; - + aux_dev->dev.parent = phys_parent; aux_dev->dev.release = acpi_video_bus_device_release; - if (auxiliary_device_init(aux_dev)) - goto err; + if (auxiliary_device_init(aux_dev)) { + kfree(aux_dev); + return; + } ACPI_COMPANION_SET(&aux_dev->dev, adev); if (__auxiliary_device_add(aux_dev, "acpi")) auxiliary_device_uninit(aux_dev); - - return; - -err: - kfree(aux_dev); } struct acpi_scan_system_dev { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ec3e143caabe..1a45e0d521d8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -646,6 +646,7 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler); int acpi_bus_scan(acpi_handle handle); void acpi_bus_trim(struct acpi_device *start); acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd); +struct device *acpi_bus_get_primary_device(struct acpi_device *adev); int acpi_match_device_ids(struct acpi_device *device, const struct acpi_device_id *ids); void acpi_set_modalias(struct acpi_device *adev, const char *default_id, @@ -948,6 +949,11 @@ int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices); u32 arch_acpi_add_auto_dep(acpi_handle handle); #else /* CONFIG_ACPI */ +static inline struct device *acpi_bus_get_primary_device(struct acpi_device *adev) +{ + return NULL; +} + static inline int register_acpi_bus_type(void *bus) { return 0; } static inline int unregister_acpi_bus_type(void *bus) { return 0; }