lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 27 Jul 2012 13:02:56 -0600
From:	Stephen Warren <swarren@...dotorg.org>
To:	Samuel Ortiz <sameo@...ux.intel.com>
Cc:	Mark Brown <broonie@...nsource.wolfsonmicro.com>,
	linux-kernel@...r.kernel.org, Stephen Warren <swarren@...dia.com>
Subject: [PATCH] mfd: arizona: convert to regmap_add_irq_chips

From: Stephen Warren <swarren@...dia.com>

The Arizona chip contains a single interrupt that represents the unified
output of multiple internal interrupt controllers. This pattern has been
factored out into regmap-irq, so convert the Arizona driver to use the
new regmap-irq code.

This introduces some hopefully minor functional changes:

1) regmap_add_irq_chips() calls regmap_add_irq_chip() with irq==0 rather
   than -1, so in turn irq_domain_add_linear() is called rather than
   irq_domain_add_legacy(). This change could be avoided by providing an
   irq_bases array to regmap_add_irq_chips().

2) regmap_add_irq_chips() requests the top-level interrupt itself, so this
   happens before the Arizona driver hooks the child BOOT_DONE and
   CTRLIF_ERR interrupts. In the original, all the IRQ chips were created
   first, and then the top-level IRQ was requested. This may cause a
   functional difference if those interrupts are pending at probe() time.

3) The top-level interrupt domain set up by regmap_add_irq_chips() does
   not have a .xlate op, whereas the removed domain in the Arizona driver
   did. However, I don't think this is an issue, since the original code
   simply used the default irq_domain_xlate_twocell, which didn't handle
   mapping the IRQ numbers to the child interrupt controllers anyway, and
   hence probably wasn't that useful. regmap-irq could easily be extended
   to provide a useful xlate function if required.

Signed-off-by: Stephen Warren <swarren@...dia.com>
---
Note, this depends on the regmap series I just posted to compile.
---
 drivers/mfd/arizona-irq.c        |  132 ++++++--------------------------------
 include/linux/mfd/arizona/core.h |    4 +-
 2 files changed, 20 insertions(+), 116 deletions(-)

diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 98ac345..f693f85 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -28,11 +28,15 @@
 
 static int arizona_map_irq(struct arizona *arizona, int irq)
 {
+	struct regmap_irq_chip_data *irq_chip;
 	int ret;
 
-	ret = regmap_irq_get_virq(arizona->aod_irq_chip, irq);
-	if (ret < 0)
-		ret = regmap_irq_get_virq(arizona->irq_chip, irq);
+	irq_chip = regmap_irq_chips_get_chip(arizona->irq_chips, 0);
+	ret = regmap_irq_get_virq(irq_chip, irq);
+	if (ret < 0) {
+		irq_chip = regmap_irq_chips_get_chip(arizona->irq_chips, 1);
+		ret = regmap_irq_get_virq(irq_chip, irq);
+	}
 
 	return ret;
 }
