All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tony Lindgren <tony@atomide.com>
To: Mark Brown <broonie@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org,
	Lee Jones <lee.jones@linaro.org>, Marcel Partap <mpartap@gmx.net>,
	Michael Scott <michael.scott@linaro.org>,
	Sebastian Reichel <sre@kernel.org>
Subject: [PATCH 1/4] regmap: irq: Fix lost interrupts by introducing handle_reread
Date: Thu, 16 Mar 2017 17:36:30 -0700	[thread overview]
Message-ID: <20170317003633.7361-2-tony@atomide.com> (raw)
In-Reply-To: <20170317003633.7361-1-tony@atomide.com>

At least Motorola CPCAP PMIC needs it's device interrupts re-read
until there are no more interrupts. Otherwise the PMIC interrupt to
the SoC will eventually stop toggling.

Let's allow doing that by introducing a flag for handle_reread
and by splitting regmap_irq_thread() into two separate functions
for regmap_read_irq_status() and regmap_irq_handle_pending().

Cc: Lee Jones <lee.jones@linaro.org>
Cc: Marcel Partap <mpartap@gmx.net>
Cc: Michael Scott <michael.scott@linaro.org>
Cc: Sebastian Reichel <sre@kernel.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
 drivers/base/regmap/regmap-irq.c | 77 ++++++++++++++++++++++++++++------------
 include/linux/regmap.h           |  2 ++
 2 files changed, 56 insertions(+), 23 deletions(-)

diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -259,27 +259,11 @@ static const struct irq_chip regmap_irq_chip = {
 	.irq_set_wake		= regmap_irq_set_wake,
 };
 
