}
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? */
}
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)
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);
* 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
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;
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
*
* @dev: pointer to struct rc_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
*
* @dev: pointer to struct rc_dev.