diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index b241e5f569efb524c6d2b22d02fa46a924cfd503..5087e76dfb03439d72c54cbf1dbc51bb13d63956 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1402,6 +1402,34 @@ void rc_free_device(struct rc_dev *dev) } EXPORT_SYMBOL_GPL(rc_free_device); +static void devm_rc_alloc_release(struct device *dev, void *res) +{ + rc_free_device(*(struct rc_dev **)res); +} + +struct rc_dev *devm_rc_allocate_device(struct device *dev) +{ + struct rc_dev **dr, *rc; + + dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return NULL; + + rc = rc_allocate_device(); + if (!rc) { + devres_free(dr); + return NULL; + } + + rc->dev.parent = dev; + rc->managed_alloc = true; + *dr = rc; + devres_add(dev, dr); + + return rc; +} +EXPORT_SYMBOL_GPL(devm_rc_allocate_device); + int rc_register_device(struct rc_dev *dev) { static bool raw_init = false; /* raw decoders loaded? */ @@ -1530,6 +1558,33 @@ int rc_register_device(struct rc_dev *dev) } EXPORT_SYMBOL_GPL(rc_register_device); +static void devm_rc_release(struct device *dev, void *res) +{ + rc_unregister_device(*(struct rc_dev **)res); +} + +int devm_rc_register_device(struct device *parent, struct rc_dev *dev) +{ + struct rc_dev **dr; + int ret; + + dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + ret = rc_register_device(dev); + if (ret) { + devres_free(dr); + return ret; + } + + *dr = dev; + devres_add(parent, dr); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_rc_register_device); + void rc_unregister_device(struct rc_dev *dev) { if (!dev) @@ -1551,7 +1606,8 @@ void rc_unregister_device(struct rc_dev *dev) ida_simple_remove(&rc_ida, dev->minor); - rc_free_device(dev); + if (!dev->managed_alloc) + rc_free_device(dev); } EXPORT_SYMBOL_GPL(rc_unregister_device); diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 40188d3624869fd932d28b1dd674def5a22cebfb..55281b92105a3ebd0d2e899028c3781e298738ea 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -68,6 +68,7 @@ enum rc_filter_type { * struct rc_dev - represents a remote control device * @dev: driver model's view of this device * @initialized: 1 if the device init has completed, 0 otherwise + * @managed_alloc: devm_rc_allocate_device was used to create rc_dev * @sysfs_groups: sysfs attribute groups * @input_name: name of the input child device * @input_phys: physical path to the input child device @@ -131,6 +132,7 @@ enum rc_filter_type { struct rc_dev { struct device dev; atomic_t initialized; + bool managed_alloc; const struct attribute_group *sysfs_groups[5]; const char *input_name; const char *input_phys; @@ -202,6 +204,14 @@ struct rc_dev { */ struct rc_dev *rc_allocate_device(void); +/** + * devm_rc_allocate_device - Managed RC device allocation + * + * @dev: pointer to struct device + * returns a pointer to struct rc_dev. + */ +struct rc_dev *devm_rc_allocate_device(struct device *dev); + /** * rc_free_device - Frees a RC device * @@ -216,6 +226,14 @@ void rc_free_device(struct rc_dev *dev); */ int rc_register_device(struct rc_dev *dev); +/** + * devm_rc_register_device - Manageded registering of a RC device + * + * @parent: pointer to struct device. + * @dev: pointer to struct rc_dev. + */ +int devm_rc_register_device(struct device *parent, struct rc_dev *dev); + /** * rc_unregister_device - Unregisters a RC device *