| From 0265634eb9e04a16ae99941c320718c38eb865e0 Mon Sep 17 00:00:00 2001 |
| From: Sean Young <sean@mess.org> |
| Date: Sat, 25 Feb 2017 08:28:16 -0300 |
| Subject: [media] serial_ir: ensure we're ready to receive interrupts |
| |
| From: Sean Young <sean@mess.org> |
| |
| commit 0265634eb9e04a16ae99941c320718c38eb865e0 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> |
| |
| --- |
| drivers/media/rc/serial_ir.c | 115 +++++++++++++++++++++---------------------- |
| 1 file changed, 58 insertions(+), 57 deletions(-) |
| |
| --- a/drivers/media/rc/serial_ir.c |
| +++ b/drivers/media/rc/serial_ir.c |
| @@ -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); |
| @@ -533,7 +588,8 @@ static int serial_ir_probe(struct platfo |
| 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) |
| @@ -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) { |
| @@ -735,69 +790,15 @@ static int __init serial_ir_init_module( |
| 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(); |
| } |
| |