summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2017-09-11 16:49:42 +0200
committerJohannes Berg <johannes.berg@intel.com>2017-09-11 16:49:42 +0200
commit9c47649c86140c8b2cee20b399200228e114bfa1 (patch)
tree3a406402bd09e4e504114796ef827827dde8e4cd
parentae1fce09e3fa6b52dd1ff5bce2ebd1824b582552 (diff)
backports: add devm_add_action()
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--backport/backport-include/linux/device.h4
-rw-r--r--backport/compat/backport-3.10.c38
2 files changed, 42 insertions, 0 deletions
diff --git a/backport/backport-include/linux/device.h b/backport/backport-include/linux/device.h
index e0886f5b..8f282ca6 100644
--- a/backport/backport-include/linux/device.h
+++ b/backport/backport-include/linux/device.h
@@ -125,6 +125,10 @@ static inline struct device *kobj_to_dev(struct kobject *kobj)
}
#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3,6,0) */
+#if LINUX_VERSION_IS_LESS(3,10,0)
+int devm_add_action(struct device *dev, void (*action) (void *), void *data);
+#endif
+
#if LINUX_VERSION_IS_LESS(3,11,0) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0)
#ifndef DEVICE_ATTR_RO
#define DEVICE_ATTR_RO(_name) \
diff --git a/backport/compat/backport-3.10.c b/backport/compat/backport-3.10.c
index 5cab709c..0c0e2603 100644
--- a/backport/compat/backport-3.10.c
+++ b/backport/compat/backport-3.10.c
@@ -197,3 +197,41 @@ void split_page(struct page *page, unsigned int order)
set_page_refcounted(page + i);
}
EXPORT_SYMBOL_GPL(split_page);
+
+struct action_devres {
+ void *data;
+ void (*action)(void *);
+};
+
+static void devm_action_release(struct device *dev, void *res)
+{
+ struct action_devres *devres = res;
+
+ devres->action(devres->data);
+}
+
+/**
+ * devm_add_action() - add a custom action to list of managed resources
+ * @dev: Device that owns the action
+ * @action: Function that should be called
+ * @data: Pointer to data passed to @action implementation
+ *
+ * This adds a custom action to the list of managed resources so that
+ * it gets executed as part of standard resource unwinding.
+ */
+int devm_add_action(struct device *dev, void (*action)(void *), void *data)
+{
+ struct action_devres *devres;
+
+ devres = devres_alloc(devm_action_release,
+ sizeof(struct action_devres), GFP_KERNEL);
+ if (!devres)
+ return -ENOMEM;
+
+ devres->data = data;
+ devres->action = action;
+
+ devres_add(dev, devres);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_add_action);