mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'acpi-driver'
Merge updates of core ACPI device drivers for 7.2-rc1: - Fix multiple issues related to probe, removal and missing NVDIMM device notifications in the ACPI NFIT driver (Rafael Wysocki) - Add support for devres-based management of ACPI notify handlers to the ACPI core (Rafael Wysocki) - Switch multiple core ACPI device drivers (including the ACPI PAD, ACPI video bus, ACPI HED, ACPI thermal zone, ACPI AC, ACPI battery, and ACPI NFIT drivers) over to using devres-based resource management during probe (Rafael Wysocki) - Replace mutex_lock/unlock() with guard()/scoped_guard() in the ACPI PMIC driver (Maxwell Doose) - Fix message kref handling in the dead device path of the ACPI IPMI address space handler (Yuho Choi) - Use sysfs_emit() in idlecpus_show() in the ACPI processor aggregator device (PAD) driver (Yury Norov) - Clean up device_id_scheme initialization in the ACPI video bus driver (Jean-Ralph Aviles) * acpi-driver: (26 commits) ACPI: IPMI: Fix message kref handling on dead device ACPI: NFIT: core: Fix possible deadlock and missing notifications ACPI: NFIT: core: Eliminate redundant local variable ACPI: NFIT: core: Fix acpi_nfit_init() error cleanup ACPI: NFIT: core: Fix possible NULL pointer dereference ACPI: bus: Clean up devm_acpi_install_notify_handler() ACPI: PAD: Use sysfs_emit() in idlecpus_show() ACPI: video: Do not initialise device_id_scheme directly ACPI: video: Switch over to devres-based resource management ACPI: video: Use devm for video->entry and backlight cleanup ACPI: video: Use devm action for freeing video devices ACPI: video: Use devm action for video bus object cleanup ACPI: video: Rearrange probe and remove code ACPI: video: Reduce the number of auxiliary device dereferences ACPI: PAD: Switch over to devres-based resource management ACPI: PAD: Fix teardown ordering in acpi_pad_remove() ACPI: PAD: Pass struct device pointer to acpi_pad_notify() ACPI: PAD: Rearrange acpi_pad_notify() ACPI: thermal: Switch over to devres-based resource management ACPI: HED: Switch over to devres-based resource management ...
This commit is contained in:
commit
9a0d10fed1
|
|
@ -193,6 +193,7 @@ static const struct dmi_system_id ac_dmi_table[] __initconst = {
|
|||
static int acpi_ac_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpi_device *adev;
|
||||
struct acpi_ac *ac;
|
||||
int result;
|
||||
|
|
@ -201,7 +202,7 @@ static int acpi_ac_probe(struct platform_device *pdev)
|
|||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
ac = kzalloc_obj(struct acpi_ac);
|
||||
ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL);
|
||||
if (!ac)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -211,7 +212,7 @@ static int acpi_ac_probe(struct platform_device *pdev)
|
|||
|
||||
result = acpi_ac_get_state(ac);
|
||||
if (result)
|
||||
goto err_release_ac;
|
||||
return result;
|
||||
|
||||
psy_cfg.drv_data = ac;
|
||||
|
||||
|
|
@ -220,33 +221,22 @@ static int acpi_ac_probe(struct platform_device *pdev)
|
|||
ac->charger_desc.properties = ac_props;
|
||||
ac->charger_desc.num_properties = ARRAY_SIZE(ac_props);
|
||||
ac->charger_desc.get_property = get_ac_property;
|
||||
ac->charger = power_supply_register(&pdev->dev,
|
||||
&ac->charger_desc, &psy_cfg);
|
||||
if (IS_ERR(ac->charger)) {
|
||||
result = PTR_ERR(ac->charger);
|
||||
goto err_release_ac;
|
||||
}
|
||||
ac->charger = devm_power_supply_register(dev, &ac->charger_desc, &psy_cfg);
|
||||
if (IS_ERR(ac->charger))
|
||||
return PTR_ERR(ac->charger);
|
||||
|
||||
pr_info("AC Adapter [%s] (%s-line)\n", acpi_device_bid(adev),
|
||||
str_on_off(ac->state));
|
||||
|
||||
result = devm_acpi_install_notify_handler(dev, ACPI_ALL_NOTIFY,
|
||||
acpi_ac_notify, ac);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
ac->battery_nb.notifier_call = acpi_ac_battery_notify;
|
||||
register_acpi_notifier(&ac->battery_nb);
|
||||
|
||||
result = acpi_dev_install_notify_handler(adev, ACPI_ALL_NOTIFY,
|
||||
acpi_ac_notify, ac);
|
||||
if (result)
|
||||
goto err_unregister;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister:
|
||||
power_supply_unregister(ac->charger);
|
||||
unregister_acpi_notifier(&ac->battery_nb);
|
||||
err_release_ac:
|
||||
kfree(ac);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -271,12 +261,7 @@ static void acpi_ac_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct acpi_ac *ac = platform_get_drvdata(pdev);
|
||||
|
||||
acpi_dev_remove_notify_handler(ac->device, ACPI_ALL_NOTIFY,
|
||||
acpi_ac_notify);
|
||||
power_supply_unregister(ac->charger);
|
||||
unregister_acpi_notifier(&ac->battery_nb);
|
||||
|
||||
kfree(ac);
|
||||
}
|
||||
|
||||
static struct platform_driver acpi_ac_driver = {
|
||||
|
|
|
|||
|
|
@ -550,7 +550,6 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
|
|||
return AE_TYPE;
|
||||
}
|
||||
|
||||
acpi_ipmi_msg_get(tx_msg);
|
||||
mutex_lock(&driver_data.ipmi_lock);
|
||||
/* Do not add a tx_msg that can not be flushed. */
|
||||
if (ipmi_device->dead) {
|
||||
|
|
@ -558,6 +557,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
|
|||
ipmi_msg_release(tx_msg);
|
||||
return AE_NOT_EXIST;
|
||||
}
|
||||
acpi_ipmi_msg_get(tx_msg);
|
||||
spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
|
||||
list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
|
||||
spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
static DEFINE_MUTEX(isolated_cpus_lock);
|
||||
static DEFINE_MUTEX(round_robin_lock);
|
||||
|
||||
static bool acpi_pad_teardown;
|
||||
|
||||
static unsigned int power_saving_mwait_eax;
|
||||
|
||||
static unsigned char tsc_detected_unstable;
|
||||
|
|
@ -334,8 +336,8 @@ static ssize_t idlecpus_store(struct device *dev,
|
|||
static ssize_t idlecpus_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return cpumap_print_to_pagebuf(false, buf,
|
||||
to_cpumask(pad_busy_cpus_bits));
|
||||
return sysfs_emit(buf, "%*pb\n",
|
||||
cpumask_pr_args(to_cpumask(pad_busy_cpus_bits)));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(idlecpus);
|
||||
|
|
@ -359,6 +361,9 @@ static int acpi_pad_pur(acpi_handle handle)
|
|||
union acpi_object *package;
|
||||
int num = -1;
|
||||
|
||||
if (unlikely(acpi_pad_teardown))
|
||||
return -1;
|
||||
|
||||
if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer)))
|
||||
return num;
|
||||
|
||||
|
|
@ -407,40 +412,29 @@ static void acpi_pad_handle_notify(acpi_handle handle)
|
|||
|
||||
static void acpi_pad_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_device *adev = data;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_PROCESSOR_AGGREGATOR_NOTIFY:
|
||||
acpi_pad_handle_notify(handle);
|
||||
acpi_bus_generate_netlink_event("acpi_pad",
|
||||
dev_name(&adev->dev), event, 0);
|
||||
break;
|
||||
default:
|
||||
if (event != ACPI_PROCESSOR_AGGREGATOR_NOTIFY) {
|
||||
pr_warn("Unsupported event [0x%x]\n", event);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_pad_handle_notify(handle);
|
||||
acpi_bus_generate_netlink_event("acpi_pad", dev_name(data), event, 0);
|
||||
}
|
||||
|
||||
static int acpi_pad_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev;
|
||||
acpi_pad_teardown = false;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
|
||||
return acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_pad_notify, adev);
|
||||
return devm_acpi_install_notify_handler(&pdev->dev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_pad_notify, &pdev->dev);
|
||||
}
|
||||
|
||||
static void acpi_pad_remove(struct platform_device *pdev)
|
||||
{
|
||||
mutex_lock(&isolated_cpus_lock);
|
||||
acpi_pad_teardown = true;
|
||||
acpi_pad_idle_cpus(0);
|
||||
mutex_unlock(&isolated_cpus_lock);
|
||||
|
||||
acpi_dev_remove_notify_handler(ACPI_COMPANION(&pdev->dev),
|
||||
ACPI_DEVICE_NOTIFY, acpi_pad_notify);
|
||||
}
|
||||
|
||||
static const struct acpi_device_id pad_device_ids[] = {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ MODULE_PARM_DESC(hw_changes_brightness,
|
|||
* Whether the struct acpi_video_device_attrib::device_id_scheme bit should be
|
||||
* assumed even if not actually set.
|
||||
*/
|
||||
static bool device_id_scheme = false;
|
||||
static bool device_id_scheme;
|
||||
module_param(device_id_scheme, bool, 0444);
|
||||
|
||||
static int only_lcd;
|
||||
|
|
@ -76,7 +76,6 @@ static DEFINE_MUTEX(video_list_lock);
|
|||
static LIST_HEAD(video_bus_head);
|
||||
static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
||||
const struct auxiliary_device_id *id);
|
||||
static void acpi_video_bus_remove(struct auxiliary_device *aux);
|
||||
static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data);
|
||||
|
||||
/*
|
||||
|
|
@ -99,7 +98,6 @@ MODULE_DEVICE_TABLE(auxiliary, video_bus_auxiliary_id_table);
|
|||
|
||||
static struct auxiliary_driver acpi_video_bus = {
|
||||
.probe = acpi_video_bus_probe,
|
||||
.remove = acpi_video_bus_remove,
|
||||
.id_table = video_bus_auxiliary_id_table,
|
||||
};
|
||||
|
||||
|
|
@ -1494,10 +1492,31 @@ int acpi_video_get_edid(struct acpi_device *device, int type, int device_id,
|
|||
}
|
||||
EXPORT_SYMBOL(acpi_video_get_edid);
|
||||
|
||||
static int
|
||||
acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
||||
struct acpi_device *device)
|
||||
static void acpi_video_bus_put_devices(void *data)
|
||||
{
|
||||
struct acpi_video_bus *video = data;
|
||||
struct acpi_video_device *dev, *next;
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
|
||||
list_del(&dev->entry);
|
||||
kfree(dev);
|
||||
}
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
|
||||
kfree(video->attached_array);
|
||||
video->attached_array = NULL;
|
||||
}
|
||||
|
||||
static int devm_acpi_video_bus_get_devices(struct device *dev,
|
||||
struct acpi_video_bus *video)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = devm_add_action(dev, acpi_video_bus_put_devices, video);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* There are systems where video module known to work fine regardless
|
||||
* of broken _DOD and ignoring returned value here doesn't cause
|
||||
|
|
@ -1505,7 +1524,8 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
|
|||
*/
|
||||
acpi_video_device_enumerate(video);
|
||||
|
||||
return acpi_dev_for_each_child(device, acpi_video_bus_get_one_device, video);
|
||||
return acpi_dev_for_each_child(video->device,
|
||||
acpi_video_bus_get_one_device, video);
|
||||
}
|
||||
|
||||
/* acpi_video interface */
|
||||
|
|
@ -1923,8 +1943,9 @@ static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
|
||||
static void acpi_video_bus_remove_notify_handler(void *data)
|
||||
{
|
||||
struct acpi_video_bus *video = data;
|
||||
struct acpi_video_device *dev;
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
|
|
@ -1939,18 +1960,23 @@ static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
|
|||
video->input = NULL;
|
||||
}
|
||||
|
||||
static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
|
||||
static void acpi_video_bus_free(void *data)
|
||||
{
|
||||
struct acpi_video_device *dev, *next;
|
||||
struct acpi_video_bus *video = data;
|
||||
|
||||
mutex_lock(&video->device_list_lock);
|
||||
list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
|
||||
list_del(&dev->entry);
|
||||
kfree(dev);
|
||||
}
|
||||
mutex_unlock(&video->device_list_lock);
|
||||
video->device->driver_data = NULL;
|
||||
kfree(video);
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void acpi_video_bus_del(void *data)
|
||||
{
|
||||
struct acpi_video_bus *video = data;
|
||||
|
||||
mutex_lock(&video_list_lock);
|
||||
list_del(&video->entry);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
}
|
||||
|
||||
static int duplicate_dev_check(struct device *sibling, void *data)
|
||||
|
|
@ -1978,7 +2004,8 @@ static bool acpi_video_bus_dev_is_duplicate(struct device *dev)
|
|||
static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
||||
const struct auxiliary_device_id *id_unused)
|
||||
{
|
||||
struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev);
|
||||
struct device *dev = &aux_dev->dev;
|
||||
struct acpi_device *device = ACPI_COMPANION(dev);
|
||||
static DEFINE_MUTEX(probe_lock);
|
||||
struct acpi_video_bus *video;
|
||||
static int instance;
|
||||
|
|
@ -1988,7 +2015,7 @@ static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
|||
/* Probe one video bus device at a time in case there are duplicates. */
|
||||
guard(mutex)(&probe_lock);
|
||||
|
||||
if (!allow_duplicates && acpi_video_bus_dev_is_duplicate(&aux_dev->dev)) {
|
||||
if (!allow_duplicates && acpi_video_bus_dev_is_duplicate(dev)) {
|
||||
pr_info(FW_BUG
|
||||
"Duplicate ACPI video bus devices for the"
|
||||
" same VGA controller, please try module "
|
||||
|
|
@ -2001,6 +2028,13 @@ static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
|||
if (!video)
|
||||
return -ENOMEM;
|
||||
|
||||
video->device = device;
|
||||
device->driver_data = video;
|
||||
|
||||
error = devm_add_action_or_reset(dev, acpi_video_bus_free, video);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* A hack to fix the duplicate name "VID" problem on T61 and the
|
||||
* duplicate name "VGA" problem on Pa 3553.
|
||||
|
|
@ -2015,20 +2049,17 @@ static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
|||
|
||||
auxiliary_set_drvdata(aux_dev, video);
|
||||
|
||||
video->device = device;
|
||||
device->driver_data = video;
|
||||
|
||||
acpi_video_bus_find_cap(video);
|
||||
error = acpi_video_bus_check(video);
|
||||
if (error)
|
||||
goto err_free_video;
|
||||
return error;
|
||||
|
||||
mutex_init(&video->device_list_lock);
|
||||
INIT_LIST_HEAD(&video->video_device_list);
|
||||
|
||||
error = acpi_video_bus_get_devices(video, device);
|
||||
error = devm_acpi_video_bus_get_devices(dev, video);
|
||||
if (error)
|
||||
goto err_put_video;
|
||||
return error;
|
||||
|
||||
/*
|
||||
* HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0
|
||||
|
|
@ -2040,10 +2071,6 @@ static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
|||
acpi_device_bid(device), str_yes_no(video->flags.multihead),
|
||||
str_yes_no(video->flags.rom), str_yes_no(video->flags.post));
|
||||
|
||||
mutex_lock(&video_list_lock);
|
||||
list_add_tail(&video->entry, &video_bus_head);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
/*
|
||||
* If backlight-type auto-detection is used then a native backlight may
|
||||
* show up later and this may change the result from video to native.
|
||||
|
|
@ -2059,53 +2086,25 @@ static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
|
|||
!auto_detect)
|
||||
acpi_video_bus_register_backlight(video);
|
||||
|
||||
error = acpi_video_bus_add_notify_handler(video, &aux_dev->dev);
|
||||
if (error)
|
||||
goto err_del;
|
||||
mutex_lock(&video_list_lock);
|
||||
list_add_tail(&video->entry, &video_bus_head);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
error = devm_add_action_or_reset(dev, acpi_video_bus_del, video);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = acpi_video_bus_add_notify_handler(video, dev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = devm_add_action_or_reset(dev, acpi_video_bus_remove_notify_handler,
|
||||
video);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return devm_acpi_install_notify_handler(dev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify, video);
|
||||
if (error)
|
||||
goto err_remove;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove:
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
err_del:
|
||||
mutex_lock(&video_list_lock);
|
||||
list_del(&video->entry);
|
||||
mutex_unlock(&video_list_lock);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
err_put_video:
|
||||
acpi_video_bus_put_devices(video);
|
||||
kfree(video->attached_array);
|
||||
err_free_video:
|
||||
kfree(video);
|
||||
device->driver_data = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void acpi_video_bus_remove(struct auxiliary_device *aux_dev)
|
||||
{
|
||||
struct acpi_video_bus *video = auxiliary_get_drvdata(aux_dev);
|
||||
struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev);
|
||||
|
||||
acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_video_bus_notify);
|
||||
|
||||
mutex_lock(&video_list_lock);
|
||||
list_del(&video->entry);
|
||||
mutex_unlock(&video_list_lock);
|
||||
|
||||
acpi_video_bus_remove_notify_handler(video);
|
||||
acpi_video_bus_unregister_backlight(video);
|
||||
acpi_video_bus_put_devices(video);
|
||||
|
||||
kfree(video->attached_array);
|
||||
kfree(video);
|
||||
device->driver_data = NULL;
|
||||
}
|
||||
|
||||
static int __init is_i740(struct pci_dev *dev)
|
||||
|
|
|
|||
|
|
@ -1182,6 +1182,26 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
|||
{},
|
||||
};
|
||||
|
||||
static void acpi_battery_wakeup_cleanup(void *data)
|
||||
{
|
||||
device_init_wakeup(data, false);
|
||||
}
|
||||
|
||||
static int devm_acpi_battery_init_wakeup(struct device *dev)
|
||||
{
|
||||
device_init_wakeup(dev, true);
|
||||
return devm_add_action_or_reset(dev, acpi_battery_wakeup_cleanup, dev);
|
||||
}
|
||||
|
||||
static void sysfs_battery_cleanup(void *data)
|
||||
{
|
||||
struct acpi_battery *battery = data;
|
||||
|
||||
guard(mutex)(&battery->update_lock);
|
||||
|
||||
sysfs_remove_battery(battery);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some machines'(E,G Lenovo Z480) ECs are not stable
|
||||
* during boot up and this causes battery driver fails to be
|
||||
|
|
@ -1190,10 +1210,15 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
|
|||
* may work. So add retry code here and 20ms sleep between
|
||||
* every retries.
|
||||
*/
|
||||
static int acpi_battery_update_retry(struct acpi_battery *battery)
|
||||
static int devm_acpi_battery_update_retry(struct device *dev,
|
||||
struct acpi_battery *battery)
|
||||
{
|
||||
int retry, ret;
|
||||
|
||||
ret = devm_add_action(dev, sysfs_battery_cleanup, battery);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
guard(mutex)(&battery->update_lock);
|
||||
|
||||
for (retry = 5; retry; retry--) {
|
||||
|
|
@ -1206,27 +1231,21 @@ static int acpi_battery_update_retry(struct acpi_battery *battery)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void sysfs_battery_cleanup(struct acpi_battery *battery)
|
||||
{
|
||||
guard(mutex)(&battery->update_lock);
|
||||
|
||||
sysfs_remove_battery(battery);
|
||||
}
|
||||
|
||||
static int acpi_battery_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpi_battery *battery;
|
||||
struct acpi_device *device;
|
||||
int result;
|
||||
|
||||
device = ACPI_COMPANION(&pdev->dev);
|
||||
device = ACPI_COMPANION(dev);
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
if (device->dep_unmet)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
battery = devm_kzalloc(&pdev->dev, sizeof(*battery), GFP_KERNEL);
|
||||
battery = devm_kzalloc(dev, sizeof(*battery), GFP_KERNEL);
|
||||
if (!battery)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -1235,54 +1254,38 @@ static int acpi_battery_probe(struct platform_device *pdev)
|
|||
battery->phys_dev = &pdev->dev;
|
||||
battery->device = device;
|
||||
|
||||
result = devm_mutex_init(&pdev->dev, &battery->update_lock);
|
||||
result = devm_mutex_init(dev, &battery->update_lock);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (acpi_has_method(battery->device->handle, "_BIX"))
|
||||
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
|
||||
|
||||
result = acpi_battery_update_retry(battery);
|
||||
result = devm_acpi_battery_update_retry(dev, battery);
|
||||
if (result)
|
||||
goto fail;
|
||||
return result;
|
||||
|
||||
pr_info("Slot [%s] (battery %s)\n", acpi_device_bid(device),
|
||||
device->status.battery_present ? "present" : "absent");
|
||||
|
||||
result = devm_acpi_battery_init_wakeup(dev);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = devm_acpi_install_notify_handler(dev, ACPI_ALL_NOTIFY,
|
||||
acpi_battery_notify, battery);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
battery->pm_nb.notifier_call = battery_notify;
|
||||
result = register_pm_notifier(&battery->pm_nb);
|
||||
if (result)
|
||||
goto fail;
|
||||
|
||||
device_init_wakeup(&pdev->dev, true);
|
||||
|
||||
result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY,
|
||||
acpi_battery_notify, battery);
|
||||
if (result)
|
||||
goto fail_pm;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_pm:
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
unregister_pm_notifier(&battery->pm_nb);
|
||||
fail:
|
||||
sysfs_battery_cleanup(battery);
|
||||
|
||||
return result;
|
||||
return register_pm_notifier(&battery->pm_nb);
|
||||
}
|
||||
|
||||
static void acpi_battery_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_battery *battery = platform_get_drvdata(pdev);
|
||||
|
||||
acpi_dev_remove_notify_handler(battery->device, ACPI_ALL_NOTIFY,
|
||||
acpi_battery_notify);
|
||||
|
||||
device_init_wakeup(&pdev->dev, false);
|
||||
unregister_pm_notifier(&battery->pm_nb);
|
||||
|
||||
sysfs_battery_cleanup(battery);
|
||||
}
|
||||
|
||||
/* this is needed to learn about changes made in suspended state */
|
||||
|
|
|
|||
|
|
@ -679,6 +679,73 @@ void acpi_dev_remove_notify_handler(struct acpi_device *adev,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_dev_remove_notify_handler);
|
||||
|
||||
struct acpi_notify_handler_devres {
|
||||
struct acpi_device *adev;
|
||||
acpi_notify_handler handler;
|
||||
u32 handler_type;
|
||||
};
|
||||
|
||||
static void devm_acpi_notify_handler_release(struct device *dev, void *res)
|
||||
{
|
||||
struct acpi_notify_handler_devres *dr = res;
|
||||
|
||||
acpi_dev_remove_notify_handler(dr->adev, dr->handler_type, dr->handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_acpi_install_notify_handler - Install an ACPI notify handler for a
|
||||
* managed device
|
||||
* @dev: Device to install a notify handler for
|
||||
* @handler_type: Type of the notify handler
|
||||
* @handler: Handler function to install
|
||||
* @context: Data passed back to the handler function
|
||||
*
|
||||
* This function performs the same function as acpi_dev_install_notify_handler()
|
||||
* called for the ACPI companion of @dev with the same @handler_type, @handler,
|
||||
* and @context arguments, but the ACPI notify handler installed by it will be
|
||||
* automatically removed on driver detach.
|
||||
*
|
||||
* Callers should ensure that all resources used by @handler have been allocated
|
||||
* prior to invoking this function, in which case those resources should be
|
||||
* devres-managed so that they won't be released before the notify handler
|
||||
* removal. Otherwise, special synchronization between @handler and the
|
||||
* management of those resources is required.
|
||||
*
|
||||
* When the request fails, an error message is printed. Don't add extra error
|
||||
* messages at the call sites.
|
||||
*
|
||||
* Return: 0 on success or a negative error number.
|
||||
*/
|
||||
int devm_acpi_install_notify_handler(struct device *dev, u32 handler_type,
|
||||
acpi_notify_handler handler, void *context)
|
||||
{
|
||||
struct acpi_notify_handler_devres *dr;
|
||||
struct acpi_device *adev;
|
||||
int ret;
|
||||
|
||||
adev = ACPI_COMPANION(dev);
|
||||
if (!adev)
|
||||
return dev_err_probe(dev, -ENODEV, "No ACPI companion\n");
|
||||
|
||||
dr = devres_alloc(devm_acpi_notify_handler_release, sizeof(*dr), GFP_KERNEL);
|
||||
if (!dr)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = acpi_dev_install_notify_handler(adev, handler_type, handler, context);
|
||||
if (ret) {
|
||||
devres_free(dr);
|
||||
return dev_err_probe(dev, ret, "Failed to install an ACPI notify handler\n");
|
||||
}
|
||||
|
||||
dr->adev = adev;
|
||||
dr->handler = handler;
|
||||
dr->handler_type = handler_type;
|
||||
devres_add(dev, dr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_acpi_install_notify_handler);
|
||||
|
||||
/* Handle events targeting \_SB device (at present only graceful shutdown) */
|
||||
|
||||
#define ACPI_SB_NOTIFY_SHUTDOWN_REQUEST 0x81
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ static const struct acpi_device_id acpi_hed_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(acpi, acpi_hed_ids);
|
||||
|
||||
static acpi_handle hed_handle;
|
||||
static bool hed_present;
|
||||
|
||||
static BLOCKING_NOTIFIER_HEAD(acpi_hed_notify_list);
|
||||
|
||||
|
|
@ -50,33 +50,24 @@ static void acpi_hed_notify(acpi_handle handle, u32 event, void *data)
|
|||
|
||||
static int acpi_hed_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *device;
|
||||
int err;
|
||||
|
||||
device = ACPI_COMPANION(&pdev->dev);
|
||||
if (!device)
|
||||
return -ENODEV;
|
||||
|
||||
/* Only one hardware error device */
|
||||
if (hed_handle)
|
||||
if (hed_present)
|
||||
return -EINVAL;
|
||||
hed_handle = device->handle;
|
||||
|
||||
err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_hed_notify, device);
|
||||
err = devm_acpi_install_notify_handler(&pdev->dev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_hed_notify, NULL);
|
||||
if (err)
|
||||
hed_handle = NULL;
|
||||
return err;
|
||||
|
||||
return err;
|
||||
hed_present = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_hed_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
|
||||
|
||||
acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_hed_notify);
|
||||
hed_handle = NULL;
|
||||
hed_present = false;
|
||||
}
|
||||
|
||||
static struct platform_driver acpi_hed_driver = {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ MODULE_PARM_DESC(force_labels, "Opt-in to labels despite missing methods");
|
|||
LIST_HEAD(acpi_descs);
|
||||
DEFINE_MUTEX(acpi_desc_lock);
|
||||
|
||||
DEFINE_MUTEX(acpi_notify_lock);
|
||||
|
||||
static struct workqueue_struct *nfit_wq;
|
||||
|
||||
struct nfit_table_prev {
|
||||
|
|
@ -1680,7 +1682,6 @@ static struct nvdimm *acpi_nfit_dimm_by_handle(struct acpi_nfit_desc *acpi_desc,
|
|||
void __acpi_nvdimm_notify(struct device *dev, u32 event)
|
||||
{
|
||||
struct nfit_mem *nfit_mem;
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
|
||||
dev_dbg(dev->parent, "%s: event: %d\n", dev_name(dev),
|
||||
event);
|
||||
|
|
@ -1691,12 +1692,11 @@ void __acpi_nvdimm_notify(struct device *dev, u32 event)
|
|||
return;
|
||||
}
|
||||
|
||||
acpi_desc = dev_get_drvdata(dev->parent);
|
||||
if (!acpi_desc)
|
||||
if (!dev_get_drvdata(dev->parent))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If we successfully retrieved acpi_desc, then we know nfit_mem data
|
||||
* If the parent's driver data pointer is not NULL, then nfit_mem data
|
||||
* is still valid.
|
||||
*/
|
||||
nfit_mem = dev_get_drvdata(dev);
|
||||
|
|
@ -1710,9 +1710,15 @@ static void acpi_nvdimm_notify(acpi_handle handle, u32 event, void *data)
|
|||
struct acpi_device *adev = data;
|
||||
struct device *dev = &adev->dev;
|
||||
|
||||
device_lock(dev->parent);
|
||||
/*
|
||||
* Locking is needed here for synchronization with driver probe and
|
||||
* removal and the parent's driver data pointer is NULL when teardown
|
||||
* is in progress (while the parent here is expected to be the ACPI
|
||||
* companion of the platform device used for driver binding).
|
||||
*/
|
||||
guard(mutex)(&acpi_notify_lock);
|
||||
|
||||
__acpi_nvdimm_notify(dev, event);
|
||||
device_unlock(dev->parent);
|
||||
}
|
||||
|
||||
static bool acpi_nvdimm_has_method(struct acpi_device *adev, char *method)
|
||||
|
|
@ -3069,6 +3075,8 @@ static void acpi_nfit_unregister(void *data)
|
|||
struct acpi_nfit_desc *acpi_desc = data;
|
||||
|
||||
nvdimm_bus_unregister(acpi_desc->nvdimm_bus);
|
||||
/* The nvdimm_bus object may have been freed, so clear the pointer. */
|
||||
acpi_desc->nvdimm_bus = NULL;
|
||||
}
|
||||
|
||||
int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, void *data, acpi_size sz)
|
||||
|
|
@ -3156,11 +3164,10 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init);
|
|||
static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
|
||||
{
|
||||
struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
|
||||
struct device *dev = acpi_desc->dev;
|
||||
|
||||
/* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
|
||||
device_lock(dev);
|
||||
device_unlock(dev);
|
||||
/* Bounce the notify lock to flush acpi_nfit_probe / acpi_nfit_notify */
|
||||
mutex_lock(&acpi_notify_lock);
|
||||
mutex_unlock(&acpi_notify_lock);
|
||||
|
||||
/* Bounce the init_mutex to complete initial registration */
|
||||
mutex_lock(&acpi_desc->init_mutex);
|
||||
|
|
@ -3292,24 +3299,26 @@ static void acpi_nfit_put_table(void *table)
|
|||
static void acpi_nfit_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
|
||||
device_lock(dev);
|
||||
__acpi_nfit_notify(dev, handle, event);
|
||||
device_unlock(dev);
|
||||
}
|
||||
/*
|
||||
* Locking is needed here for synchronization with driver probe and
|
||||
* removal and the ACPI companion's driver data pointer is NULL when
|
||||
* teardown is in progress.
|
||||
*/
|
||||
guard(mutex)(&acpi_notify_lock);
|
||||
|
||||
static void acpi_nfit_remove_notify_handler(void *data)
|
||||
{
|
||||
struct acpi_device *adev = data;
|
||||
|
||||
acpi_dev_remove_notify_handler(adev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_nfit_notify);
|
||||
if (dev_get_drvdata(&adev->dev))
|
||||
__acpi_nfit_notify(dev, handle, event);
|
||||
}
|
||||
|
||||
void acpi_nfit_shutdown(void *data)
|
||||
{
|
||||
struct acpi_nfit_desc *acpi_desc = data;
|
||||
struct device *bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus);
|
||||
struct device *bus_dev;
|
||||
|
||||
if (!acpi_desc || !acpi_desc->nvdimm_bus)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Destruct under acpi_desc_lock so that nfit_handle_mce does not
|
||||
|
|
@ -3324,6 +3333,7 @@ void acpi_nfit_shutdown(void *data)
|
|||
mutex_unlock(&acpi_desc->init_mutex);
|
||||
cancel_delayed_work_sync(&acpi_desc->dwork);
|
||||
|
||||
bus_dev = to_nvdimm_bus_dev(acpi_desc->nvdimm_bus);
|
||||
/*
|
||||
* Bounce the nvdimm bus lock to make sure any in-flight
|
||||
* acpi_nfit_ars_rescan() submissions have had a chance to
|
||||
|
|
@ -3341,23 +3351,20 @@ static int acpi_nfit_probe(struct platform_device *pdev)
|
|||
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_nfit_desc *acpi_desc;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpi_device *adev = ACPI_COMPANION(dev);
|
||||
struct acpi_table_header *tbl;
|
||||
struct acpi_device *adev;
|
||||
acpi_status status = AE_OK;
|
||||
acpi_size sz;
|
||||
int rc = 0;
|
||||
|
||||
adev = ACPI_COMPANION(&pdev->dev);
|
||||
if (!adev)
|
||||
return -ENODEV;
|
||||
/*
|
||||
* Prevent acpi_nfit_notify() from progressing until the probe is
|
||||
* complete in case there is a concurrent event to process.
|
||||
*/
|
||||
guard(mutex)(&acpi_notify_lock);
|
||||
|
||||
rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_nfit_notify, dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler,
|
||||
adev);
|
||||
rc = devm_acpi_install_notify_handler(dev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_nfit_notify, dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -3371,6 +3378,11 @@ static int acpi_nfit_probe(struct platform_device *pdev)
|
|||
* data in the format of a series of NFIT Structures.
|
||||
*/
|
||||
dev_dbg(dev, "failed to find NFIT at startup\n");
|
||||
/*
|
||||
* Let acpi_nfit_update_notify() run in case it will need to
|
||||
* allocate the acpi_desc object.
|
||||
*/
|
||||
dev_set_drvdata(&adev->dev, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3405,10 +3417,28 @@ static int acpi_nfit_probe(struct platform_device *pdev)
|
|||
+ sizeof(struct acpi_table_nfit),
|
||||
sz - sizeof(struct acpi_table_nfit));
|
||||
|
||||
if (rc)
|
||||
if (rc) {
|
||||
acpi_nfit_shutdown(acpi_desc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
|
||||
/*
|
||||
* Let notify handlers operate (the actual value of the ACPI companion's
|
||||
* driver data pointer does not matter here so long as it is not NULL).
|
||||
*/
|
||||
dev_set_drvdata(&adev->dev, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void acpi_nfit_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
|
||||
|
||||
guard(mutex)(&acpi_notify_lock);
|
||||
|
||||
/* Make notify handlers bail out early going forward. */
|
||||
dev_set_drvdata(&adev->dev, NULL);
|
||||
acpi_nfit_shutdown(platform_get_drvdata(pdev));
|
||||
}
|
||||
|
||||
static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
|
||||
|
|
@ -3460,6 +3490,9 @@ static void acpi_nfit_uc_error_notify(struct device *dev, acpi_handle handle)
|
|||
{
|
||||
struct acpi_nfit_desc *acpi_desc = dev_get_drvdata(dev);
|
||||
|
||||
if (!acpi_desc)
|
||||
return;
|
||||
|
||||
if (acpi_desc->scrub_mode == HW_ERROR_SCRUB_ON)
|
||||
acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG);
|
||||
else
|
||||
|
|
@ -3489,6 +3522,7 @@ MODULE_DEVICE_TABLE(acpi, acpi_nfit_ids);
|
|||
|
||||
static struct platform_driver acpi_nfit_driver = {
|
||||
.probe = acpi_nfit_probe,
|
||||
.remove = acpi_nfit_remove,
|
||||
.driver = {
|
||||
.name = "acpi-nfit",
|
||||
.acpi_match_table = acpi_nfit_ids,
|
||||
|
|
|
|||
|
|
@ -67,14 +67,12 @@ static acpi_status intel_pmic_power_handler(u32 function,
|
|||
if (result == -ENOENT)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
mutex_lock(&opregion->lock);
|
||||
guard(mutex)(&opregion->lock);
|
||||
|
||||
result = function == ACPI_READ ?
|
||||
d->get_power(regmap, reg, bit, value64) :
|
||||
d->update_power(regmap, reg, bit, *value64 == 1);
|
||||
|
||||
mutex_unlock(&opregion->lock);
|
||||
|
||||
return result ? AE_ERROR : AE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -182,19 +180,16 @@ static acpi_status intel_pmic_thermal_handler(u32 function,
|
|||
if (result == -ENOENT)
|
||||
return AE_BAD_PARAMETER;
|
||||
|
||||
mutex_lock(&opregion->lock);
|
||||
|
||||
if (pmic_thermal_is_temp(address))
|
||||
result = pmic_thermal_temp(opregion, reg, function, value64);
|
||||
else if (pmic_thermal_is_aux(address))
|
||||
result = pmic_thermal_aux(opregion, reg, function, value64);
|
||||
else if (pmic_thermal_is_pen(address))
|
||||
result = pmic_thermal_pen(opregion, reg, bit,
|
||||
function, value64);
|
||||
else
|
||||
result = -EINVAL;
|
||||
|
||||
mutex_unlock(&opregion->lock);
|
||||
scoped_guard(mutex, &opregion->lock) {
|
||||
if (pmic_thermal_is_temp(address))
|
||||
result = pmic_thermal_temp(opregion, reg, function, value64);
|
||||
else if (pmic_thermal_is_aux(address))
|
||||
result = pmic_thermal_aux(opregion, reg, function, value64);
|
||||
else if (pmic_thermal_is_pen(address))
|
||||
result = pmic_thermal_pen(opregion, reg, bit, function, value64);
|
||||
else
|
||||
result = -EINVAL;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
if (result == -EINVAL)
|
||||
|
|
@ -354,13 +349,15 @@ int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
|
|||
|
||||
d = intel_pmic_opregion->data;
|
||||
|
||||
mutex_lock(&intel_pmic_opregion->lock);
|
||||
guard(mutex)(&intel_pmic_opregion->lock);
|
||||
|
||||
if (d->exec_mipi_pmic_seq_element) {
|
||||
ret = d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
|
||||
return d->exec_mipi_pmic_seq_element(intel_pmic_opregion->regmap,
|
||||
i2c_address, reg_address,
|
||||
value, mask);
|
||||
} else if (d->pmic_i2c_address) {
|
||||
}
|
||||
|
||||
if (d->pmic_i2c_address) {
|
||||
if (i2c_address == d->pmic_i2c_address) {
|
||||
ret = regmap_update_bits(intel_pmic_opregion->regmap,
|
||||
reg_address, mask, value);
|
||||
|
|
@ -376,8 +373,6 @@ int intel_soc_pmic_exec_mipi_pmic_seq_element(u16 i2c_address, u32 reg_address,
|
|||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_unlock(&intel_pmic_opregion->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_soc_pmic_exec_mipi_pmic_seq_element);
|
||||
|
|
|
|||
|
|
@ -655,8 +655,12 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz,
|
|||
return result;
|
||||
}
|
||||
|
||||
static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
|
||||
static void acpi_thermal_zone_unregister(void *data)
|
||||
{
|
||||
struct acpi_thermal *tz = data;
|
||||
|
||||
flush_workqueue(acpi_thermal_pm_queue);
|
||||
|
||||
thermal_zone_device_disable(tz->thermal_zone);
|
||||
acpi_thermal_zone_sysfs_remove(tz);
|
||||
thermal_zone_device_unregister(tz->thermal_zone);
|
||||
|
|
@ -765,8 +769,9 @@ static void acpi_thermal_check_fn(struct work_struct *work)
|
|||
mutex_unlock(&tz->thermal_check_lock);
|
||||
}
|
||||
|
||||
static void acpi_thermal_free_thermal_zone(struct acpi_thermal *tz)
|
||||
static void acpi_thermal_zone_free(void *data)
|
||||
{
|
||||
struct acpi_thermal *tz = data;
|
||||
int i;
|
||||
|
||||
acpi_handle_list_free(&tz->trips.passive.trip.devices);
|
||||
|
|
@ -779,7 +784,8 @@ static void acpi_thermal_free_thermal_zone(struct acpi_thermal *tz)
|
|||
static int acpi_thermal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct thermal_trip trip_table[ACPI_THERMAL_MAX_NR_TRIPS] = { 0 };
|
||||
struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct acpi_device *device = ACPI_COMPANION(dev);
|
||||
struct acpi_thermal_trip *acpi_trip;
|
||||
struct thermal_trip *trip;
|
||||
struct acpi_thermal *tz;
|
||||
|
|
@ -795,6 +801,10 @@ static int acpi_thermal_probe(struct platform_device *pdev)
|
|||
if (!tz)
|
||||
return -ENOMEM;
|
||||
|
||||
result = devm_add_action_or_reset(dev, acpi_thermal_zone_free, tz);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
platform_set_drvdata(pdev, tz);
|
||||
|
||||
tz->device = device;
|
||||
|
|
@ -817,7 +827,7 @@ static int acpi_thermal_probe(struct platform_device *pdev)
|
|||
/* Get temperature [_TMP] (required). */
|
||||
result = acpi_thermal_get_temperature(tz);
|
||||
if (result)
|
||||
goto free_memory;
|
||||
return result;
|
||||
|
||||
/* Determine the default polling frequency [_TZP]. */
|
||||
if (tzp)
|
||||
|
|
@ -870,7 +880,11 @@ static int acpi_thermal_probe(struct platform_device *pdev)
|
|||
trip - trip_table,
|
||||
passive_delay);
|
||||
if (result)
|
||||
goto free_memory;
|
||||
return result;
|
||||
|
||||
result = devm_add_action_or_reset(dev, acpi_thermal_zone_unregister, tz);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
refcount_set(&tz->thermal_check_count, 3);
|
||||
mutex_init(&tz->thermal_check_lock);
|
||||
|
|
@ -879,32 +893,8 @@ static int acpi_thermal_probe(struct platform_device *pdev)
|
|||
pr_info("Thermal Zone [%s] (%ld C)\n", acpi_device_bid(device),
|
||||
deci_kelvin_to_celsius(tz->temp_dk));
|
||||
|
||||
result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_thermal_notify, tz);
|
||||
if (result)
|
||||
goto flush_wq;
|
||||
|
||||
return 0;
|
||||
|
||||
flush_wq:
|
||||
flush_workqueue(acpi_thermal_pm_queue);
|
||||
acpi_thermal_unregister_thermal_zone(tz);
|
||||
free_memory:
|
||||
acpi_thermal_free_thermal_zone(tz);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void acpi_thermal_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct acpi_thermal *tz = platform_get_drvdata(pdev);
|
||||
|
||||
acpi_dev_remove_notify_handler(tz->device, ACPI_DEVICE_NOTIFY,
|
||||
acpi_thermal_notify);
|
||||
|
||||
flush_workqueue(acpi_thermal_pm_queue);
|
||||
acpi_thermal_unregister_thermal_zone(tz);
|
||||
acpi_thermal_free_thermal_zone(tz);
|
||||
return devm_acpi_install_notify_handler(dev, ACPI_DEVICE_NOTIFY,
|
||||
acpi_thermal_notify, tz);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
|
@ -937,7 +927,6 @@ MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
|
|||
|
||||
static struct platform_driver acpi_thermal_driver = {
|
||||
.probe = acpi_thermal_probe,
|
||||
.remove = acpi_thermal_remove,
|
||||
.driver = {
|
||||
.name = "acpi-thermal",
|
||||
.acpi_match_table = thermal_device_ids,
|
||||
|
|
|
|||
|
|
@ -629,6 +629,8 @@ int acpi_dev_install_notify_handler(struct acpi_device *adev,
|
|||
void acpi_dev_remove_notify_handler(struct acpi_device *adev,
|
||||
u32 handler_type,
|
||||
acpi_notify_handler handler);
|
||||
int devm_acpi_install_notify_handler(struct device *dev, u32 handler_type,
|
||||
acpi_notify_handler handler, void *context);
|
||||
extern int acpi_notifier_call_chain(const char *device_class,
|
||||
const char *bus_id, u32 type, u32 data);
|
||||
extern int register_acpi_notifier(struct notifier_block *);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user