diff options
author | Luis Henriques <luis.henriques@canonical.com> | 2012-04-21 11:25:21 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-21 12:40:01 -0400 |
commit | 423b4f2750ebb8cb06c20396b66fb0144b92bbda (patch) | |
tree | 737ae2ca8eac42b98908c7a8248380c176896d23 | |
parent | dbda13fc2193061009cd20998f64dd01a97309a9 (diff) |
media: rc: Postpone ISR registration
commit 9ef449c6b31bb6a8e6dedc24de475a3b8c79be20 upstream.
An early registration of an ISR was causing a crash to several users (for
example, with the ite-cir driver: http://bugs.launchpad.net/bugs/972723).
The reason was that IRQs were being triggered before a driver
initialisation was completed.
This patch fixes this by moving the invocation to request_irq() and to
request_region() to a later stage on the driver probe function.
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
Acked-by: Jarod Wilson <jarod@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/media/rc/ene_ir.c | 32 | ||||
-rw-r--r-- | drivers/media/rc/fintek-cir.c | 20 | ||||
-rw-r--r-- | drivers/media/rc/ite-cir.c | 20 | ||||
-rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 36 | ||||
-rw-r--r-- | drivers/media/rc/winbond-cir.c | 78 |
5 files changed, 93 insertions, 93 deletions
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index a43ed6c41bf..12b91ae1b20 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c | |||
@@ -1017,22 +1017,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | |||
1017 | 1017 | ||
1018 | spin_lock_init(&dev->hw_lock); | 1018 | spin_lock_init(&dev->hw_lock); |
1019 | 1019 | ||
1020 | /* claim the resources */ | ||
1021 | error = -EBUSY; | ||
1022 | dev->hw_io = pnp_port_start(pnp_dev, 0); | ||
1023 | if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { | ||
1024 | dev->hw_io = -1; | ||
1025 | dev->irq = -1; | ||
1026 | goto error; | ||
1027 | } | ||
1028 | |||
1029 | dev->irq = pnp_irq(pnp_dev, 0); | ||
1030 | if (request_irq(dev->irq, ene_isr, | ||
1031 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { | ||
1032 | dev->irq = -1; | ||
1033 | goto error; | ||
1034 | } | ||
1035 | |||
1036 | pnp_set_drvdata(pnp_dev, dev); | 1020 | pnp_set_drvdata(pnp_dev, dev); |
1037 | dev->pnp_dev = pnp_dev; | 1021 | dev->pnp_dev = pnp_dev; |
1038 | 1022 | ||
@@ -1085,6 +1069,22 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) | |||
1085 | device_set_wakeup_capable(&pnp_dev->dev, true); | 1069 | device_set_wakeup_capable(&pnp_dev->dev, true); |
1086 | device_set_wakeup_enable(&pnp_dev->dev, true); | 1070 | device_set_wakeup_enable(&pnp_dev->dev, true); |
1087 | 1071 | ||
1072 | /* claim the resources */ | ||
1073 | error = -EBUSY; | ||
1074 | dev->hw_io = pnp_port_start(pnp_dev, 0); | ||
1075 | if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { | ||
1076 | dev->hw_io = -1; | ||
1077 | dev->irq = -1; | ||
1078 | goto error; | ||
1079 | } | ||
1080 | |||
1081 | dev->irq = pnp_irq(pnp_dev, 0); | ||
1082 | if (request_irq(dev->irq, ene_isr, | ||
1083 | IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) { | ||
1084 | dev->irq = -1; | ||
1085 | goto error; | ||
1086 | } | ||
1087 | |||
1088 | error = rc_register_device(rdev); | 1088 | error = rc_register_device(rdev); |
1089 | if (error < 0) | 1089 | if (error < 0) |
1090 | goto error; | 1090 | goto error; |
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c index 7f7079b12f2..4218f7369c5 100644 --- a/drivers/media/rc/fintek-cir.c +++ b/drivers/media/rc/fintek-cir.c | |||
@@ -504,16 +504,6 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id | |||
504 | 504 | ||
505 | spin_lock_init(&fintek->fintek_lock); | 505 | spin_lock_init(&fintek->fintek_lock); |
506 | 506 | ||
507 | ret = -EBUSY; | ||
508 | /* now claim resources */ | ||
509 | if (!request_region(fintek->cir_addr, | ||
510 | fintek->cir_port_len, FINTEK_DRIVER_NAME)) | ||
511 | goto failure; | ||
512 | |||
513 | if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED, | ||
514 | FINTEK_DRIVER_NAME, (void *)fintek)) | ||
515 | goto failure; | ||
516 | |||
517 | pnp_set_drvdata(pdev, fintek); | 507 | pnp_set_drvdata(pdev, fintek); |
518 | fintek->pdev = pdev; | 508 | fintek->pdev = pdev; |
519 | 509 | ||
@@ -548,6 +538,16 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id | |||
548 | /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ | 538 | /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ |
549 | rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); | 539 | rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); |
550 | 540 | ||
541 | ret = -EBUSY; | ||
542 | /* now claim resources */ | ||
543 | if (!request_region(fintek->cir_addr, | ||
544 | fintek->cir_port_len, FINTEK_DRIVER_NAME)) | ||
545 | goto failure; | ||
546 | |||
547 | if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED, | ||
548 | FINTEK_DRIVER_NAME, (void *)fintek)) | ||
549 | goto failure; | ||
550 | |||
551 | ret = rc_register_device(rdev); | 551 | ret = rc_register_device(rdev); |
552 | if (ret) | 552 | if (ret) |
553 | goto failure; | 553 | goto failure; |
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index ecd3d028076..c5ca0914087 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c | |||
@@ -1519,16 +1519,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id | |||
1519 | /* initialize raw event */ | 1519 | /* initialize raw event */ |
1520 | init_ir_raw_event(&itdev->rawir); | 1520 | init_ir_raw_event(&itdev->rawir); |
1521 | 1521 | ||
1522 | ret = -EBUSY; | ||
1523 | /* now claim resources */ | ||
1524 | if (!request_region(itdev->cir_addr, | ||
1525 | dev_desc->io_region_size, ITE_DRIVER_NAME)) | ||
1526 | goto failure; | ||
1527 | |||
1528 | if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED, | ||
1529 | ITE_DRIVER_NAME, (void *)itdev)) | ||
1530 | goto failure; | ||
1531 | |||
1532 | /* set driver data into the pnp device */ | 1522 | /* set driver data into the pnp device */ |
1533 | pnp_set_drvdata(pdev, itdev); | 1523 | pnp_set_drvdata(pdev, itdev); |
1534 | itdev->pdev = pdev; | 1524 | itdev->pdev = pdev; |
@@ -1604,6 +1594,16 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id | |||
1604 | rdev->driver_name = ITE_DRIVER_NAME; | 1594 | rdev->driver_name = ITE_DRIVER_NAME; |
1605 | rdev->map_name = RC_MAP_RC6_MCE; | 1595 | rdev->map_name = RC_MAP_RC6_MCE; |
1606 | 1596 | ||
1597 | ret = -EBUSY; | ||
1598 | /* now claim resources */ | ||
1599 | if (!request_region(itdev->cir_addr, | ||
1600 | dev_desc->io_region_size, ITE_DRIVER_NAME)) | ||
1601 | goto failure; | ||
1602 | |||
1603 | if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED, | ||
1604 | ITE_DRIVER_NAME, (void *)itdev)) | ||
1605 | goto failure; | ||
1606 | |||
1607 | ret = rc_register_device(rdev); | 1607 | ret = rc_register_device(rdev); |
1608 | if (ret) | 1608 | if (ret) |
1609 | goto failure; | 1609 | goto failure; |
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 9fd019e6b9b..c212276202f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c | |||
@@ -1027,24 +1027,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) | |||
1027 | spin_lock_init(&nvt->nvt_lock); | 1027 | spin_lock_init(&nvt->nvt_lock); |
1028 | spin_lock_init(&nvt->tx.lock); | 1028 | spin_lock_init(&nvt->tx.lock); |
1029 | 1029 | ||
1030 | ret = -EBUSY; | ||
1031 | /* now claim resources */ | ||
1032 | if (!request_region(nvt->cir_addr, | ||
1033 | CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) | ||
1034 | goto failure; | ||
1035 | |||
1036 | if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, | ||
1037 | NVT_DRIVER_NAME, (void *)nvt)) | ||
1038 | goto failure; | ||
1039 | |||
1040 | if (!request_region(nvt->cir_wake_addr, | ||
1041 | CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) | ||
1042 | goto failure; | ||
1043 | |||
1044 | if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, | ||
1045 | NVT_DRIVER_NAME, (void *)nvt)) | ||
1046 | goto failure; | ||
1047 | |||
1048 | pnp_set_drvdata(pdev, nvt); | 1030 | pnp_set_drvdata(pdev, nvt); |
1049 | nvt->pdev = pdev; | 1031 | nvt->pdev = pdev; |
1050 | 1032 | ||
@@ -1091,6 +1073,24 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) | |||
1091 | rdev->tx_resolution = XYZ; | 1073 | rdev->tx_resolution = XYZ; |
1092 | #endif | 1074 | #endif |
1093 | 1075 | ||
1076 | ret = -EBUSY; | ||
1077 | /* now claim resources */ | ||
1078 | if (!request_region(nvt->cir_addr, | ||
1079 | CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) | ||
1080 | goto failure; | ||
1081 | |||
1082 | if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, | ||
1083 | NVT_DRIVER_NAME, (void *)nvt)) | ||
1084 | goto failure; | ||
1085 | |||
1086 | if (!request_region(nvt->cir_wake_addr, | ||
1087 | CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) | ||
1088 | goto failure; | ||
1089 | |||
1090 | if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, | ||
1091 | NVT_DRIVER_NAME, (void *)nvt)) | ||
1092 | goto failure; | ||
1093 | |||
1094 | ret = rc_register_device(rdev); | 1094 | ret = rc_register_device(rdev); |
1095 | if (ret) | 1095 | if (ret) |
1096 | goto failure; | 1096 | goto failure; |
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c index 6f03846ab1f..9e55a0c9ac5 100644 --- a/drivers/media/rc/winbond-cir.c +++ b/drivers/media/rc/winbond-cir.c | |||
@@ -1003,39 +1003,10 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
1003 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", | 1003 | "(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n", |
1004 | data->wbase, data->ebase, data->sbase, data->irq); | 1004 | data->wbase, data->ebase, data->sbase, data->irq); |
1005 | 1005 | ||
1006 | if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { | ||
1007 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1008 | data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); | ||
1009 | err = -EBUSY; | ||
1010 | goto exit_free_data; | ||
1011 | } | ||
1012 | |||
1013 | if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { | ||
1014 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1015 | data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); | ||
1016 | err = -EBUSY; | ||
1017 | goto exit_release_wbase; | ||
1018 | } | ||
1019 | |||
1020 | if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { | ||
1021 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1022 | data->sbase, data->sbase + SP_IOMEM_LEN - 1); | ||
1023 | err = -EBUSY; | ||
1024 | goto exit_release_ebase; | ||
1025 | } | ||
1026 | |||
1027 | err = request_irq(data->irq, wbcir_irq_handler, | ||
1028 | IRQF_DISABLED, DRVNAME, device); | ||
1029 | if (err) { | ||
1030 | dev_err(dev, "Failed to claim IRQ %u\n", data->irq); | ||
1031 | err = -EBUSY; | ||
1032 | goto exit_release_sbase; | ||
1033 | } | ||
1034 | |||
1035 | led_trigger_register_simple("cir-tx", &data->txtrigger); | 1006 | led_trigger_register_simple("cir-tx", &data->txtrigger); |
1036 | if (!data->txtrigger) { | 1007 | if (!data->txtrigger) { |
1037 | err = -ENOMEM; | 1008 | err = -ENOMEM; |
1038 | goto exit_free_irq; | 1009 | goto exit_free_data; |
1039 | } | 1010 | } |
1040 | 1011 | ||
1041 | led_trigger_register_simple("cir-rx", &data->rxtrigger); | 1012 | led_trigger_register_simple("cir-rx", &data->rxtrigger); |
@@ -1074,9 +1045,38 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
1074 | data->dev->priv = data; | 1045 | data->dev->priv = data; |
1075 | data->dev->dev.parent = &device->dev; | 1046 | data->dev->dev.parent = &device->dev; |
1076 | 1047 | ||
1048 | if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) { | ||
1049 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1050 | data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1); | ||
1051 | err = -EBUSY; | ||
1052 | goto exit_free_rc; | ||
1053 | } | ||
1054 | |||
1055 | if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) { | ||
1056 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1057 | data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1); | ||
1058 | err = -EBUSY; | ||
1059 | goto exit_release_wbase; | ||
1060 | } | ||
1061 | |||
1062 | if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) { | ||
1063 | dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", | ||
1064 | data->sbase, data->sbase + SP_IOMEM_LEN - 1); | ||
1065 | err = -EBUSY; | ||
1066 | goto exit_release_ebase; | ||
1067 | } | ||
1068 | |||
1069 | err = request_irq(data->irq, wbcir_irq_handler, | ||
1070 | IRQF_DISABLED, DRVNAME, device); | ||
1071 | if (err) { | ||
1072 | dev_err(dev, "Failed to claim IRQ %u\n", data->irq); | ||
1073 | err = -EBUSY; | ||
1074 | goto exit_release_sbase; | ||
1075 | } | ||
1076 | |||
1077 | err = rc_register_device(data->dev); | 1077 | err = rc_register_device(data->dev); |
1078 | if (err) | 1078 | if (err) |
1079 | goto exit_free_rc; | 1079 | goto exit_free_irq; |
1080 | 1080 | ||
1081 | device_init_wakeup(&device->dev, 1); | 1081 | device_init_wakeup(&device->dev, 1); |
1082 | 1082 | ||
@@ -1084,14 +1084,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
1084 | 1084 | ||
1085 | return 0; | 1085 | return 0; |
1086 | 1086 | ||
1087 | exit_free_rc: | ||
1088 | rc_free_device(data->dev); | ||
1089 | exit_unregister_led: | ||
1090 | led_classdev_unregister(&data->led); | ||
1091 | exit_unregister_rxtrigger: | ||
1092 | led_trigger_unregister_simple(data->rxtrigger); | ||
1093 | exit_unregister_txtrigger: | ||
1094 | led_trigger_unregister_simple(data->txtrigger); | ||
1095 | exit_free_irq: | 1087 | exit_free_irq: |
1096 | free_irq(data->irq, device); | 1088 | free_irq(data->irq, device); |
1097 | exit_release_sbase: | 1089 | exit_release_sbase: |
@@ -1100,6 +1092,14 @@ exit_release_ebase: | |||
1100 | release_region(data->ebase, EHFUNC_IOMEM_LEN); | 1092 | release_region(data->ebase, EHFUNC_IOMEM_LEN); |
1101 | exit_release_wbase: | 1093 | exit_release_wbase: |
1102 | release_region(data->wbase, WAKEUP_IOMEM_LEN); | 1094 | release_region(data->wbase, WAKEUP_IOMEM_LEN); |
1095 | exit_free_rc: | ||
1096 | rc_free_device(data->dev); | ||
1097 | exit_unregister_led: | ||
1098 | led_classdev_unregister(&data->led); | ||
1099 | exit_unregister_rxtrigger: | ||
1100 | led_trigger_unregister_simple(data->rxtrigger); | ||
1101 | exit_unregister_txtrigger: | ||
1102 | led_trigger_unregister_simple(data->txtrigger); | ||
1103 | exit_free_data: | 1103 | exit_free_data: |
1104 | kfree(data); | 1104 | kfree(data); |
1105 | pnp_set_drvdata(device, NULL); | 1105 | pnp_set_drvdata(device, NULL); |