From 26eb387265872b59566ddeed5e9bf142a6b9ff5b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 Nov 2010 23:08:38 +0100 Subject: gpio-charger: Fix potential race between irq handler and probe/remove This patch fixes a potential race between the irq handler and the probe and remove functions. The irq should not be requested before the chargers power_supply has been registered and has to be freed before the power_supply is unregistered, otherwise it is possible that the irq fires while the power_supply is not initialized yet or has already been freed. While we are at it replace request_irq with request_any_context_irq. Signed-off-by: Lars-Peter Clausen Signed-off-by: Anton Vorontsov --- drivers/power/gpio-charger.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'drivers/power/gpio-charger.c') diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c index 43078e34428a..25b88ac1d44c 100644 --- a/drivers/power/gpio-charger.c +++ b/drivers/power/gpio-charger.c @@ -98,7 +98,7 @@ static int __devinit gpio_charger_probe(struct platform_device *pdev) charger->type = pdata->type; charger->properties = gpio_charger_properties; charger->num_properties = ARRAY_SIZE(gpio_charger_properties); - charger->get_property = gpio_charger_get_property; + charger->get_property = gpio_charger_get_property; charger->supplied_to = pdata->supplied_to; charger->num_supplicants = pdata->num_supplicants; @@ -113,9 +113,18 @@ static int __devinit gpio_charger_probe(struct platform_device *pdev) goto err_gpio_free; } + gpio_charger->pdata = pdata; + + ret = power_supply_register(&pdev->dev, charger); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register power supply: %d\n", + ret); + goto err_gpio_free; + } + irq = gpio_to_irq(pdata->gpio); if (irq > 0) { - ret = request_irq(irq, gpio_charger_irq, + ret = request_any_context_irq(irq, gpio_charger_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), charger); if (ret) @@ -124,21 +133,10 @@ static int __devinit gpio_charger_probe(struct platform_device *pdev) gpio_charger->irq = irq; } - gpio_charger->pdata = pdata; - - ret = power_supply_register(&pdev->dev, charger); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register power supply: %d\n", ret); - goto err_irq_free; - } - platform_set_drvdata(pdev, gpio_charger); return 0; -err_irq_free: - if (gpio_charger->irq) - free_irq(gpio_charger->irq, charger); err_gpio_free: gpio_free(pdata->gpio); err_free: @@ -150,10 +148,11 @@ static int __devexit gpio_charger_remove(struct platform_device *pdev) { struct gpio_charger *gpio_charger = platform_get_drvdata(pdev); - power_supply_unregister(&gpio_charger->charger); - if (gpio_charger->irq) free_irq(gpio_charger->irq, &gpio_charger->charger); + + power_supply_unregister(&gpio_charger->charger); + gpio_free(gpio_charger->pdata->gpio); platform_set_drvdata(pdev, NULL); -- cgit v1.2.3