[media] rc-main: Fix device de-registration logic
rc unregister logic were deadly broken, preventing some drivers to be removed. Among the broken things, rc_dev_uevent() is being called during device_del(), causing a data filling on an area that it is not ready anymore. Also, some drivers have a stop callback defined, that needs to be called before data removal, as it stops data polling. Acked-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
eaceba650d
commit
b05681b917
|
@ -928,10 +928,6 @@ out:
|
||||||
|
|
||||||
static void rc_dev_release(struct device *device)
|
static void rc_dev_release(struct device *device)
|
||||||
{
|
{
|
||||||
struct rc_dev *dev = to_rc_dev(device);
|
|
||||||
|
|
||||||
kfree(dev);
|
|
||||||
module_put(THIS_MODULE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ADD_HOTPLUG_VAR(fmt, val...) \
|
#define ADD_HOTPLUG_VAR(fmt, val...) \
|
||||||
|
@ -945,6 +941,9 @@ static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||||
{
|
{
|
||||||
struct rc_dev *dev = to_rc_dev(device);
|
struct rc_dev *dev = to_rc_dev(device);
|
||||||
|
|
||||||
|
if (!dev || !dev->input_dev)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
if (dev->rc_map.name)
|
if (dev->rc_map.name)
|
||||||
ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
|
ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
|
||||||
if (dev->driver_name)
|
if (dev->driver_name)
|
||||||
|
@ -1013,10 +1012,16 @@ EXPORT_SYMBOL_GPL(rc_allocate_device);
|
||||||
|
|
||||||
void rc_free_device(struct rc_dev *dev)
|
void rc_free_device(struct rc_dev *dev)
|
||||||
{
|
{
|
||||||
if (dev) {
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dev->input_dev)
|
||||||
input_free_device(dev->input_dev);
|
input_free_device(dev->input_dev);
|
||||||
|
|
||||||
put_device(&dev->dev);
|
put_device(&dev->dev);
|
||||||
}
|
|
||||||
|
kfree(dev);
|
||||||
|
module_put(THIS_MODULE);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rc_free_device);
|
EXPORT_SYMBOL_GPL(rc_free_device);
|
||||||
|
|
||||||
|
@ -1143,14 +1148,18 @@ void rc_unregister_device(struct rc_dev *dev)
|
||||||
if (dev->driver_type == RC_DRIVER_IR_RAW)
|
if (dev->driver_type == RC_DRIVER_IR_RAW)
|
||||||
ir_raw_event_unregister(dev);
|
ir_raw_event_unregister(dev);
|
||||||
|
|
||||||
input_unregister_device(dev->input_dev);
|
/* Freeing the table should also call the stop callback */
|
||||||
dev->input_dev = NULL;
|
|
||||||
|
|
||||||
ir_free_table(&dev->rc_map);
|
ir_free_table(&dev->rc_map);
|
||||||
IR_dprintk(1, "Freed keycode table\n");
|
IR_dprintk(1, "Freed keycode table\n");
|
||||||
|
|
||||||
device_unregister(&dev->dev);
|
input_unregister_device(dev->input_dev);
|
||||||
|
dev->input_dev = NULL;
|
||||||
|
|
||||||
|
device_del(&dev->dev);
|
||||||
|
|
||||||
|
rc_free_device(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(rc_unregister_device);
|
EXPORT_SYMBOL_GPL(rc_unregister_device);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue