[media] IR: make sure we register the input device when it is safe to do so
authorMaxim Levitsky <maximlevitsky@gmail.com>
Mon, 6 Sep 2010 21:26:07 +0000 (18:26 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 21 Oct 2010 09:54:13 +0000 (07:54 -0200)
As soon as input device is registered, it might be accessed (and it is)
This can trigger a hardware interrupt that can access
not yet initialized ir->raw, (by sending a sample)

This can be reproduced by holding down a remote button and reloading the module.
And this always crashes the systems where hardware decides to send an interrupt
right at the moment it is enabled.

Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Acked-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/IR/ir-core-priv.h
drivers/media/IR/ir-keytable.c
drivers/media/IR/ir-sysfs.c

index 90eb3912c455a8588d0c07f6699bf99b8ed75129..6830580ae4db3b523eeae4fedecb7955321aa8ac 100644 (file)
@@ -122,6 +122,7 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
  * Routines from ir-sysfs.c - Meant to be called only internally inside
  * ir-core
  */
+int ir_register_input(struct input_dev *input_dev);
 
 int ir_register_class(struct input_dev *input_dev);
 void ir_unregister_class(struct input_dev *input_dev);
index 59510cd334198abe5fb6fc6ebbbec71ecce5595b..a616bd0523360b51858fa231b5b4709fe26ad533 100644 (file)
@@ -506,6 +506,8 @@ int __ir_input_register(struct input_dev *input_dev,
                                goto out_event;
                }
 
+       rc = ir_register_input(input_dev);
+
        IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
                   driver_name, rc_tab->name,
                   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
index 186807aa226d0dc1676b3ff5a7b071f26c9bf516..38423a8da8717e32aeb5b08e95a0fc02424e43ca 100644 (file)
@@ -265,8 +265,6 @@ static struct device_type rc_dev_type = {
  */
 int ir_register_class(struct input_dev *input_dev)
 {
-       int rc;
-       const char *path;
        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
        int devno = find_first_zero_bit(&ir_core_dev_number,
                                        IRRCV_NUM_DEVICES);
@@ -275,17 +273,28 @@ int ir_register_class(struct input_dev *input_dev)
                return devno;
 
        ir_dev->dev.type = &rc_dev_type;
+       ir_dev->devno = devno;
 
        ir_dev->dev.class = &ir_input_class;
        ir_dev->dev.parent = input_dev->dev.parent;
+       input_dev->dev.parent = &ir_dev->dev;
        dev_set_name(&ir_dev->dev, "rc%d", devno);
        dev_set_drvdata(&ir_dev->dev, ir_dev);
-       rc = device_register(&ir_dev->dev);
-       if (rc)
-               return rc;
+       return  device_register(&ir_dev->dev);
+};
+
+/**
+ * ir_register_input - registers ir input device with input subsystem
+ * @input_dev: the struct input_dev descriptor of the device
+ */
+
+int ir_register_input(struct input_dev *input_dev)
+{
+       struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+       int rc;
+       const char *path;
 
 
-       input_dev->dev.parent = &ir_dev->dev;
        rc = input_register_device(input_dev);
        if (rc < 0) {
                device_del(&ir_dev->dev);
@@ -301,11 +310,9 @@ int ir_register_class(struct input_dev *input_dev)
                path ? path : "N/A");
        kfree(path);
 
-       ir_dev->devno = devno;
-       set_bit(devno, &ir_core_dev_number);
-
+       set_bit(ir_dev->devno, &ir_core_dev_number);
        return 0;
-};
+}
 
 /**
  * ir_unregister_class() - removes the sysfs for sysfs for