[PATCH OLK-5.10] soc: hisilicon: Serialize the online and onfline the acpi devices

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC0DU9 ----------------------------------------------- The parallelization of hbm on and off can cause problems, such as the abnormal state of acpi device. Force paralleize the routine of power on/off the hbm device, which can fix various the abnormal state of acpi devices. Signed-off-by: Zhang Zekun <zhangzekun11@huawei.com> --- drivers/acpi/device_sysfs.c | 8 +++ drivers/acpi/osl.c | 5 ++ drivers/soc/hisilicon/hisi_hbmdev.c | 83 +++++++++++++++++++---------- include/linux/acpi.h | 2 + 4 files changed, 69 insertions(+), 29 deletions(-) diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 57ee8314dfb8..0f0bde3a41f6 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -359,6 +359,11 @@ static ssize_t power_state_show(struct device *dev, static DEVICE_ATTR_RO(power_state); +static struct acpi_platform_list no_eject_plat_info[] = { + {"HISI ", "HIP11 ", 0, ACPI_SIG_IORT, all_versions, NULL, 0}, + { } +}; + static ssize_t eject_store(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -378,6 +383,9 @@ eject_store(struct device *d, struct device_attribute *attr, if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) return -ENODEV; + if (acpi_match_platform_list(no_eject_plat_info) >= 0) + return -ENODEV; + get_device(&acpi_device->dev); status = acpi_hotplug_schedule(acpi_device, ACPI_OST_EC_OSPM_EJECT); if (ACPI_SUCCESS(status)) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 0418febc5cf2..213eb9b63776 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1194,6 +1194,11 @@ bool acpi_queue_hotplug_work(struct work_struct *work) return queue_work(kacpi_hotplug_wq, work); } +void flush_hotplug_workqueue(void) +{ + flush_workqueue(kacpi_hotplug_wq); +} + acpi_status acpi_os_create_semaphore(u32 max_units, u32 initial_units, acpi_handle * handle) { diff --git a/drivers/soc/hisilicon/hisi_hbmdev.c b/drivers/soc/hisilicon/hisi_hbmdev.c index 7ed874ff2206..cb65da2c5463 100644 --- a/drivers/soc/hisilicon/hisi_hbmdev.c +++ b/drivers/soc/hisilicon/hisi_hbmdev.c @@ -19,6 +19,7 @@ struct cdev_node { struct list_head clist; }; +static struct mutex dev_lock; struct cdev_node cdev_list; static int get_pxm(struct acpi_device *acpi_device, void *arg) @@ -54,21 +55,6 @@ static ssize_t pxms_show(struct device *dev, } static DEVICE_ATTR_RO(pxms); -static int memdev_power_on(struct acpi_device *adev) -{ - acpi_handle handle = adev->handle; - acpi_status status; - - /* Power on and online the devices */ - status = acpi_evaluate_object(handle, "_ON", NULL, NULL); - if (ACPI_FAILURE(status)) { - acpi_handle_warn(handle, "Power on failed (0x%x)\n", status); - return -ENODEV; - } - - return 0; -} - static int hbmdev_check(struct acpi_device *adev, void *arg) { const char *hid = acpi_device_hid(adev); @@ -79,34 +65,61 @@ static int hbmdev_check(struct acpi_device *adev, void *arg) *found = true; return -1; } - - /* There might be devices have not attached */ - if (!adev->handler) - return 0; - - adev->handler->hotplug.demand_offline = true; } return 0; } -static int memdev_power_off(struct acpi_device *adev) +static int memdev_power_on(struct acpi_device *adev) { acpi_handle handle = adev->handle; + struct acpi_device *child; acpi_status status; - acpi_scan_lock_acquire(); - acpi_dev_for_each_child(adev, hbmdev_check, NULL); - acpi_scan_lock_release(); + list_for_each_entry(child, &adev->children, node) { + unsigned long long sta = 0; - /* Eject the devices and power off */ - status = acpi_evaluate_object(handle, "_OFF", NULL, NULL); + status = acpi_evaluate_integer(child->handle, "_STA", NULL, &sta); + if (ACPI_FAILURE(status) || (sta & ACPI_STA_DEVICE_ENABLED)) + return -EINVAL; + } + + /* Power on and online the devices */ + status = acpi_evaluate_object(handle, "_ON", NULL, NULL); if (ACPI_FAILURE(status)) { + acpi_handle_warn(handle, "Power on failed (0x%x)\n", status); return -ENODEV; } + return 0; } +static void memdev_power_off(struct acpi_device *adev) +{ + struct acpi_device *child; + + list_for_each_entry(child, &adev->children, node) { + const char *hid = acpi_device_hid(child); + acpi_status status; + + if (strcmp(hid, ACPI_MEMORY_DEVICE_HID)) + continue; + + if (!child->handler) + continue; + + child->handler->hotplug.demand_offline = true; + + get_device(&child->dev); + status = acpi_hotplug_schedule(child, ACPI_OST_EC_OSPM_EJECT); + if (ACPI_SUCCESS(status)) + continue; + + put_device(&child->dev); + + } +} + static ssize_t state_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -114,23 +127,33 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, const int type = online_type_from_str(buf); int ret; + if (!mutex_trylock(&dev_lock)) + return -EBUSY; + /* Disallow pending on the mutex to avoid potential hung task*/ ret = lock_device_hotplug_sysfs(); - if (ret) + if (ret) { + mutex_unlock(&dev_lock); return ret; + } switch (type) { case STATE_ONLINE: ret = memdev_power_on(adev); break; case STATE_OFFLINE: - ret = memdev_power_off(adev); + memdev_power_off(adev); break; default: break; } + unlock_device_hotplug(); + acpi_os_wait_events_complete(); + flush_hotplug_workqueue(); + + mutex_unlock(&dev_lock); if (ret) return ret; @@ -212,6 +235,8 @@ static int __init hbmdev_init(void) if (acpi_match_platform_list(hbm_plat_info) < 0) return 0; + mutex_init(&dev_lock); + return container_init(); } module_init(hbmdev_init); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 38ad6478c4b9..0d4f5ccfc059 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1416,12 +1416,14 @@ static inline void acpi_init_pcc(void) { } #ifdef CONFIG_ACPI extern int acpi_platform_notify(struct device *dev, enum kobject_action action); +extern void flush_hotplug_workqueue(void); #else static inline int acpi_platform_notify(struct device *dev, enum kobject_action action) { return 0; } +static inline void flush_hotplug_workqueue(void) {} #endif struct acpi_pptt_processor * -- 2.22.0

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/15866 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/RHB... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/15866 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/RHB...
participants (2)
-
patchwork bot
-
Zhang Zekun