Skip to content

Commit

Permalink
UPSTREAM: [media] rc: core: add managed versions of rc_allocate_devic…
Browse files Browse the repository at this point in the history
…e and rc_register_device

Introduce managed versions of both functions.
They allows to simplify the error path in the probe function of
rc drivers, and usually also to simplify the remove function.

New element managed_alloc in struct rc_dev is needed to correctly
handle mixed use, e.g. managed version of rc_register_device and
normal version of rc_allocate_device.

In addition devm_rc_allocate_device sets rc->dev.parent as having a
reference to the parent device might be useful for future extensions.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
(cherry picked from commit ddbf7d5a698c4d8553ad2f77cb281d7b37898d34)
Change-Id: I1e45fd0beb1c58058be654185dfc6f5cf7d55e3f
Signed-off-by: TogoFire <togofire@mailfence.com>
  • Loading branch information
hkallweit authored and TogoFire committed Apr 22, 2023
1 parent b98cec1 commit f626025
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
58 changes: 57 additions & 1 deletion drivers/media/rc/rc-main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1403,6 +1403,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? */
Expand Down Expand Up @@ -1536,6 +1564,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)
Expand All @@ -1557,7 +1612,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);
Expand Down
18 changes: 18 additions & 0 deletions include/media/rc-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
*
Expand All @@ -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
*
Expand Down

0 comments on commit f626025

Please sign in to comment.