diff options
author | Matthijs Kooijman <matthijs@stdin.nl> | 2012-11-02 08:13:56 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-12-21 15:26:11 -0500 |
commit | 9fa35204dd19eb0e96ee870b7128a8f5da51dbfa (patch) | |
tree | 5496a8441112847b57a97324c39e907d77cff5c4 /drivers | |
parent | d62b6818477704683d00c680335eff5833bd3906 (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.c | 14 | ||||
-rw-r--r-- | drivers/media/rc/ite-cir.c | 14 | ||||
-rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 14 | ||||
-rw-r--r-- | drivers/media/rc/winbond-cir.c | 14 |
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 | ||
1097 | exit_free_irq: | ||
1098 | free_irq(dev->irq, dev); | ||
1099 | exit_release_hw_io: | 1097 | exit_release_hw_io: |
1100 | release_region(dev->hw_io, ENE_IO_SIZE); | 1098 | release_region(dev->hw_io, ENE_IO_SIZE); |
1099 | exit_unregister_device: | ||
1100 | rc_unregister_device(rdev); | ||
1101 | exit_free_dev_rdev: | 1101 | exit_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 | ||
1612 | exit_free_irq: | ||
1613 | free_irq(itdev->cir_irq, itdev); | ||
1614 | exit_release_cir_addr: | 1612 | exit_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); |
1614 | exit_unregister_device: | ||
1615 | rc_unregister_device(rdev); | ||
1616 | exit_free_dev_rdev: | 1616 | exit_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 | ||
1102 | exit_free_wake_irq: | ||
1103 | free_irq(nvt->cir_wake_irq, nvt); | ||
1104 | exit_release_cir_wake_addr: | 1102 | exit_release_cir_wake_addr: |
1105 | release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); | 1103 | release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); |
1106 | exit_free_irq: | 1104 | exit_free_irq: |
1107 | free_irq(nvt->cir_irq, nvt); | 1105 | free_irq(nvt->cir_irq, nvt); |
1108 | exit_release_cir_addr: | 1106 | exit_release_cir_addr: |
1109 | release_region(nvt->cir_addr, CIR_IOREG_LENGTH); | 1107 | release_region(nvt->cir_addr, CIR_IOREG_LENGTH); |
1108 | exit_unregister_device: | ||
1109 | rc_unregister_device(rdev); | ||
1110 | exit_free_dev_rdev: | 1110 | exit_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 | ||
1135 | exit_free_irq: | ||
1136 | free_irq(data->irq, device); | ||
1137 | exit_release_sbase: | 1135 | exit_release_sbase: |
1138 | release_region(data->sbase, SP_IOMEM_LEN); | 1136 | release_region(data->sbase, SP_IOMEM_LEN); |
1139 | exit_release_ebase: | 1137 | exit_release_ebase: |
1140 | release_region(data->ebase, EHFUNC_IOMEM_LEN); | 1138 | release_region(data->ebase, EHFUNC_IOMEM_LEN); |
1141 | exit_release_wbase: | 1139 | exit_release_wbase: |
1142 | release_region(data->wbase, WAKEUP_IOMEM_LEN); | 1140 | release_region(data->wbase, WAKEUP_IOMEM_LEN); |
1141 | exit_unregister_device: | ||
1142 | rc_unregister_device(data->dev); | ||
1143 | exit_free_rc: | 1143 | exit_free_rc: |
1144 | rc_free_device(data->dev); | 1144 | rc_free_device(data->dev); |
1145 | exit_unregister_led: | 1145 | exit_unregister_led: |