@@ -91,83 +95,24 @@ static irqreturn_t arizona_ctrlif_err(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t arizona_irq_thread(int irq, void *data)
-{
-	struct arizona *arizona = data;
-	int i, ret;
-
-	ret = pm_runtime_get_sync(arizona->dev);
-	if (ret < 0) {
-		dev_err(arizona->dev, "Failed to resume device: %d\n", ret);
-		return IRQ_NONE;
-	}
-
-	/* Check both domains */
-	for (i = 0; i < 2; i++)
-		handle_nested_irq(irq_find_mapping(arizona->virq, i));
-
-	pm_runtime_mark_last_busy(arizona->dev);
-	pm_runtime_put_autosuspend(arizona->dev);
-
-	return IRQ_HANDLED;
-}
-
-static void arizona_irq_enable(struct irq_data *data)
-{
-}
-
-static void arizona_irq_disable(struct irq_data *data)
-{
-}
-
-static struct irq_chip arizona_irq_chip = {
-	.name			= "arizona",
-	.irq_disable		= arizona_irq_disable,
-	.irq_enable		= arizona_irq_enable,
-};
-
-static int arizona_irq_map(struct irq_domain *h, unsigned int virq,
-			      irq_hw_number_t hw)
-{
-	struct regmap_irq_chip_data *data = h->host_data;
-
-	irq_set_chip_data(virq, data);
-	irq_set_chip_and_handler(virq, &arizona_irq_chip, handle_edge_irq);
-	irq_set_nested_thread(virq, 1);
-
-	/* ARM needs us to explicitly flag the IRQ as valid
-	 * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
-	set_irq_flags(virq, IRQF_VALID);
-#else
-	irq_set_noprobe(virq);
-#endif
-
-	return 0;
-}
-
-static struct irq_domain_ops arizona_domain_ops = {
-	.map	= arizona_irq_map,
-	.xlate	= irq_domain_xlate_twocell,
-};
-
 int arizona_irq_init(struct arizona *arizona)
 {
 	int flags = IRQF_ONESHOT;
 	int ret, i;
-	const struct regmap_irq_chip *aod, *irq;
+	struct regmap *maps[2] = { arizona->regmap, arizona->regmap };
+	const struct regmap_irq_chip *chips[2];
 
 	switch (arizona->type) {
 #ifdef CONFIG_MFD_WM5102
 	case WM5102:
-		aod = &wm5102_aod;
-		irq = &wm5102_irq;
+		chips[0] = &wm5102_aod;
+		chips[1] = &wm5102_irq;
 		break;
 #endif
 #ifdef CONFIG_MFD_WM5110
 	case WM5110:
-		aod = &wm5110_aod;
-		irq = &wm5110_irq;
+		chips[0] = &wm5110_aod;
+		chips[1] = &wm5110_irq;
 		break;
 #endif
 	default:
@@ -189,30 +134,11 @@ int arizona_irq_init(struct arizona *arizona)
 		flags |= IRQF_TRIGGER_LOW;
 	}
 
-	/* Allocate a virtual IRQ domain to distribute to the regmap domains */
-	arizona->virq = irq_domain_add_linear(NULL, 2, &arizona_domain_ops,
-					      arizona);
-	if (!arizona->virq) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	ret = regmap_add_irq_chip(arizona->regmap,
-				  irq_create_mapping(arizona->virq, 0),
-				  IRQF_ONESHOT, -1, aod,
-				  &arizona->aod_irq_chip);
+	ret = regmap_add_irq_chips(arizona->irq, flags, 2, maps, NULL, chips,
+				   &arizona->irq_chips);
 	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret);
-		goto err_domain;
-	}
-
-	ret = regmap_add_irq_chip(arizona->regmap,
-				  irq_create_mapping(arizona->virq, 1),
-				  IRQF_ONESHOT, -1, irq,
-				  &arizona->irq_chip);
-	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to add AOD IRQs: %d\n", ret);
-		goto err_aod;
+		dev_err(arizona->dev, "Failed to add IRQs: %d\n", ret);
+		goto err;
 	}
 
 	/* Make sure the boot done IRQ is unmasked for resumes */
@@ -235,28 +161,12 @@ int arizona_irq_init(struct arizona *arizona)
 		goto err_ctrlif;
 	}
 
-	ret = request_threaded_irq(arizona->irq, NULL, arizona_irq_thread,
-				   flags, "arizona", arizona);
-
-	if (ret != 0) {
-		dev_err(arizona->dev, "Failed to request IRQ %d: %d\n",
-			arizona->irq, ret);
-		goto err_main_irq;
-	}
-
 	return 0;
 
-err_main_irq:
-	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
 err_ctrlif:
 	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
 err_boot_done:
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
-			    arizona->irq_chip);
-err_aod:
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
-			    arizona->aod_irq_chip);
-err_domain:
+	regmap_del_irq_chips(arizona->irq_chips);
 err:
 	return ret;
 }
@@ -265,11 +175,7 @@ int arizona_irq_exit(struct arizona *arizona)
 {
 	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR), arizona);
 	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
-			    arizona->irq_chip);
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
-			    arizona->aod_irq_chip);
-	free_irq(arizona->irq, arizona);
+	regmap_del_irq_chips(arizona->irq_chips);
 
 	return 0;
 }
diff --git a/include/linux/mfd/arizona/core.h b/include/linux/mfd/arizona/core.h
index dd231ac..769b3a0 100644
--- a/include/linux/mfd/arizona/core.h
+++ b/include/linux/mfd/arizona/core.h
@@ -92,9 +92,7 @@ struct arizona {
 	struct arizona_pdata pdata;
 
 	int irq;
-	struct irq_domain *virq;
-	struct regmap_irq_chip_data *aod_irq_chip;
-	struct regmap_irq_chip_data *irq_chip;
+	struct regmap_irq_chips_data *irq_chips;
 
 	struct mutex clk_lock;
 	int clk32k_ref;
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