mfd: arizona: Correctly clean up after IRQs

Currently we leak a lot of things when tearing down the IRQs this patch
fixes this cleaning up both the IRQ mappings and the IRQ domain itself.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
This commit is contained in:
Charles Keepax 2016-11-22 16:10:28 +00:00 committed by Lee Jones
parent 1a86dcb3f1
commit 3dfaff274d
1 changed files with 41 additions and 18 deletions

View File

@ -210,6 +210,7 @@ int arizona_irq_init(struct arizona *arizona)
int ret;
const struct regmap_irq_chip *aod, *irq;
struct irq_data *irq_data;
unsigned int virq;
arizona->ctrlif_error = true;
@ -321,26 +322,34 @@ int arizona_irq_init(struct arizona *arizona)
}
if (aod) {
ret = regmap_add_irq_chip(arizona->regmap,
irq_create_mapping(arizona->virq,
ARIZONA_AOD_IRQ_INDEX),
IRQF_ONESHOT, 0, aod,
&arizona->aod_irq_chip);
virq = irq_create_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
if (!virq) {
dev_err(arizona->dev, "Failed to map AOD IRQs\n");
ret = -EINVAL;
goto err_domain;
}
ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
0, aod, &arizona->aod_irq_chip);
if (ret != 0) {
dev_err(arizona->dev,
"Failed to add AOD IRQs: %d\n", ret);
goto err;
goto err_map_aod;
}
}
ret = regmap_add_irq_chip(arizona->regmap,
irq_create_mapping(arizona->virq,
ARIZONA_MAIN_IRQ_INDEX),
IRQF_ONESHOT, 0, irq,
&arizona->irq_chip);
virq = irq_create_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
if (!virq) {
dev_err(arizona->dev, "Failed to map main IRQs\n");
ret = -EINVAL;
goto err_aod;
}
ret = regmap_add_irq_chip(arizona->regmap, virq, IRQF_ONESHOT,
0, irq, &arizona->irq_chip);
if (ret != 0) {
dev_err(arizona->dev, "Failed to add main IRQs: %d\n", ret);
goto err_aod;
goto err_map_main_irq;
}
/* Used to emulate edge trigger and to work around broken pinmux */
@ -404,26 +413,40 @@ err_main_irq:
regmap_del_irq_chip(irq_find_mapping(arizona->virq,
ARIZONA_MAIN_IRQ_INDEX),
arizona->irq_chip);
err_map_main_irq:
irq_dispose_mapping(irq_find_mapping(arizona->virq,
ARIZONA_MAIN_IRQ_INDEX));
err_aod:
regmap_del_irq_chip(irq_find_mapping(arizona->virq,
ARIZONA_AOD_IRQ_INDEX),
arizona->aod_irq_chip);
err_map_aod:
irq_dispose_mapping(irq_find_mapping(arizona->virq,
ARIZONA_AOD_IRQ_INDEX));
err_domain:
irq_domain_remove(arizona->virq);
err:
return ret;
}
int arizona_irq_exit(struct arizona *arizona)
{
unsigned int virq;
if (arizona->ctrlif_error)
arizona_free_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR, arizona);
arizona_free_irq(arizona, ARIZONA_IRQ_BOOT_DONE, arizona);
regmap_del_irq_chip(irq_find_mapping(arizona->virq,
ARIZONA_MAIN_IRQ_INDEX),
arizona->irq_chip);
regmap_del_irq_chip(irq_find_mapping(arizona->virq,
ARIZONA_AOD_IRQ_INDEX),
arizona->aod_irq_chip);
virq = irq_find_mapping(arizona->virq, ARIZONA_MAIN_IRQ_INDEX);
regmap_del_irq_chip(virq, arizona->irq_chip);
irq_dispose_mapping(virq);
virq = irq_find_mapping(arizona->virq, ARIZONA_AOD_IRQ_INDEX);
regmap_del_irq_chip(virq, arizona->aod_irq_chip);
irq_dispose_mapping(virq);
irq_domain_remove(arizona->virq);
free_irq(arizona->irq, arizona);
return 0;