-static irqreturn_t regmap_irq_thread(int irq, void *d)
+static int regmap_read_irq_status(struct regmap_irq_chip_data *data)
 {
-	struct regmap_irq_chip_data *data = d;
 	const struct regmap_irq_chip *chip = data->chip;
 	struct regmap *map = data->map;
 	int ret, i;
-	bool handled = false;
-	u32 reg;
-
-	if (chip->handle_pre_irq)
-		chip->handle_pre_irq(chip->irq_drv_data);
-
-	if (chip->runtime_pm) {
-		ret = pm_runtime_get_sync(map->dev);
-		if (ret < 0) {
-			dev_err(map->dev, "IRQ thread failed to resume: %d\n",
-				ret);
-			pm_runtime_put(map->dev);
-			goto exit;
-		}
-	}
 
 	/*
 	 * Read in the statuses, using a single bulk read if possible
@@ -299,7 +283,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 		if (ret != 0) {
 			dev_err(map->dev, "Failed to read IRQ status: %d\n",
 				ret);
-			goto exit;
+			return ret;
 		}
 
 		for (i = 0; i < data->chip->num_regs; i++) {
@@ -315,7 +299,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 				break;
 			default:
 				BUG();
-				goto exit;
+				return ret;
 			}
 		}
 
@@ -330,13 +314,21 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 				dev_err(map->dev,
 					"Failed to read IRQ status: %d\n",
 					ret);
-				if (chip->runtime_pm)
-					pm_runtime_put(map->dev);
-				goto exit;
+				return ret;
 			}
 		}
 	}
 
+	return 0;
+}
+
+static int regmap_irq_handle_pending(struct regmap_irq_chip_data *data)
+{
+	const struct regmap_irq_chip *chip = data->chip;
+	struct regmap *map = data->map;
+	int ret, i, handled = 0;
+	u32 reg;
+
 	/*
 	 * Ignore masked IRQs and ack if we need to; we ack early so
 	 * there is no race between handling and acknowleding the
@@ -361,10 +353,49 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
 		if (data->status_buf[chip->irqs[i].reg_offset /
 				     map->reg_stride] & chip->irqs[i].mask) {
 			handle_nested_irq(irq_find_mapping(data->domain, i));
-			handled = true;
+			handled++;
 		}
 	}
 
+	return handled;
+}
+
+static irqreturn_t regmap_irq_thread(int irq, void *d)
+{
+	struct regmap_irq_chip_data *data = d;
+	const struct regmap_irq_chip *chip = data->chip;
+	struct regmap *map = data->map;
+	int ret, handled = 0;
+
+	if (chip->handle_pre_irq)
+		chip->handle_pre_irq(chip->irq_drv_data);
+
+	if (chip->runtime_pm) {
+		ret = pm_runtime_get_sync(map->dev);
+		if (ret < 0) {
+			dev_err(map->dev, "IRQ thread failed to resume: %d\n",
+				ret);
+			pm_runtime_put(map->dev);
+			goto exit;
+		}
+	}
+
+	do {
+		ret = regmap_read_irq_status(data);
+		if (ret)
+			goto out_runtime_put;
+
+		ret = regmap_irq_handle_pending(data);
+		if (ret < 0)
+			goto out_runtime_put;
+
+		if (!ret)
+			break;
+
+		handled += ret;
+	} while (chip->handle_reread);
+
+out_runtime_put:
 	if (chip->runtime_pm)
 		pm_runtime_put(map->dev);
 
diff --git a/include/linux/regmap.h b/include/linux/regmap.h
--- a/include/linux/regmap.h
+++ b/include/linux/regmap.h
@@ -897,6 +897,7 @@ struct regmap_irq {
  * @ack_invert:  Inverted ack register: cleared bits for ack.
  * @wake_invert: Inverted wake register: cleared bits are wake enabled.
  * @type_invert: Invert the type flags.
+ * @handle_reread: Read interrupt status until no more interrupts are seen.
  * @runtime_pm:  Hold a runtime PM lock on the device when accessing it.
  *
  * @num_regs:    Number of registers in each control bank.
@@ -934,6 +935,7 @@ struct regmap_irq_chip {
 	bool wake_invert:1;
 	bool runtime_pm:1;
 	bool type_invert:1;
+	bool handle_reread:1;
 
 	int num_regs;
 
-- 
2.11.1

  reply	other threads:[~2017-03-17  0:37 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-17  0:36 [PATCH 0/4] Regmap IRQ fix and related changes CPCAP Tony Lindgren
2017-03-17  0:36 ` Tony Lindgren [this message]
2017-03-20 15:14   ` [PATCH 1/4] regmap: irq: Fix lost interrupts by introducing handle_reread Charles Keepax
2017-03-20 15:14     ` Charles Keepax
2017-03-20 15:33     ` Tony Lindgren
2017-03-21  9:23       ` Charles Keepax
2017-03-21  9:23         ` Charles Keepax
2017-03-21 15:41         ` Tony Lindgren
2017-03-21 16:43           ` Charles Keepax
2017-03-21 16:43             ` Charles Keepax
2017-03-17  0:36 ` [PATCH 2/4] mfd: cpcap: Use handle_reread flag for interrupts Tony Lindgren
2017-03-17  0:36 ` [PATCH 3/4] mfd: cpcap: Use ack_invert interrupts Tony Lindgren
2017-03-17  0:36 ` [PATCH 4/4] mfd: cpcap: Fix bad use of IRQ sense register Tony Lindgren
2017-03-19  2:01   ` Sebastian Reichel
2017-03-19 16:07     ` Tony Lindgren
2017-03-20 10:47   ` Lee Jones
2017-03-22  2:22 ` [PATCH 0/4] Regmap IRQ fix and related changes CPCAP Sebastian Reichel
2017-03-22 17:10 [PATCHv2 " Tony Lindgren
2017-03-22 17:10 ` [PATCH 1/4] regmap: irq: Fix lost interrupts by introducing handle_reread Tony Lindgren
2017-03-27 17:49   ` Mark Brown
2017-03-28  0:36     ` Tony Lindgren
2017-03-28 15:18       ` Mark Brown
2017-03-28 15:47         ` Tony Lindgren
2017-03-28 16:49           ` Mark Brown
2017-03-28 17:10             ` Tony Lindgren
2017-04-04  3:03               ` Tony Lindgren
2017-04-04 12:19                 ` Mark Brown
2017-04-04 13:56                   ` Tony Lindgren
2017-04-04 15:28                     ` Mark Brown
2017-04-03 11:27   ` Lee Jones

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=20170317003633.7361-2-tony@atomide.com \
    --to=tony@atomide.com \
    --cc=broonie@kernel.org \
    --cc=lee.jones@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=michael.scott@linaro.org \
    --cc=mpartap@gmx.net \
    --cc=sre@kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.