Skip to content

Commit

Permalink
serial_ir: ensure we're ready to receive interrupts
Browse files Browse the repository at this point in the history
commit 0265634 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: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Sean Young authored and Greg Kroah-Hartman committed Mar 18, 2017
1 parent 81383a0 commit 2030aed
Showing 1 changed file with 58 additions and 57 deletions.
115 changes: 58 additions & 57 deletions drivers/media/rc/serial_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,10 +471,65 @@ static int hardware_init_port(void)
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)
{
struct rc_dev *rcdev;
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,
share_irq ? IRQF_SHARED : 0,
KBUILD_MODNAME, &hardware);
Expand Down Expand Up @@ -533,7 +588,8 @@ static int serial_ir_probe(struct platform_device *dev)
sense ? "low" : "high");

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)
Expand Down Expand Up @@ -704,7 +760,6 @@ static void serial_ir_exit(void)

static int __init serial_ir_init_module(void)
{
struct rc_dev *rcdev;
int result;

switch (type) {
Expand Down Expand Up @@ -735,69 +790,15 @@ static int __init serial_ir_init_module(void)
sense = !!sense;

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)
return 0;
serial_cleanup:

serial_ir_exit();
return result;
}

static void __exit serial_ir_exit_module(void)
{
rc_unregister_device(serial_ir.rcdev);
serial_ir_exit();
}

Expand Down

0 comments on commit 2030aed

Please sign in to comment.