backports: add devm_add_action()
authorJohannes Berg <johannes.berg@intel.com>
Mon, 11 Sep 2017 14:49:42 +0000 (16:49 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 11 Sep 2017 14:49:42 +0000 (16:49 +0200)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
backport/backport-include/linux/device.h
backport/compat/backport-3.10.c

index e0886f5b3cf5f0e379e6274683bfc0a086b1f866..8f282ca6a39d83071d9c2959edcf0ee5d2a78097 100644 (file)
@@ -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) \
index 5cab709c69ccc505b6d58ce7d7228311343d5bf6..0c0e2603b427dd742d3d6b155860c96185fddaa2 100644 (file)
@@ -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);