Skip to content

Commit

Permalink
[media] IR: make sure we register the input device when it is safe to…
Browse files Browse the repository at this point in the history
… do so

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>
  • Loading branch information
Maxim Levitsky authored and Mauro Carvalho Chehab committed Oct 21, 2010
1 parent c6ef1e7 commit 58b3dd4
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 10 deletions.
1 change: 1 addition & 0 deletions drivers/media/IR/ir-core-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/media/IR/ir-keytable.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) ?
Expand Down
27 changes: 17 additions & 10 deletions drivers/media/IR/ir-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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
Expand Down

0 comments on commit 58b3dd4

Please sign in to comment.