Commit 2030aedc authored by Sean Young's avatar Sean Young Committed by Greg Kroah-Hartman

serial_ir: ensure we're ready to receive interrupts

commit 0265634e upstream.

When the interrupt requested with devm_request_irq(), serial_ir.rcdev
is still null so will cause null deference if the irq handler is called
early on.

Also ensure that timeout_timer is setup.

Link: http://lkml.kernel.org/r/CA+55aFxsh2uF8gi5sN_guY3Z+tiLv7LpJYKBw+y8vqLzp+TsnQ@mail.gmail.com

[mchehab@s-opensource.com: moved serial_ir_probe() back to its original place]
Signed-off-by: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 81383a00
...@@ -471,10 +471,65 @@ static int hardware_init_port(void) ...@@ -471,10 +471,65 @@ static int hardware_init_port(void)
return 0; return 0;
} }
/* Needed by serial_ir_probe() */
static int serial_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
unsigned int count);
static int serial_ir_tx_duty_cycle(struct rc_dev *dev, u32 cycle);
static int serial_ir_tx_carrier(struct rc_dev *dev, u32 carrier);
static int serial_ir_open(struct rc_dev *rcdev);
static void serial_ir_close(struct rc_dev *rcdev);
static int serial_ir_probe(struct platform_device *dev) static int serial_ir_probe(struct platform_device *dev)
{ {
struct rc_dev *rcdev;
int i, nlow, nhigh, result; int i, nlow, nhigh, result;
rcdev = devm_rc_allocate_device(&dev->dev);
if (!rcdev)
return -ENOMEM;
if (hardware[type].send_pulse && hardware[type].send_space)
rcdev->tx_ir = serial_ir_tx;
if (hardware[type].set_send_carrier)
rcdev->s_tx_carrier = serial_ir_tx_carrier;
if (hardware[type].set_duty_cycle)
rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
switch (type) {
case IR_HOMEBREW:
rcdev->input_name = "Serial IR type home-brew";
break;
case IR_IRDEO:
rcdev->input_name = "Serial IR type IRdeo";
break;
case IR_IRDEO_REMOTE:
rcdev->input_name = "Serial IR type IRdeo remote";
break;
case IR_ANIMAX:
rcdev->input_name = "Serial IR type AnimaX";
break;
case IR_IGOR:
rcdev->input_name = "Serial IR type IgorPlug";
break;
}
rcdev->input_phys = KBUILD_MODNAME "/input0";
rcdev->input_id.bustype = BUS_HOST;
rcdev->input_id.vendor = 0x0001;
rcdev->input_id.product = 0x0001;
rcdev->input_id.version = 0x0100;
rcdev->open = serial_ir_open;
rcdev->close = serial_ir_close;
rcdev->dev.parent = &serial_ir.pdev->dev;
rcdev->driver_type = RC_DRIVER_IR_RAW;
rcdev->allowed_protocols = RC_BIT_ALL;
rcdev->driver_name = KBUILD_MODNAME;
rcdev->map_name = RC_MAP_RC6_MCE;
rcdev->timeout = IR_DEFAULT_TIMEOUT;
rcdev->rx_resolution = 250000;
serial_ir.rcdev = rcdev;
result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler, result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler,
share_irq ? IRQF_SHARED : 0, share_irq ? IRQF_SHARED : 0,
KBUILD_MODNAME, &hardware); KBUILD_MODNAME, &hardware);
...@@ -533,7 +588,8 @@ static int serial_ir_probe(struct platform_device *dev) ...@@ -533,7 +588,8 @@ static int serial_ir_probe(struct platform_device *dev)
sense ? "low" : "high"); sense ? "low" : "high");
dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io); dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);
return 0;
return devm_rc_register_device(&dev->dev, rcdev);
} }
static int serial_ir_open(struct rc_dev *rcdev) static int serial_ir_open(struct rc_dev *rcdev)
...@@ -704,7 +760,6 @@ static void serial_ir_exit(void) ...@@ -704,7 +760,6 @@ static void serial_ir_exit(void)
static int __init serial_ir_init_module(void) static int __init serial_ir_init_module(void)
{ {
struct rc_dev *rcdev;
int result; int result;
switch (type) { switch (type) {
...@@ -735,69 +790,15 @@ static int __init serial_ir_init_module(void) ...@@ -735,69 +790,15 @@ static int __init serial_ir_init_module(void)
sense = !!sense; sense = !!sense;
result = serial_ir_init(); result = serial_ir_init();
if (result)
return result;
rcdev = devm_rc_allocate_device(&serial_ir.pdev->dev);
if (!rcdev) {
result = -ENOMEM;
goto serial_cleanup;
}
if (hardware[type].send_pulse && hardware[type].send_space)
rcdev->tx_ir = serial_ir_tx;
if (hardware[type].set_send_carrier)
rcdev->s_tx_carrier = serial_ir_tx_carrier;
if (hardware[type].set_duty_cycle)
rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
switch (type) {
case IR_HOMEBREW:
rcdev->input_name = "Serial IR type home-brew";
break;
case IR_IRDEO:
rcdev->input_name = "Serial IR type IRdeo";
break;
case IR_IRDEO_REMOTE:
rcdev->input_name = "Serial IR type IRdeo remote";
break;
case IR_ANIMAX:
rcdev->input_name = "Serial IR type AnimaX";
break;
case IR_IGOR:
rcdev->input_name = "Serial IR type IgorPlug";
break;
}
rcdev->input_phys = KBUILD_MODNAME "/input0";
rcdev->input_id.bustype = BUS_HOST;
rcdev->input_id.vendor = 0x0001;
rcdev->input_id.product = 0x0001;
rcdev->input_id.version = 0x0100;
rcdev->open = serial_ir_open;
rcdev->close = serial_ir_close;
rcdev->dev.parent = &serial_ir.pdev->dev;
rcdev->driver_type = RC_DRIVER_IR_RAW;
rcdev->allowed_protocols = RC_BIT_ALL;
rcdev->driver_name = KBUILD_MODNAME;
rcdev->map_name = RC_MAP_RC6_MCE;
rcdev->timeout = IR_DEFAULT_TIMEOUT;
rcdev->rx_resolution = 250000;
serial_ir.rcdev = rcdev;
result = rc_register_device(rcdev);
if (!result) if (!result)
return 0; return 0;
serial_cleanup:
serial_ir_exit(); serial_ir_exit();
return result; return result;
} }
static void __exit serial_ir_exit_module(void) static void __exit serial_ir_exit_module(void)
{ {
rc_unregister_device(serial_ir.rcdev);
serial_ir_exit(); serial_ir_exit();
} }
......
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