diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-26 14:06:08 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-08-26 14:06:08 -0700 |
| commit | 3382bfbca58c7d5ee3f31a7b37fbeb208e98e656 (patch) | |
| tree | 4b3bc4d8d1c8a347911d736623163af15968e5cd /drivers | |
| parent | 502d45774af09f1c681c754c4b7cdfb5d7f72fd9 (diff) | |
| parent | ea10c0b334e0dca944de2b5ecf57cf7e366674f4 (diff) | |
| download | linux-3382bfbca58c7d5ee3f31a7b37fbeb208e98e656.tar.gz linux-3382bfbca58c7d5ee3f31a7b37fbeb208e98e656.zip | |
Merge tag 'acpi-7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more ACPI support updates from Rafael Wysocki:
"These update documentation to reflect recent changes in the upstream
ACPICA project, fix issues in the core ACPI device enumeration code
(one of which has been introduced recently), improve the primary
"physical" device lookup for ACPI device objects in that code, and
update ACPI device drivers:
- Update MAINTAINERS, CREDITS and ACPI subsystem documentation to
reflect recent changes in the upstream ACPICA project (Rafael
Wysocki)
- Prevent the core ACPI enumeration code from combining device
resources that overlap completely in order to avoid resource
conflicts during platform device registration because there are
drivers that expect such resources to be present (Rafael Wysocki)
- Defer device power initialization during ACPI-based device
enumeration to the point when the given device is known to be
present and functional and all of its dependencies have been met
(Peixin Xie)
- Fix bus ID cleanup on device_add() failures during ACPI device
object registration (Hongyan Xu)
- Introduce a new helper function for looking up the primary
"physical" device for a given ACPI device object and update the
core ACPI device enumeration code to use that function (Rafael
Wysocki)
- Protect all battery properties with a separated mutex in the ACPI
battery driver to prevent race conditions from occurring and avoid
evaluating the _BST ACPI control method multiple times in parallel
for the same battery device (Rong Zhang)
- Add DMI quirk for the Razer Blade Pro 17 early 2020 lid switch to
the ACPI button driver (Robin Everaars)
- Convert fixed clock rates in the ACPI driver for AMD SoCs (APD) to
use HZ_PER_MHZ and add a clock frequency for the HJMC01 I2C
controller to it (Hongnan Li and Xiangyang Yu)
- Fix a stack buffer overflow in query_capability() in the ACPI
platform firmware runtime update driver (Anirudh Prasad)"
* tag 'acpi-7.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI: button: Add DMI quirk for Razer Blade Pro 17 early 2020 lid switch
ACPI: scan: Do not combine resources that overlap completely
ACPI: Update upstream ACPICA repository URL in documentation
ACPI: Update MAINTAINERS entry for ACPICA
ACPI: Add Bob Moore to CREDITS
ACPI: pfr_update: fix stack buffer overflow in query_capability()
ACPI: scan: Defer device power initialization
ACPI: APD: Add clock frequency for HJMC01 I2C controller
ACPI: APD: Convert fixed clock rates to use HZ_PER_MHZ
ACPI: scan: Use acpi_bus_get_primary_device()
ACPI: platform: Use acpi_bus_get_primary_device()
ACPI: bus: Introduce acpi_bus_get_primary_device()
ACPI: scan: fix bus ID cleanup on device_add() failures
ACPI: battery: Protect all properties with a separated mutex
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/acpi/acpi_apd.c | 35 | ||||
| -rw-r--r-- | drivers/acpi/acpi_platform.c | 24 | ||||
| -rw-r--r-- | drivers/acpi/battery.c | 147 | ||||
| -rw-r--r-- | drivers/acpi/bus.c | 54 | ||||
| -rw-r--r-- | drivers/acpi/button.c | 11 | ||||
| -rw-r--r-- | drivers/acpi/pfr_update.c | 45 | ||||
| -rw-r--r-- | drivers/acpi/power.c | 1 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 37 |
8 files changed, 228 insertions, 126 deletions
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 <linux/io.h> #include <linux/platform_data/clk-fch.h> #include <linux/platform_device.h> +#include <linux/units.h> #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 <linux/kernel.h> #include <linux/kfifo.h> #include <linux/list.h> +#include <linux/lockdep.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/platform_device.h> @@ -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_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 - Get first physical node of an ACPI 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; - - mutex_lock(physical_node_lock); - if (list_empty(&adev->physical_node_list)) { - phys_dev = NULL; - } else { - const struct acpi_device_physical_node *node; + guard(mutex)(&adev->physical_node_lock); - 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 @@ -135,6 +135,17 @@ static const struct dmi_system_id dmi_lid_quirks[] = { }, { /* + * 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 * lid closed. */ 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 { |
