Commit 3dfaff27 authored by Charles Keepax's avatar Charles Keepax Committed by Lee Jones
Browse files

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: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 1a86dcb3
Loading
Loading
Loading
Loading
+41 −18
Original line number Diff line number Diff line
@@ -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;