From: nyushchenko@dev.rtsoft.ru
To: Grant Likely <grant.likely@linaro.org>,
Rob Herring <robh+dt@kernel.org>,
Benjamin Herrenschmidt <benh@kernel.crashing.org>,
Thomas Gleixner <tglx@linutronix.de>,
devicetree@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, lugovskoy@dev.rtsoft.ru,
Nikita Yushchenko <nyushchenko@dev.rtsoft.ru>
Subject: [PATCH 01/21] irq: add devres version of OF IRQ mapping routines
Date: Wed, 4 Jun 2014 15:13:01 +0400 [thread overview]
Message-ID: <1401880402-30091-2-git-send-email-nyushchenko@dev.rtsoft.ru> (raw)
In-Reply-To: <1401880402-30091-1-git-send-email-nyushchenko@dev.rtsoft.ru>
From: Nikita Yushchenko <nyushchenko@dev.rtsoft.ru>
Many drivers use devres to manage their resources, and at the same time
use irq_of_parse_and_map() / irq_dispose_mapping(). This creates problem
on driver unload paths and on error paths:
- it is invalid to call irq_dispose_mapping() while IRQ handler is still
installed,
- devres moves removal of IRQ handler out of driver,
- without explicit devres support for IRQ mapping, irq_dispose_mapping()
stays in driver and thus gets called while IRQ handler is still
installed.
This patch adds devm_irq_create_of_mapping() and devm_irq_of_parse_and_map()
routines to be used by drivers for correct release of resources.
Signed-off-by: Nikita Yushchenko <nyushchenko@dev.rtsoft.ru>
---
drivers/of/irq.c | 24 +++++++++++++++++++++++
include/linux/irqdomain.h | 3 +++
include/linux/of_irq.h | 12 ++++++++++++
kernel/irq/irqdomain.c | 47 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 86 insertions(+)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 5aeb894..30b5010 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -46,6 +46,30 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
/**
+ * devm_irq_of_parse_and_map - Parse and map an interrupt into linux virq space
+ * @dev: Device interrupt will be used for
+ * @dn: Device node of the device whose interrupt is to be mapped
+ * @index: Index of the interrupt to map
+ *
+ * This function does the same as irq_of_parse_and_map(), but ensures that
+ * irq_dispose_mapping() will be called automatically at driver detatch.
+ *
+ * If IRQ mapping created by this function needs to be removed manually,
+ * devm_irq_dispose_mapping() must be called instead of irq_dispose_mapping().
+ */
+int devm_irq_of_parse_and_map(struct device *dev, struct device_node *dn,
+ int index)
+{
+ struct of_phandle_args oirq;
+
+ if (of_irq_parse_one(dn, index, &oirq))
+ return 0;
+
+ return devm_irq_create_of_mapping(dev, &oirq);
+}
+EXPORT_SYMBOL_GPL(devm_irq_of_parse_and_map);
+
+/**
* of_irq_find_parent - Given a device node, find its interrupt parent node
* @child: pointer to device node
*
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c983ed1..44e6261 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -176,6 +176,7 @@ extern void irq_domain_associate_many(struct irq_domain *domain,
extern unsigned int irq_create_mapping(struct irq_domain *host,
irq_hw_number_t hwirq);
extern void irq_dispose_mapping(unsigned int virq);
+extern void devm_irq_dispose_mapping(struct device *dev, unsigned int virq);
/**
* irq_linear_revmap() - Find a linux irq from a hw irq number.
@@ -220,6 +221,8 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
#else /* CONFIG_IRQ_DOMAIN */
static inline void irq_dispose_mapping(unsigned int virq) { }
+static inline void devm_irq_dispose_mapping(struct device *dev,
+ unsigned int virq) { }
#endif /* !CONFIG_IRQ_DOMAIN */
#endif /* _LINUX_IRQDOMAIN_H */
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 6404253..4ac7138 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -35,6 +35,8 @@ extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
extern int of_irq_parse_one(struct device_node *device, int index,
struct of_phandle_args *out_irq);
extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
+extern int devm_irq_create_of_mapping(struct device *dev,
+ struct of_phandle_args *irq_data);
extern int of_irq_to_resource(struct device_node *dev, int index,
struct resource *r);
extern int of_irq_to_resource_table(struct device_node *dev,
@@ -63,6 +65,9 @@ static inline int of_irq_get(struct device_node *dev, int index)
* so declare it here regardless of the CONFIG_OF_IRQ setting.
*/
extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
+extern int devm_irq_of_parse_and_map(struct device *dev,
+ struct device_node *node,
+ int index);
extern struct device_node *of_irq_find_parent(struct device_node *child);
#else /* !CONFIG_OF */
@@ -72,6 +77,13 @@ static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
return 0;
}
+static inline int devm_irq_of_parse_and_map(struct device *dev,
+ struct device_node *node,
+ int index)
+{
+ return 0;
+}
+
static inline void *of_irq_find_parent(struct device_node *child)
{
return NULL;
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index f140337..c8705de 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/fs.h>
+#include <linux/device.h>
static LIST_HEAD(irq_domain_list);
static DEFINE_MUTEX(irq_domain_mutex);
@@ -502,6 +503,34 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+static void devm_release_irq_mapping(void *p)
+{
+ unsigned int virq = (unsigned int)((unsigned long)p);
+
+ if (virq)
+ irq_dispose_mapping(virq);
+}
+
+int devm_irq_create_of_mapping(struct device *dev,
+ struct of_phandle_args *irq_data)
+{
+ unsigned int virq;
+ int ret;
+
+ virq = irq_create_of_mapping(irq_data);
+ if (virq) {
+ ret = devm_add_action(dev, devm_release_irq_mapping,
+ (void *)((unsigned long)virq));
+ if (ret) {
+ irq_dispose_mapping(virq);
+ return ret;
+ }
+ }
+
+ return virq;
+}
+EXPORT_SYMBOL_GPL(devm_irq_create_of_mapping);
+
/**
* irq_dispose_mapping() - Unmap an interrupt
* @virq: linux irq number of the interrupt to unmap
@@ -524,6 +553,24 @@ void irq_dispose_mapping(unsigned int virq)
EXPORT_SYMBOL_GPL(irq_dispose_mapping);
/**
+ * devm_irq_dispose_mapping() - Unmap an interrupt
+ * @dev: device irq was used for
+ * @virq: linux irq number of the interrupt to unmap
+ *
+ * This should be used instead of irq_dispose_mapping() if mapping was created
+ * with devm_irq_create_of_mapping()
+ */
+void devm_irq_dispose_mapping(struct device *dev, unsigned int virq)
+{
+ if (virq) {
+ devm_remove_action(dev, devm_release_irq_mapping,
+ (void *)((unsigned long)virq));
+ irq_dispose_mapping(virq);
+ }
+}
+EXPORT_SYMBOL_GPL(devm_irq_dispose_mapping);
+
+/**
* irq_find_mapping() - Find a linux irq from an hw irq number.
* @domain: domain owning this hardware interrupt
* @hwirq: hardware irq number in that domain space
--
1.7.10.4
next prev parent reply other threads:[~2014-06-04 11:13 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-04 11:13 [PATCH 00/21] add and use devm_irq_of_parse_and_map() nyushchenko
2014-06-04 11:13 ` nyushchenko [this message]
[not found] ` <1401880402-30091-2-git-send-email-nyushchenko-jFhMxQ4mL6a2X5qOxWx28w@public.gmane.org>
2014-06-04 13:39 ` [PATCH 01/21] irq: add devres version of OF IRQ mapping routines Thomas Gleixner
2014-06-04 11:13 ` [PATCH 02/21] ata: use devm_irq_of_parse_and_map() where appropriate nyushchenko
2014-06-04 11:13 ` [PATCH 03/21] exynos5440-cpufreq: use devm_irq_of_parse_and_map() nyushchenko
2014-06-04 11:13 ` [PATCH 04/21] omap-sham: " nyushchenko
2014-06-04 11:13 ` [PATCH 05/21] dma: use devm_irq_of_parse_and_map() where appropriate nyushchenko
2014-06-04 11:13 ` [PATCH 06/21] mpc85xx_edac: use devm_irq_of_parse_and_map() nyushchenko
2014-06-04 11:13 ` [PATCH 07/21] gpio: use devm_irq_of_parse_and_map() where appropriate nyushchenko
2014-06-04 11:13 ` [PATCH 08/21] i2c: " nyushchenko
2014-06-04 11:13 ` [PATCH 09/21] apbps2: use devm_irq_of_parse_and_map() nyushchenko
2014-06-04 11:13 ` [PATCH 10/21] media: use devm_irq_of_parse_and_map() where appropriate nyushchenko
2014-06-04 11:13 ` [PATCH 12/21] mpc5121_nfc: use devm_irq_of_parse_and_map() nyushchenko
2014-06-04 11:13 ` [PATCH 13/21] net/can: use devm_irq_of_parse_and_map() where appropriate nyushchenko
2014-06-04 11:13 ` [PATCH 16/21] bq24190_charger: use devm_irq_of_parse_and_map() nyushchenko
2014-06-04 11:13 ` [PATCH 17/21] rtc-mpc5121: " nyushchenko
2014-06-04 11:13 ` [PATCH 18/21] spi: use devm_irq_of_parse_and_map() where appropriate nyushchenko
2014-06-04 11:13 ` [PATCH 19/21] exynos_tmu: use devm_irq_of_parse_and_map() nyushchenko
[not found] ` <1401880402-30091-1-git-send-email-nyushchenko-jFhMxQ4mL6a2X5qOxWx28w@public.gmane.org>
2014-06-04 11:13 ` [PATCH 11/21] mfd: use devm_irq_of_parse_and_map() where appropriate nyushchenko-jFhMxQ4mL6a2X5qOxWx28w
2014-06-17 15:12 ` Lee Jones
2014-06-17 15:36 ` Nikita Yushchenko
2014-06-18 8:48 ` Lee Jones
2014-06-18 11:31 ` Nikita Yushchenko
2014-06-18 12:20 ` Lee Jones
2014-06-04 11:13 ` [PATCH 14/21] net/ethernet: " nyushchenko-jFhMxQ4mL6a2X5qOxWx28w
2014-06-04 11:13 ` [PATCH 15/21] pinctrl: " nyushchenko-jFhMxQ4mL6a2X5qOxWx28w
2014-06-04 11:13 ` [PATCH 20/21] usb: " nyushchenko-jFhMxQ4mL6a2X5qOxWx28w
[not found] ` <1401880402-30091-21-git-send-email-nyushchenko-jFhMxQ4mL6a2X5qOxWx28w@public.gmane.org>
2014-06-16 9:35 ` Andreas Larsson
[not found] ` <539EBA6F.7060008-FkzTOoA/JUlBDgjK7y7TUQ@public.gmane.org>
2014-06-16 9:44 ` Nikita Yushchenko
[not found] ` <539EBC8E.6060602-jFhMxQ4mL6a2X5qOxWx28w@public.gmane.org>
2014-06-16 9:54 ` Andreas Larsson
2014-06-04 11:13 ` [PATCH 21/21] at91sam9_wdt: use devm_irq_of_parse_and_map() nyushchenko
2014-06-12 10:03 ` [PATCH 00/21] add and " Andreas Larsson
[not found] ` <5399AE1B.1080301@gaisler.com>
2014-06-12 19:02 ` Nikita Yushchenko
2014-06-16 8:23 ` Andreas Larsson
[not found] ` <539EA986.1090501-FkzTOoA/JUlBDgjK7y7TUQ@public.gmane.org>
2014-06-16 8:36 ` Nikita Yushchenko
2014-06-16 9:29 ` Andreas Larsson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1401880402-30091-2-git-send-email-nyushchenko@dev.rtsoft.ru \
--to=nyushchenko@dev.rtsoft.ru \
--cc=benh@kernel.crashing.org \
--cc=devicetree@vger.kernel.org \
--cc=grant.likely@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lugovskoy@dev.rtsoft.ru \
--cc=robh+dt@kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).