I noticed there were a number of problems with the init and shutdown
routines for the code in drivers/cbus/retu*. This patch (for review)
attempts to fix them.
commit 59e589227131abbe5e07576f542cc35a8821c9d3
Author: Andrew de Quincey <adq@xxxxxxxxxxxxx>
Date: Mon May 25 23:58:27 2009 +0100
Correctness fixes for the retu drivers
diff --git a/drivers/cbus/retu-headset.c b/drivers/cbus/retu-headset.c
index e798bc2..fe8266f 100644
--- a/drivers/cbus/retu-headset.c
+++ b/drivers/cbus/retu-headset.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Nokia Corporation
*
- * Written by Juha Yrj�+ * Written by Juha Yrj�l�
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
@@ -265,6 +265,8 @@ static int __init retu_headset_probe(struct platform_device *pdev)
retu_disable_irq(RETU_INT_HOOK);
return 0;
err6:
+ del_timer_sync(&hs->enable_timer);
+ del_timer_sync(&hs->detect_timer);
device_remove_file(&pdev->dev, &dev_attr_enable_det);
err5:
device_remove_file(&pdev->dev, &dev_attr_enable);
@@ -291,6 +293,7 @@ static int retu_headset_remove(struct platform_device *pdev)
retu_free_irq(RETU_INT_HOOK);
input_unregister_device(hs->idev);
input_free_device(hs->idev);
+ kfree(hs);
return 0;
}
@@ -352,4 +355,4 @@ module_exit(retu_headset_exit);
MODULE_DESCRIPTION("Retu/Vilma headset detection");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Juha Yrj�);
+MODULE_AUTHOR("Juha Yrj�l�");
diff --git a/drivers/cbus/retu-pwrbutton.c b/drivers/cbus/retu-pwrbutton.c
index 38d7aa4..cc47691 100644
--- a/drivers/cbus/retu-pwrbutton.c
+++ b/drivers/cbus/retu-pwrbutton.c
@@ -7,7 +7,7 @@
*
* Written by Ari Saastamoinen <ari.saastamoinen@xxxxxxxxxxxxxx>
*
- * Contact Juha Yrj�<juha.yrjola@xxxxxxxxx>
+ * Contact Juha Yrj�l� <juha.yrjola@xxxxxxxxx>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
@@ -75,29 +75,40 @@ static void retubutton_irq(unsigned long arg)
*/
static int __init retubutton_init(void)
{
- int irq;
-
- printk(KERN_INFO "Retu power button driver initialized\n");
- irq = RETU_INT_PWR;
+ int ret;
init_timer(&pwrbtn_timer);
pwrbtn_timer.function = retubutton_timer_func;
- if (retu_request_irq(irq, &retubutton_irq, 0, "PwrOnX") < 0) {
+ if (retu_request_irq(RETU_INT_PWR, &retubutton_irq, 0, "PwrOnX") < 0) {
+ del_timer_sync(&pwrbtn_timer);
printk(KERN_ERR "%s@%s: Cannot allocate irq\n",
__FUNCTION__, __FILE__);
return -EBUSY;
}
pwrbtn_dev = input_allocate_device();
- if (!pwrbtn_dev)
+ if (!pwrbtn_dev) {
+ retu_free_irq(RETU_INT_PWR);
+ del_timer_sync(&pwrbtn_timer);
return -ENOMEM;
+ }
pwrbtn_dev->evbit[0] = BIT_MASK(EV_KEY);
pwrbtn_dev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
pwrbtn_dev->name = "retu-pwrbutton";
- return input_register_device(pwrbtn_dev);
+ ret = input_register_device(pwrbtn_dev);
+ if (ret < 0) {
+ retu_free_irq(RETU_INT_PWR);
+ del_timer_sync(&pwrbtn_timer);
+ input_free_device(pwrbtn_dev);
+ return ret;
+ }
+
+ printk(KERN_INFO "Retu power button driver initialized\n");
+
+ return 0;
}
/**
@@ -108,6 +119,7 @@ static void __exit retubutton_exit(void)
retu_free_irq(RETU_INT_PWR);
del_timer_sync(&pwrbtn_timer);
input_unregister_device(pwrbtn_dev);
+ input_free_device(pwrbtn_dev);
}
module_init(retubutton_init);
diff --git a/drivers/cbus/retu-rtc.c b/drivers/cbus/retu-rtc.c
index 76343f9..5a6a816 100644
--- a/drivers/cbus/retu-rtc.c
+++ b/drivers/cbus/retu-rtc.c
@@ -381,7 +381,7 @@ static int __devinit retu_rtc_probe(struct platform_device *pdev)
retu_rtc_do_reset();
if ((r = device_create_file(&(pdev->dev), &dev_attr_time)) != 0)
- return r;
+ goto err_free_irqs;
else if ((r = device_create_file(&(pdev->dev), &dev_attr_reset)) != 0)
goto err_unregister_time;
else if ((r = device_create_file(&(pdev->dev), &dev_attr_alarm)) != 0)
@@ -401,6 +401,9 @@ err_unregister_reset:
device_remove_file(&(pdev->dev), &dev_attr_reset);
err_unregister_time:
device_remove_file(&(pdev->dev), &dev_attr_time);
+err_free_irqs:
+ retu_free_irq(RETU_INT_RTCS);
+ retu_free_irq(RETU_INT_RTCA);
return r;
}
diff --git a/drivers/cbus/retu.c b/drivers/cbus/retu.c
index d9f28d5..8c0d7cb 100644
--- a/drivers/cbus/retu.c
+++ b/drivers/cbus/retu.c
@@ -331,6 +331,7 @@ static int __devinit retu_probe(struct platform_device *pdev)
struct omap_em_asic_bb5_config);
if (em_asic_config == NULL) {
printk(KERN_ERR PFX "Unable to retrieve config data\n");
+ tasklet_kill(&retu_tasklet);
return -ENODATA;
}
@@ -338,6 +339,7 @@ static int __devinit retu_probe(struct platform_device *pdev)
if ((ret = gpio_request(retu_irq_pin, "RETU irq")) < 0) {
printk(KERN_ERR PFX "Unable to reserve IRQ GPIO\n");
+ tasklet_kill(&retu_tasklet);
return ret;
}
@@ -364,6 +366,7 @@ static int __devinit retu_probe(struct platform_device *pdev)
if (ret < 0) {
printk(KERN_ERR PFX "Unable to register IRQ handler\n");
gpio_free(retu_irq_pin);
+ tasklet_kill(&retu_tasklet);
return ret;
}
set_irq_wake(gpio_to_irq(retu_irq_pin), 1);
@@ -377,6 +380,7 @@ static int __devinit retu_probe(struct platform_device *pdev)
printk(KERN_ERR "Unable to initialize driver\n");
free_irq(gpio_to_irq(retu_irq_pin), 0);
gpio_free(retu_irq_pin);
+ tasklet_kill(&retu_tasklet);
return ret;
}
#endif