aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-07-11 23:00:12 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-10-13 19:16:28 -0400
commit74188cba088192e14cd7fd5433876e8c947bcdd8 (patch)
treea57d582ea4a75155a169b0dede83f5eed3c2e9b1
parent615fc8cb0f900c91ee50f0da0a1821a7c6823671 (diff)
hwmon: Provide managed hwmon registration
Drivers using the new hwmon_device_register_with_groups API often have a remove function which consists solely of a call hwmon_device_unregister(). Provide support for devm_hwmon_device_register_with_groups and devm_hwmon_device_unregister to allow this repeated code to be removed and help eliminate error handling code. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/hwmon.c63
-rw-r--r--include/linux/hwmon.h5
2 files changed, 68 insertions, 0 deletions
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index a982528293ea..e176a43af63d 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -163,6 +163,69 @@ void hwmon_device_unregister(struct device *dev)
163} 163}
164EXPORT_SYMBOL_GPL(hwmon_device_unregister); 164EXPORT_SYMBOL_GPL(hwmon_device_unregister);
165 165
166static void devm_hwmon_release(struct device *dev, void *res)
167{
168 struct device *hwdev = *(struct device **)res;
169
170 hwmon_device_unregister(hwdev);
171}
172
173/**
174 * devm_hwmon_device_register_with_groups - register w/ hwmon
175 * @dev: the parent device
176 * @name: hwmon name attribute
177 * @drvdata: driver data to attach to created device
178 * @groups: List of attribute groups to create
179 *
180 * Returns the pointer to the new device. The new device is automatically
181 * unregistered with the parent device.
182 */
183struct device *
184devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
185 void *drvdata,
186 const struct attribute_group **groups)
187{
188 struct device **ptr, *hwdev;
189
190 if (!dev)
191 return ERR_PTR(-EINVAL);
192
193 ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
194 if (!ptr)
195 return ERR_PTR(-ENOMEM);
196
197 hwdev = hwmon_device_register_with_groups(dev, name, drvdata, groups);
198 if (IS_ERR(hwdev))
199 goto error;
200
201 *ptr = hwdev;
202 devres_add(dev, ptr);
203 return hwdev;
204
205error:
206 devres_free(ptr);
207 return hwdev;
208}
209EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
210
211static int devm_hwmon_match(struct device *dev, void *res, void *data)
212{
213 struct device **hwdev = res;
214
215 return *hwdev == data;
216}
217
218/**
219 * devm_hwmon_device_unregister - removes a previously registered hwmon device
220 *
221 * @dev: the parent device of the device to unregister
222 */
223void devm_hwmon_device_unregister(struct device *dev)
224{
225 WARN_ON(devres_release(dev, devm_hwmon_release, devm_hwmon_match, dev));
226}
227EXPORT_SYMBOL_GPL(devm_hwmon_device_unregister);
228
166static void __init hwmon_pci_quirks(void) 229static void __init hwmon_pci_quirks(void)
167{ 230{
168#if defined CONFIG_X86 && defined CONFIG_PCI 231#if defined CONFIG_X86 && defined CONFIG_PCI
diff --git a/include/linux/hwmon.h b/include/linux/hwmon.h
index 6d02ff77ae1a..09354f6c1d63 100644
--- a/include/linux/hwmon.h
+++ b/include/linux/hwmon.h
@@ -22,7 +22,12 @@ struct device *
22hwmon_device_register_with_groups(struct device *dev, const char *name, 22hwmon_device_register_with_groups(struct device *dev, const char *name,
23 void *drvdata, 23 void *drvdata,
24 const struct attribute_group **groups); 24 const struct attribute_group **groups);
25struct device *
26devm_hwmon_device_register_with_groups(struct device *dev, const char *name,
27 void *drvdata,
28 const struct attribute_group **groups);
25 29
26void hwmon_device_unregister(struct device *dev); 30void hwmon_device_unregister(struct device *dev);
31void devm_hwmon_device_unregister(struct device *dev);
27 32
28#endif 33#endif