public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Ed Blake <ed.blake@sondrel.com>
To: tglx@linutronix.de, jason@lakedaemon.net, marc.zyngier@arm.com
Cc: linux-kernel@vger.kernel.org, Ed Blake <ed.blake@sondrel.com>
Subject: [PATCH 1/4] irqchip: imgpdc: Avoid unbalanced irq wake disable
Date: Mon,  2 Oct 2017 10:55:56 +0100	[thread overview]
Message-ID: <1506938159-466-2-git-send-email-ed.blake@sondrel.com> (raw)
In-Reply-To: <1506938159-466-1-git-send-email-ed.blake@sondrel.com>

To avoid 'unbalanced irq wake disable' kernel warnings, only pass on
wake disables to the parent irq controller if the previous wake enable
succeeded.

Some platforms utilise the wake capability of the parent irq
controller, so we must attempt to pass on wake enables to the parent.
But in other platforms the wake capability of the PDC is used, when
the parent isn't required to support wake and we need to avoid
unbalanced wake disables in this case.

Signed-off-by: Ed Blake <ed.blake@sondrel.com>
---
 drivers/irqchip/irq-imgpdc.c | 62 ++++++++++++++++++++++++++++++++------------
 1 file changed, 46 insertions(+), 16 deletions(-)

diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c
index c02d29c..2ac3210 100644
--- a/drivers/irqchip/irq-imgpdc.c
+++ b/drivers/irqchip/irq-imgpdc.c
@@ -63,21 +63,25 @@
 
 /**
  * struct pdc_intc_priv - private pdc interrupt data.
- * @nr_perips:		Number of peripheral interrupt signals.
- * @nr_syswakes:	Number of syswake signals.
- * @perip_irqs:		List of peripheral IRQ numbers handled.
- * @syswake_irq:	Shared PDC syswake IRQ number.
- * @domain:		IRQ domain for PDC peripheral and syswake IRQs.
- * @pdc_base:		Base of PDC registers.
- * @irq_route:		Cached version of PDC_IRQ_ROUTE register.
- * @lock:		Lock to protect the PDC syswake registers and the cached
- *			values of those registers in this struct.
+ * @nr_perips:			Number of peripheral interrupt signals.
+ * @nr_syswakes:		Number of syswake signals.
+ * @perip_irqs:			List of peripheral IRQ numbers handled.
+ * @perip_irq_wake_depths:	List of peripheral IRQs wake depths.
+ * @syswake_irq:		Shared PDC syswake IRQ number.
+ * @syswake_irq_wake_depth:	Shared PDC syswake IRQ wake depth.
+ * @domain:			IRQ domain for PDC peripheral and syswake IRQs.
+ * @pdc_base:			Base of PDC registers.
+ * @irq_route:			Cached version of PDC_IRQ_ROUTE register.
+ * @lock:			Lock to protect the PDC syswake regs and the
+ *				cached values of those regs in this struct.
  */
 struct pdc_intc_priv {
 	unsigned int		nr_perips;
 	unsigned int		nr_syswakes;
 	unsigned int		*perip_irqs;
+	unsigned int		*perip_irq_wake_depths;
 	unsigned int		syswake_irq;
+	unsigned int		syswake_irq_wake_depth;
 	struct irq_domain	*domain;
 	void __iomem		*pdc_base;
 
@@ -199,6 +203,17 @@ static int pdc_irq_set_wake(struct irq_data *data, unsigned int on)
 	irq_hw_number_t hw = data->hwirq;
 	unsigned int mask = (1 << 16) << hw;
 	unsigned int dst_irq;
+	unsigned int *dst_irq_wake_depth;
+	int ret;
+
+	/* control the destination IRQ wakeup too for standby mode */
+	if (hwirq_is_syswake(hw)) {
+		dst_irq = priv->syswake_irq;
+		dst_irq_wake_depth = &priv->syswake_irq_wake_depth;
+	} else {
+		dst_irq = priv->perip_irqs[hw];
+		dst_irq_wake_depth = &priv->perip_irq_wake_depths[hw];
+	}
 
 	raw_spin_lock(&priv->lock);
 	if (on)
@@ -206,14 +221,22 @@ static int pdc_irq_set_wake(struct irq_data *data, unsigned int on)
 	else
 		priv->irq_route &= ~mask;
 	pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route);
-	raw_spin_unlock(&priv->lock);
 
-	/* control the destination IRQ wakeup too for standby mode */
-	if (hwirq_is_syswake(hw))
-		dst_irq = priv->syswake_irq;
-	else
-		dst_irq = priv->perip_irqs[hw];
-	irq_set_irq_wake(dst_irq, on);
+	/*
+	 * Pass on the set_wake request to the parent interrupt controller.
+	 * The parent isn't required to support wake, but we must balance
+	 * successful irq_set_irq_wake calls.
+	 */
+	if (on || *dst_irq_wake_depth) {
+		ret = irq_set_irq_wake(dst_irq, on);
+		if (!ret) {
+			if (on)
+				(*dst_irq_wake_depth)++;
+			else
+				(*dst_irq_wake_depth)--;
+		}
+	}
+	raw_spin_unlock(&priv->lock);
 
 	return 0;
 }
@@ -359,6 +382,13 @@ static int pdc_intc_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "cannot allocate perip IRQ list\n");
 		return -ENOMEM;
 	}
+	priv->perip_irq_wake_depths = devm_kzalloc(&pdev->dev,
+						   4 * priv->nr_perips,
+						   GFP_KERNEL);
+	if (!priv->perip_irq_wake_depths) {
+		dev_err(&pdev->dev, "cannot allocate perip IRQ wake depth list\n");
+		return -ENOMEM;
+	}
 	for (i = 0; i < priv->nr_perips; ++i) {
 		irq = platform_get_irq(pdev, 1 + i);
 		if (irq < 0) {
-- 
1.9.1

  reply	other threads:[~2017-10-02  9:56 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-02  9:55 [PATCH 0/4] irqchip: imgpdc: Fix various issues Ed Blake
2017-10-02  9:55 ` Ed Blake [this message]
2017-10-02  9:55 ` [PATCH 2/4] irqchip: imgpdc: Avoid immediate wake event during set_wake Ed Blake
2017-10-02  9:55 ` [PATCH 3/4] irqchip: imgpdc: Set sys wake polarities to active high Ed Blake
2017-10-04 13:14   ` James Hogan
2017-10-05 14:37     ` Ed Blake
2017-10-02  9:55 ` [PATCH 4/4] irqchip: imgpdc: Pass on peripheral mask/unmasks to the parent Ed Blake
2017-10-04 14:03   ` James Hogan
2017-10-05 14:48     ` Ed Blake
2017-10-05 15:26       ` James Hogan
2017-10-05 15:43         ` Ed Blake
2017-10-05 16:42           ` Ed Blake
2017-10-03 20:32 ` [PATCH 0/4] irqchip: imgpdc: Fix various issues Thomas Gleixner

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=1506938159-466-2-git-send-email-ed.blake@sondrel.com \
    --to=ed.blake@sondrel.com \
    --cc=jason@lakedaemon.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --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