]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
regmap: irq: add devm apis for regmap_{add,del}_irq_chip
authorLaxman Dewangan <ldewangan@nvidia.com>
Wed, 10 Feb 2016 08:59:50 +0000 (14:29 +0530)
committerMark Brown <broonie@kernel.org>
Sat, 5 Mar 2016 05:32:27 +0000 (14:32 +0900)
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>
drivers/base/regmap/regmap-irq.c
include/linux/regmap.h

index 9b0d202414d065bf6e03a6f39bb33c9925dee4db..0b0ea3b88a9173da325841571821731e222bc87c 100644 (file)
@@ -674,6 +674,88 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
 }
 EXPORT_SYMBOL_GPL(regmap_del_irq_chip);
 
+static void devm_regmap_irq_chip_release(struct device *dev, void *res)
+{
+       struct regmap_irq_chip_data *d = *(struct regmap_irq_chip_data **)res;
+
+       regmap_del_irq_chip(d->irq, d);
+}
+
+static int devm_regmap_irq_chip_match(struct device *dev, void *res, void *data)
+
+{
+       struct regmap_irq_chip_data **r = res;
+
+       if (!r || !*r) {
+               WARN_ON(!r || !*r);
+               return 0;
+       }
+       return *r == data;
+}
+
+/**
+ * devm_regmap_add_irq_chip(): Resource manager regmap_add_irq_chip()
+ *
+ * @dev:       The device pointer on which irq_chip belongs to.
+ * @map:       The regmap for the device.
+ * @irq:       The IRQ the device uses to signal interrupts
+ * @irq_flags: The IRQF_ flags to use for the primary interrupt.
+ * @chip:      Configuration for the interrupt controller.
+ * @data:      Runtime data structure for the controller, allocated on success
+ *
+ * Returns 0 on success or an errno on failure.
+ *
+ * The regmap_irq_chip data automatically be released when the device is
+ * unbound.
+ */
+int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
+                            int irq_flags, int irq_base,
+                            const struct regmap_irq_chip *chip,
+                            struct regmap_irq_chip_data **data)
+{
+       struct regmap_irq_chip_data **ptr, *d;
+       int ret;
+
+       ptr = devres_alloc(devm_regmap_irq_chip_release, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       ret = regmap_add_irq_chip(map, irq, irq_flags, irq_base,
+                                 chip, &d);
+       if (ret < 0) {
+               devres_free(ptr);
+               return ret;
+       }
+
+       *ptr = d;
+       devres_add(dev, ptr);
+       *data = d;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_regmap_add_irq_chip);
+
+/**
+ * devm_regmap_del_irq_chip(): Resource managed regmap_del_irq_chip()
+ *
+ * @dev: Device for which which resource was allocated.
+ * @irq: Primary IRQ for the device
+ * @d:   regmap_irq_chip_data allocated by regmap_add_irq_chip()
+ */
+void devm_regmap_del_irq_chip(struct device *dev, int irq,
+                             struct regmap_irq_chip_data *data)
+{
+       int rc;
+
+       WARN_ON(irq != data->irq);
+       rc = devres_release(dev, devm_regmap_irq_chip_release,
+                           devm_regmap_irq_chip_match, data);
+
+       if (rc != 0)
+               WARN_ON(rc);
+}
+EXPORT_SYMBOL_GPL(devm_regmap_del_irq_chip);
+
 /**
  * regmap_irq_chip_get_base(): Retrieve interrupt base for a regmap IRQ chip
  *
index 18394343f4891a42dc986e4a17e9c9ebb0b747ee..de428962bfe67b5bab578bb771b7370c79ed469e 100644 (file)
@@ -868,6 +868,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
                        int irq_base, const struct regmap_irq_chip *chip,
                        struct regmap_irq_chip_data **data);
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
+
+int devm_regmap_add_irq_chip(struct device *dev, struct regmap *map, int irq,
+                            int irq_flags, int irq_base,
+                            const struct regmap_irq_chip *chip,
+                            struct regmap_irq_chip_data **data);
+void devm_regmap_del_irq_chip(struct device *dev, int irq,
+                             struct regmap_irq_chip_data *data);
+
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
 struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);