mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-20 00:46:22 +07:00
[media] rc-core: cleanup rc_register_device
The device core infrastructure is based on the presumption that once a driver calls device_add(), it must be ready to accept userspace interaction. This requires splitting rc_setup_rx_device() into two functions and reorganizing rc_register_device() so that as much work as possible is performed before calling device_add(). Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
6709e03cba
commit
f56928abaa
@ -263,7 +263,9 @@ int ir_raw_gen_pl(struct ir_raw_event **ev, unsigned int max,
|
||||
* Routines from rc-raw.c to be used internally and by decoders
|
||||
*/
|
||||
u64 ir_raw_get_allowed_protocols(void);
|
||||
int ir_raw_event_prepare(struct rc_dev *dev);
|
||||
int ir_raw_event_register(struct rc_dev *dev);
|
||||
void ir_raw_event_free(struct rc_dev *dev);
|
||||
void ir_raw_event_unregister(struct rc_dev *dev);
|
||||
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
|
||||
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
|
||||
|
@ -486,15 +486,18 @@ EXPORT_SYMBOL(ir_raw_encode_scancode);
|
||||
/*
|
||||
* Used to (un)register raw event clients
|
||||
*/
|
||||
int ir_raw_event_register(struct rc_dev *dev)
|
||||
int ir_raw_event_prepare(struct rc_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
struct ir_raw_handler *handler;
|
||||
struct task_struct *thread;
|
||||
static bool raw_init; /* 'false' default value, raw decoders loaded? */
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!raw_init) {
|
||||
request_module("ir-lirc-codec");
|
||||
raw_init = true;
|
||||
}
|
||||
|
||||
dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
|
||||
if (!dev->raw)
|
||||
return -ENOMEM;
|
||||
@ -503,6 +506,14 @@ int ir_raw_event_register(struct rc_dev *dev)
|
||||
dev->change_protocol = change_protocol;
|
||||
INIT_KFIFO(dev->raw->kfifo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ir_raw_event_register(struct rc_dev *dev)
|
||||
{
|
||||
struct ir_raw_handler *handler;
|
||||
struct task_struct *thread;
|
||||
|
||||
/*
|
||||
* raw transmitters do not need any event registration
|
||||
* because the event is coming from userspace
|
||||
@ -511,10 +522,8 @@ int ir_raw_event_register(struct rc_dev *dev)
|
||||
thread = kthread_run(ir_raw_event_thread, dev->raw, "rc%u",
|
||||
dev->minor);
|
||||
|
||||
if (IS_ERR(thread)) {
|
||||
rc = PTR_ERR(thread);
|
||||
goto out;
|
||||
}
|
||||
if (IS_ERR(thread))
|
||||
return PTR_ERR(thread);
|
||||
|
||||
dev->raw->thread = thread;
|
||||
}
|
||||
@ -527,11 +536,15 @@ int ir_raw_event_register(struct rc_dev *dev)
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ir_raw_event_free(struct rc_dev *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
out:
|
||||
kfree(dev->raw);
|
||||
dev->raw = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ir_raw_event_unregister(struct rc_dev *dev)
|
||||
@ -550,8 +563,7 @@ void ir_raw_event_unregister(struct rc_dev *dev)
|
||||
handler->raw_unregister(dev);
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
|
||||
kfree(dev->raw);
|
||||
dev->raw = NULL;
|
||||
ir_raw_event_free(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1663,7 +1663,7 @@ struct rc_dev *devm_rc_allocate_device(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_rc_allocate_device);
|
||||
|
||||
static int rc_setup_rx_device(struct rc_dev *dev)
|
||||
static int rc_prepare_rx_device(struct rc_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
struct rc_map *rc_map;
|
||||
@ -1708,10 +1708,22 @@ static int rc_setup_rx_device(struct rc_dev *dev)
|
||||
dev->input_dev->phys = dev->input_phys;
|
||||
dev->input_dev->name = dev->input_name;
|
||||
|
||||
return 0;
|
||||
|
||||
out_table:
|
||||
ir_free_table(&dev->rc_map);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int rc_setup_rx_device(struct rc_dev *dev)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* rc_open will be called here */
|
||||
rc = input_register_device(dev->input_dev);
|
||||
if (rc)
|
||||
goto out_table;
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* Default delay of 250ms is too short for some protocols, especially
|
||||
@ -1729,27 +1741,23 @@ static int rc_setup_rx_device(struct rc_dev *dev)
|
||||
dev->input_dev->rep[REP_PERIOD] = 125;
|
||||
|
||||
return 0;
|
||||
|
||||
out_table:
|
||||
ir_free_table(&dev->rc_map);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void rc_free_rx_device(struct rc_dev *dev)
|
||||
{
|
||||
if (!dev || dev->driver_type == RC_DRIVER_IR_RAW_TX)
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
ir_free_table(&dev->rc_map);
|
||||
if (dev->input_dev) {
|
||||
input_unregister_device(dev->input_dev);
|
||||
dev->input_dev = NULL;
|
||||
}
|
||||
|
||||
input_unregister_device(dev->input_dev);
|
||||
dev->input_dev = NULL;
|
||||
ir_free_table(&dev->rc_map);
|
||||
}
|
||||
|
||||
int rc_register_device(struct rc_dev *dev)
|
||||
{
|
||||
static bool raw_init; /* 'false' default value, raw decoders loaded? */
|
||||
const char *path;
|
||||
int attr = 0;
|
||||
int minor;
|
||||
@ -1776,30 +1784,39 @@ int rc_register_device(struct rc_dev *dev)
|
||||
dev->sysfs_groups[attr++] = &rc_dev_wakeup_filter_attr_grp;
|
||||
dev->sysfs_groups[attr++] = NULL;
|
||||
|
||||
if (dev->driver_type == RC_DRIVER_IR_RAW ||
|
||||
dev->driver_type == RC_DRIVER_IR_RAW_TX) {
|
||||
rc = ir_raw_event_prepare(dev);
|
||||
if (rc < 0)
|
||||
goto out_minor;
|
||||
}
|
||||
|
||||
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
|
||||
rc = rc_prepare_rx_device(dev);
|
||||
if (rc)
|
||||
goto out_raw;
|
||||
}
|
||||
|
||||
rc = device_add(&dev->dev);
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
goto out_rx_free;
|
||||
|
||||
path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
|
||||
dev_info(&dev->dev, "%s as %s\n",
|
||||
dev->input_name ?: "Unspecified device", path ?: "N/A");
|
||||
kfree(path);
|
||||
|
||||
if (dev->driver_type == RC_DRIVER_IR_RAW ||
|
||||
dev->driver_type == RC_DRIVER_IR_RAW_TX) {
|
||||
if (!raw_init) {
|
||||
request_module_nowait("ir-lirc-codec");
|
||||
raw_init = true;
|
||||
}
|
||||
rc = ir_raw_event_register(dev);
|
||||
if (rc < 0)
|
||||
goto out_dev;
|
||||
}
|
||||
|
||||
if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
|
||||
rc = rc_setup_rx_device(dev);
|
||||
if (rc)
|
||||
goto out_raw;
|
||||
goto out_dev;
|
||||
}
|
||||
|
||||
if (dev->driver_type == RC_DRIVER_IR_RAW ||
|
||||
dev->driver_type == RC_DRIVER_IR_RAW_TX) {
|
||||
rc = ir_raw_event_register(dev);
|
||||
if (rc < 0)
|
||||
goto out_rx;
|
||||
}
|
||||
|
||||
/* Allow the RC sysfs nodes to be accessible */
|
||||
@ -1811,11 +1828,15 @@ int rc_register_device(struct rc_dev *dev)
|
||||
|
||||
return 0;
|
||||
|
||||
out_raw:
|
||||
ir_raw_event_unregister(dev);
|
||||
out_rx:
|
||||
rc_free_rx_device(dev);
|
||||
out_dev:
|
||||
device_del(&dev->dev);
|
||||
out_unlock:
|
||||
out_rx_free:
|
||||
ir_free_table(&dev->rc_map);
|
||||
out_raw:
|
||||
ir_raw_event_free(dev);
|
||||
out_minor:
|
||||
ida_simple_remove(&rc_ida, minor);
|
||||
return rc;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user