diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 1cf382a0b277..1dedebda1cef 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -699,19 +699,50 @@ void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle) } EXPORT_SYMBOL_GPL(rc_keydown_notimeout); +int rc_open(struct rc_dev *rdev) +{ + int rval = 0; + + if (!rdev) + return -EINVAL; + + mutex_lock(&rdev->lock); + if (!rdev->users++) + rval = rdev->open(rdev); + + if (rval) + rdev->users--; + + mutex_unlock(&rdev->lock); + + return rval; +} +EXPORT_SYMBOL_GPL(rc_open); + static int ir_open(struct input_dev *idev) { struct rc_dev *rdev = input_get_drvdata(idev); - return rdev->open(rdev); + return rc_open(rdev); } +void rc_close(struct rc_dev *rdev) +{ + if (rdev) { + mutex_lock(&rdev->lock); + + if (!--rdev->users) + rdev->close(rdev); + + mutex_unlock(&rdev->lock); + } +} +EXPORT_SYMBOL_GPL(rc_close); + static void ir_close(struct input_dev *idev) { struct rc_dev *rdev = input_get_drvdata(idev); - - if (rdev) - rdev->close(rdev); + rc_close(rdev); } /* class for /sys/class/rc */ @@ -1076,7 +1107,14 @@ int rc_register_device(struct rc_dev *dev) memcpy(&dev->input_dev->id, &dev->input_id, sizeof(dev->input_id)); dev->input_dev->phys = dev->input_phys; dev->input_dev->name = dev->input_name; + + /* input_register_device can call ir_open, so unlock mutex here */ + mutex_unlock(&dev->lock); + rc = input_register_device(dev->input_dev); + + mutex_lock(&dev->lock); + if (rc) goto out_table; diff --git a/include/media/rc-core.h b/include/media/rc-core.h index 06a75deff553..2f6f1f78d958 100644 --- a/include/media/rc-core.h +++ b/include/media/rc-core.h @@ -101,6 +101,7 @@ struct rc_dev { bool idle; u64 allowed_protos; u64 enabled_protocols; + u32 users; u32 scanmask; void *priv; spinlock_t keylock; @@ -142,6 +143,9 @@ void rc_free_device(struct rc_dev *dev); int rc_register_device(struct rc_dev *dev); void rc_unregister_device(struct rc_dev *dev); +int rc_open(struct rc_dev *rdev); +void rc_close(struct rc_dev *rdev); + void rc_repeat(struct rc_dev *dev); void rc_keydown(struct rc_dev *dev, int scancode, u8 toggle); void rc_keydown_notimeout(struct rc_dev *dev, int scancode, u8 toggle);