aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2016-02-10 03:59:50 -0500
committerMark Brown <broonie@kernel.org>2016-03-05 00:32:27 -0500
commit045b98480cbe9d8dfe80983013591769f8a112cc (patch)
treee657e3858d6bb9d621a7828ad3a1e3e886e24757
parent92e963f50fc74041b5e9e744c330dca48e04f08d (diff)
regmap: irq: add devm apis for regmap_{add,del}_irq_chip
Add device managed APIs for regmap_add_irq_chip() and regmap_del_irq_chip() so that it can be managed by device framework for freeing it. This helps on following: 1. Maintaining the sequence of resource allocation and deallocation regmap_add_irq_chip(&d); devm_requested_threaded_irq(virq) On free path: regmap_del_irq_chip(d); and then removing the irq registration. On this case, regmap irq is deleted before the irq is free. This force to use normal irq registration. By using devm apis, the sequence can be maintain properly: devm_regmap_add_irq_chip(&d); devm_requested_threaded_irq(virq); and resource deallocation will be done in reverse order by device framework. 2. No need to delete the regmap_irq_chip in error path or remove callback and hence there is less code on this path. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/base/regmap/regmap-irq.c82
-rw-r--r--include/linux/regmap.h8
2 files changed, 90 insertions, 0 deletions
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 9b0d202414d0..0b0ea3b88a91 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -674,6 +674,88 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
674} 674}
675EXPORT_SYMBOL_GPL(regmap_del_irq_chip); 675EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
676 676
677static void devm_regmap_irq_chip_release(struct device *dev, void *res)
678{
679 struct regmap_irq_chip_data *d = *(struct regmap_irq_chip_data **)res;
680
681 regmap_del_irq_chip(d->irq, d);
682}
683
684static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
685
686{
687 struct regmap_irq_chip_data **r = res;
688
689 if (!r || !*r) {
690 WARN_ON(!r || !*r);
691 return 0;
692 }
693 return *r == data;
694}
695
696/**
697 * devm_regmap_add_irq_chip(): Resource manager regmap_add_irq_chip()
698 *
699 * @dev: The device pointer on which irq_chip belongs to.
700 * @map: The regmap for the device.
701 * @irq: The IRQ the device uses to signal interrupts
702 * @irq_flags: The IRQF_ flags to use for the primary interrupt.
703 * @chip: Configuration for the interrupt controller.
704 * @data: Runtime data structure for the controller, allocated on success
705 *
706 * Returns 0 on success or an errno on failure.
707 *
708 * The regmap_irq_chip data automatically be released when the device is
709 * unbound.
710 */
711int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
712 int irq_flags, int irq_base,
713 const struct regmap_irq_chip *chip,
714 struct regmap_irq_chip_data **data)
715{
716 struct regmap_irq_chip_data **ptr, *d;
717 int ret;
718
719 ptr = devres_alloc(devm_regmap_irq_chip_release, sizeof(*ptr),
720 GFP_KERNEL);
721 if (!ptr)
722 return -ENOMEM;
723
724 ret = regmap_add_irq_chip(map, irq, irq_flags, irq_base,
725 chip, &d);
726 if (ret < 0) {
727 devres_free(ptr);
728 return ret;
729 }
730
731 *ptr = d;
732 devres_add(dev, ptr);
733 *data = d;
734 return 0;
735}
736EXPORT_SYMBOL_GPL(devm_regmap_add_irq_chip);
737
738/**
739 * devm_regmap_del_irq_chip(): Resource managed regmap_del_irq_chip()
740 *
741 * @dev: Device for which which resource was allocated.
742 * @irq: Primary IRQ for the device
743 * @d: regmap_irq_chip_data allocated by regmap_add_irq_chip()
744 */
745void devm_regmap_del_irq_chip(struct device *dev, int irq,
746 struct regmap_irq_chip_data *data)
747{
748 int rc;
749
750 WARN_ON(irq != data->irq);
751 rc = devres_release(dev, devm_regmap_irq_chip_release,
752 devm_regmap_irq_chip_match, data);
753
754 if (rc != 0)
755 WARN_ON(rc);
756}
757EXPORT_SYMBOL_GPL(devm_regmap_del_irq_chip);
758
677/** 759/**
678 * regmap_irq_chip_get_base(): Retrieve interrupt base for a regmap IRQ chip 760 * regmap_irq_chip_get_base(): Retrieve interrupt base for a regmap IRQ chip
679 * 761 *
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
index 18394343f489..de428962bfe6 100644
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -868,6 +868,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
868 int irq_base, const struct regmap_irq_chip *chip, 868 int irq_base, const struct regmap_irq_chip *chip,
869 struct regmap_irq_chip_data **data); 869 struct regmap_irq_chip_data **data);
870void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data); 870void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
871
872int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
873 int irq_flags, int irq_base,
874 const struct regmap_irq_chip *chip,
875 struct regmap_irq_chip_data **data);
876void devm_regmap_del_irq_chip(struct device *dev, int irq,
877 struct regmap_irq_chip_data *data);
878
871int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data); 879int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
872int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq); 880int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
873struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data); 881struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);