aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2010-09-06 17:26:07 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-10-21 05:54:13 -0400
commit58b3dd449feaa997129bde23592c6a31da039e4e (patch)
treef2ea7542e56dccc9750593248e0651b914b4302c /drivers/media/IR
parentc6ef1e7fdc752bbaeacb3570cf955ba2ad60c61b (diff)
[media] IR: make sure we register the input device when it is safe to 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>
Diffstat (limited to 'drivers/media/IR')
-rw-r--r--drivers/media/IR/ir-core-priv.h1
-rw-r--r--drivers/media/IR/ir-keytable.c2
-rw-r--r--drivers/media/IR/ir-sysfs.c27
3 files changed, 20 insertions, 10 deletions
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index 90eb3912c455..6830580ae4db 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -122,6 +122,7 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
122 * Routines from ir-sysfs.c - Meant to be called only internally inside 122 * Routines from ir-sysfs.c - Meant to be called only internally inside
123 * ir-core 123 * ir-core
124 */ 124 */
125int ir_register_input(struct input_dev *input_dev);
125 126
126int ir_register_class(struct input_dev *input_dev); 127int ir_register_class(struct input_dev *input_dev);
127void ir_unregister_class(struct input_dev *input_dev); 128void ir_unregister_class(struct input_dev *input_dev);
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 59510cd33419..a616bd052336 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -506,6 +506,8 @@ int __ir_input_register(struct input_dev *input_dev,
506 goto out_event; 506 goto out_event;
507 } 507 }
508 508
509 rc = ir_register_input(input_dev);
510
509 IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", 511 IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
510 driver_name, rc_tab->name, 512 driver_name, rc_tab->name,
511 (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ? 513 (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 186807aa226d..38423a8da871 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -265,8 +265,6 @@ static struct device_type rc_dev_type = {
265 */ 265 */
266int ir_register_class(struct input_dev *input_dev) 266int ir_register_class(struct input_dev *input_dev)
267{ 267{
268 int rc;
269 const char *path;
270 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 268 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
271 int devno = find_first_zero_bit(&ir_core_dev_number, 269 int devno = find_first_zero_bit(&ir_core_dev_number,
272 IRRCV_NUM_DEVICES); 270 IRRCV_NUM_DEVICES);
@@ -275,17 +273,28 @@ int ir_register_class(struct input_dev *input_dev)
275 return devno; 273 return devno;
276 274
277 ir_dev->dev.type = &rc_dev_type; 275 ir_dev->dev.type = &rc_dev_type;
276 ir_dev->devno = devno;
278 277
279 ir_dev->dev.class = &ir_input_class; 278 ir_dev->dev.class = &ir_input_class;
280 ir_dev->dev.parent = input_dev->dev.parent; 279 ir_dev->dev.parent = input_dev->dev.parent;
280 input_dev->dev.parent = &ir_dev->dev;
281 dev_set_name(&ir_dev->dev, "rc%d", devno); 281 dev_set_name(&ir_dev->dev, "rc%d", devno);
282 dev_set_drvdata(&ir_dev->dev, ir_dev); 282 dev_set_drvdata(&ir_dev->dev, ir_dev);
283 rc = device_register(&ir_dev->dev); 283 return device_register(&ir_dev->dev);
284 if (rc) 284};
285 return rc; 285
286/**
287 * ir_register_input - registers ir input device with input subsystem
288 * @input_dev: the struct input_dev descriptor of the device
289 */
290
291int ir_register_input(struct input_dev *input_dev)
292{
293 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
294 int rc;
295 const char *path;
286 296
287 297
288 input_dev->dev.parent = &ir_dev->dev;
289 rc = input_register_device(input_dev); 298 rc = input_register_device(input_dev);
290 if (rc < 0) { 299 if (rc < 0) {
291 device_del(&ir_dev->dev); 300 device_del(&ir_dev->dev);
@@ -301,11 +310,9 @@ int ir_register_class(struct input_dev *input_dev)
301 path ? path : "N/A"); 310 path ? path : "N/A");
302 kfree(path); 311 kfree(path);
303 312
304 ir_dev->devno = devno; 313 set_bit(ir_dev->devno, &ir_core_dev_number);
305 set_bit(devno, &ir_core_dev_number);
306
307 return 0; 314 return 0;
308}; 315}
309 316
310/** 317/**
311 * ir_unregister_class() - removes the sysfs for sysfs for 318 * ir_unregister_class() - removes the sysfs for sysfs for