}
EXPORT_SYMBOL_GPL(acpi_dev_remove_notify_handler);
+struct acpi_notify_handler_devres {
+ 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(ACPI_COMPANION(dev), 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 in %s()\n", __func__);
+
+ 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->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
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 *);