aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMatthijs Kooijman <matthijs@stdin.nl>2012-11-02 08:13:56 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-12-21 15:26:11 -0500
commit9fa35204dd19eb0e96ee870b7128a8f5da51dbfa (patch)
tree5496a8441112847b57a97324c39e907d77cff5c4 /drivers
parentd62b6818477704683d00c680335eff5833bd3906 (diff)
[media] rc: Call rc_register_device before irq setup
This should fix a potential race condition, when the irq handler triggers while rc_register_device is still setting up the rdev->raw device. This crash has not been observed in practice, but there should be a very small window where it could occur. Since ir_raw_event_store_with_filter checks if rdev->raw is not NULL before using it, this bug is not triggered if the request_irq triggers a pending irq directly (since rdev->raw will still be NULL then). This commit was tested on nuvoton-cir only. Cc: Jarod Wilson <jarod@redhat.com> Cc: Maxim Levitsky <maximlevitsky@gmail.com> Cc: David Härdeman <david@hardeman.nu> Signed-off-by: Matthijs Kooijman <matthijs@stdin.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/rc/ene_ir.c14
-rw-r--r--drivers/media/rc/ite-cir.c14
-rw-r--r--drivers/media/rc/nuvoton-cir.c14
-rw-r--r--drivers/media/rc/winbond-cir.c14
4 files changed, 28 insertions, 28 deletions
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index f7fdfea49ab1..e601166c1edb 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1075,10 +1075,14 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
1075 device_set_wakeup_capable(&pnp_dev->dev, true); 1075 device_set_wakeup_capable(&pnp_dev->dev, true);
1076 device_set_wakeup_enable(&pnp_dev->dev, true); 1076 device_set_wakeup_enable(&pnp_dev->dev, true);
1077 1077
1078 error = rc_register_device(rdev);
1079 if (error < 0)
1080 goto exit_free_dev_rdev;
1081
1078 /* claim the resources */ 1082 /* claim the resources */
1079 error = -EBUSY; 1083 error = -EBUSY;
1080 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { 1084 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
1081 goto exit_free_dev_rdev; 1085 goto exit_unregister_device;
1082 } 1086 }
1083 1087
1084 dev->irq = pnp_irq(pnp_dev, 0); 1088 dev->irq = pnp_irq(pnp_dev, 0);
@@ -1087,17 +1091,13 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
1087 goto exit_release_hw_io; 1091 goto exit_release_hw_io;
1088 } 1092 }
1089 1093
1090 error = rc_register_device(rdev);
1091 if (error < 0)
1092 goto exit_free_irq;
1093
1094 pr_notice("driver has been successfully loaded\n"); 1094 pr_notice("driver has been successfully loaded\n");
1095 return 0; 1095 return 0;
1096 1096
1097exit_free_irq:
1098 free_irq(dev->irq, dev);
1099exit_release_hw_io: 1097exit_release_hw_io:
1100 release_region(dev->hw_io, ENE_IO_SIZE); 1098 release_region(dev->hw_io, ENE_IO_SIZE);
1099exit_unregister_device:
1100 rc_unregister_device(rdev);
1101exit_free_dev_rdev: 1101exit_free_dev_rdev:
1102 rc_free_device(rdev); 1102 rc_free_device(rdev);
1103 kfree(dev); 1103 kfree(dev);
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 8e0e661b5ef9..e810846fada4 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1591,28 +1591,28 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
1591 rdev->driver_name = ITE_DRIVER_NAME; 1591 rdev->driver_name = ITE_DRIVER_NAME;
1592 rdev->map_name = RC_MAP_RC6_MCE; 1592 rdev->map_name = RC_MAP_RC6_MCE;
1593 1593
1594 ret = rc_register_device(rdev);
1595 if (ret)
1596 goto exit_free_dev_rdev;
1597
1594 ret = -EBUSY; 1598 ret = -EBUSY;
1595 /* now claim resources */ 1599 /* now claim resources */
1596 if (!request_region(itdev->cir_addr, 1600 if (!request_region(itdev->cir_addr,
1597 dev_desc->io_region_size, ITE_DRIVER_NAME)) 1601 dev_desc->io_region_size, ITE_DRIVER_NAME))
1598 goto exit_free_dev_rdev; 1602 goto exit_unregister_device;
1599 1603
1600 if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED, 1604 if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
1601 ITE_DRIVER_NAME, (void *)itdev)) 1605 ITE_DRIVER_NAME, (void *)itdev))
1602 goto exit_release_cir_addr; 1606 goto exit_release_cir_addr;
1603 1607
1604 ret = rc_register_device(rdev);
1605 if (ret)
1606 goto exit_free_irq;
1607
1608 ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); 1608 ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
1609 1609
1610 return 0; 1610 return 0;
1611 1611
1612exit_free_irq:
1613 free_irq(itdev->cir_irq, itdev);
1614exit_release_cir_addr: 1612exit_release_cir_addr:
1615 release_region(itdev->cir_addr, itdev->params.io_region_size); 1613 release_region(itdev->cir_addr, itdev->params.io_region_size);
1614exit_unregister_device:
1615 rc_unregister_device(rdev);
1616exit_free_dev_rdev: 1616exit_free_dev_rdev:
1617 rc_free_device(rdev); 1617 rc_free_device(rdev);
1618 kfree(itdev); 1618 kfree(itdev);
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index c6441e690dd4..6cf43cc237eb 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1067,11 +1067,15 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
1067#endif 1067#endif
1068 nvt->rdev = rdev; 1068 nvt->rdev = rdev;
1069 1069
1070 ret = rc_register_device(rdev);
1071 if (ret)
1072 goto exit_free_dev_rdev;
1073
1070 ret = -EBUSY; 1074 ret = -EBUSY;
1071 /* now claim resources */ 1075 /* now claim resources */
1072 if (!request_region(nvt->cir_addr, 1076 if (!request_region(nvt->cir_addr,
1073 CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) 1077 CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
1074 goto exit_free_dev_rdev; 1078 goto exit_unregister_device;
1075 1079
1076 if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, 1080 if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
1077 NVT_DRIVER_NAME, (void *)nvt)) 1081 NVT_DRIVER_NAME, (void *)nvt))
@@ -1085,10 +1089,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
1085 NVT_DRIVER_NAME, (void *)nvt)) 1089 NVT_DRIVER_NAME, (void *)nvt))
1086 goto exit_release_cir_wake_addr; 1090 goto exit_release_cir_wake_addr;
1087 1091
1088 ret = rc_register_device(rdev);
1089 if (ret)
1090 goto exit_free_wake_irq;
1091
1092 device_init_wakeup(&pdev->dev, true); 1092 device_init_wakeup(&pdev->dev, true);
1093 1093
1094 nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); 1094 nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n");
@@ -1099,14 +1099,14 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
1099 1099
1100 return 0; 1100 return 0;
1101 1101
1102exit_free_wake_irq:
1103 free_irq(nvt->cir_wake_irq, nvt);
1104exit_release_cir_wake_addr: 1102exit_release_cir_wake_addr:
1105 release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); 1103 release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
1106exit_free_irq: 1104exit_free_irq:
1107 free_irq(nvt->cir_irq, nvt); 1105 free_irq(nvt->cir_irq, nvt);
1108exit_release_cir_addr: 1106exit_release_cir_addr:
1109 release_region(nvt->cir_addr, CIR_IOREG_LENGTH); 1107 release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
1108exit_unregister_device:
1109 rc_unregister_device(rdev);
1110exit_free_dev_rdev: 1110exit_free_dev_rdev:
1111 rc_free_device(rdev); 1111 rc_free_device(rdev);
1112 kfree(nvt); 1112 kfree(nvt);
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 7f3c476dde05..553d1cdc439f 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1093,11 +1093,15 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
1093 data->dev->rx_resolution = US_TO_NS(2); 1093 data->dev->rx_resolution = US_TO_NS(2);
1094 data->dev->allowed_protos = RC_BIT_ALL; 1094 data->dev->allowed_protos = RC_BIT_ALL;
1095 1095
1096 err = rc_register_device(data->dev);
1097 if (err)
1098 goto exit_free_rc;
1099
1096 if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { 1100 if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
1097 dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", 1101 dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
1098 data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); 1102 data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
1099 err = -EBUSY; 1103 err = -EBUSY;
1100 goto exit_free_rc; 1104 goto exit_unregister_device;
1101 } 1105 }
1102 1106
1103 if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { 1107 if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
@@ -1122,24 +1126,20 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
1122 goto exit_release_sbase; 1126 goto exit_release_sbase;
1123 } 1127 }
1124 1128
1125 err = rc_register_device(data->dev);
1126 if (err)
1127 goto exit_free_irq;
1128
1129 device_init_wakeup(&device->dev, 1); 1129 device_init_wakeup(&device->dev, 1);
1130 1130
1131 wbcir_init_hw(data); 1131 wbcir_init_hw(data);
1132 1132
1133 return 0; 1133 return 0;
1134 1134
1135exit_free_irq:
1136 free_irq(data->irq, device);
1137exit_release_sbase: 1135exit_release_sbase:
1138 release_region(data->sbase, SP_IOMEM_LEN); 1136 release_region(data->sbase, SP_IOMEM_LEN);
1139exit_release_ebase: 1137exit_release_ebase:
1140 release_region(data->ebase, EHFUNC_IOMEM_LEN); 1138 release_region(data->ebase, EHFUNC_IOMEM_LEN);
1141exit_release_wbase: 1139exit_release_wbase:
1142 release_region(data->wbase, WAKEUP_IOMEM_LEN); 1140 release_region(data->wbase, WAKEUP_IOMEM_LEN);
1141exit_unregister_device:
1142 rc_unregister_device(data->dev);
1143exit_free_rc: 1143exit_free_rc:
1144 rc_free_device(data->dev); 1144 rc_free_device(data->dev);
1145exit_unregister_led: 1145exit_unregister_led: