Commit b05681b9 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[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: default avatarJarod Wilson <jarod@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent eaceba65
...@@ -928,10 +928,6 @@ static ssize_t store_protocols(struct device *device, ...@@ -928,10 +928,6 @@ static ssize_t store_protocols(struct device *device,
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) ...@@ -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); ...@@ -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) ...@@ -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);
/* Freeing the table should also call the stop callback */
ir_free_table(&dev->rc_map);
IR_dprintk(1, "Freed keycode table\n");
input_unregister_device(dev->input_dev); input_unregister_device(dev->input_dev);
dev->input_dev = NULL; dev->input_dev = NULL;
ir_free_table(&dev->rc_map); device_del(&dev->dev);
IR_dprintk(1, "Freed keycode table\n");
device_unregister(&dev->dev); rc_free_device(dev);
} }
EXPORT_SYMBOL_GPL(rc_unregister_device); EXPORT_SYMBOL_GPL(rc_unregister_device);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment