linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/4] net: ipa: IPA interrupt cleanup
@ 2021-07-27 19:46 Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 1/4] net: ipa: make IPA interrupt handler threaded only Alex Elder
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Alex Elder @ 2021-07-27 19:46 UTC (permalink / raw)
  To: davem, kuba
  Cc: bjorn.andersson, evgreen, cpratapa, subashab, elder, netdev,
	linux-kernel

The first patch in this series makes all IPA interrupt handling be
done in a threaded context.  The remaining ones refactor some code
to simplify that threaded handler function.

					-Alex

Alex Elder (4):
  net: ipa: make IPA interrupt handler threaded only
  net: ipa: clear disabled IPA interrupt conditions
  net: ipa: get rid of some unneeded IPA interrupt code
  net: ipa: kill ipa_interrupt_process_all()

 drivers/net/ipa/ipa_interrupt.c | 57 +++++++++++----------------------
 1 file changed, 19 insertions(+), 38 deletions(-)

-- 
2.27.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next 1/4] net: ipa: make IPA interrupt handler threaded only
  2021-07-27 19:46 [PATCH net-next 0/4] net: ipa: IPA interrupt cleanup Alex Elder
@ 2021-07-27 19:46 ` Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 2/4] net: ipa: clear disabled IPA interrupt conditions Alex Elder
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2021-07-27 19:46 UTC (permalink / raw)
  To: davem, kuba
  Cc: bjorn.andersson, evgreen, cpratapa, subashab, elder, netdev,
	linux-kernel

When the IPA interrupt handler runs, the IPA core clock must already
be operational, and the interconnect providing access by the AP to
IPA config space must be enabled too.

Currently we ensure this by taking a top-level "stay awake" IPA
clock reference, but that will soon go away.  In preparation for
that, move all handling for the IPA IRQ into the thread function.

Signed-off-by: Alex Elder <elder@linaro.org>
---
 drivers/net/ipa/ipa_interrupt.c | 29 +++++++++++------------------
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index 9fd158dd90473..7dee4ebaf5a95 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -100,32 +100,22 @@ static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt)
 	}
 }
 
-/* Threaded part of the IPA IRQ handler */
+/* IPA IRQ handler is threaded */
 static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
-{
-	struct ipa_interrupt *interrupt = dev_id;
-
-	ipa_clock_get(interrupt->ipa);
-
-	ipa_interrupt_process_all(interrupt);
-
-	ipa_clock_put(interrupt->ipa);
-
-	return IRQ_HANDLED;
-}
-
-/* Hard part (i.e., "real" IRQ handler) of the IRQ handler */
-static irqreturn_t ipa_isr(int irq, void *dev_id)
 {
 	struct ipa_interrupt *interrupt = dev_id;
 	struct ipa *ipa = interrupt->ipa;
 	u32 offset;
 	u32 mask;
 
+	ipa_clock_get(ipa);
+
 	offset = ipa_reg_irq_stts_offset(ipa->version);
 	mask = ioread32(ipa->reg_virt + offset);
-	if (mask & interrupt->enabled)
-		return IRQ_WAKE_THREAD;
+	if (mask & interrupt->enabled) {
+		ipa_interrupt_process_all(interrupt);
+		goto out_clock_put;
+	}
 
 	/* Nothing in the mask was supposed to cause an interrupt */
 	offset = ipa_reg_irq_clr_offset(ipa->version);
@@ -134,6 +124,9 @@ static irqreturn_t ipa_isr(int irq, void *dev_id)
 	dev_err(&ipa->pdev->dev, "%s: unexpected interrupt, mask 0x%08x\n",
 		__func__, mask);
 
+out_clock_put:
+	ipa_clock_put(ipa);
+
 	return IRQ_HANDLED;
 }
 
@@ -260,7 +253,7 @@ struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa)
 	offset = ipa_reg_irq_en_offset(ipa->version);
 	iowrite32(0, ipa->reg_virt + offset);
 
-	ret = request_threaded_irq(irq, ipa_isr, ipa_isr_thread, IRQF_ONESHOT,
+	ret = request_threaded_irq(irq, NULL, ipa_isr_thread, IRQF_ONESHOT,
 				   "ipa", interrupt);
 	if (ret) {
 		dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret);
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 2/4] net: ipa: clear disabled IPA interrupt conditions
  2021-07-27 19:46 [PATCH net-next 0/4] net: ipa: IPA interrupt cleanup Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 1/4] net: ipa: make IPA interrupt handler threaded only Alex Elder
@ 2021-07-27 19:46 ` Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 3/4] net: ipa: get rid of some unneeded IPA interrupt code Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 4/4] net: ipa: kill ipa_interrupt_process_all() Alex Elder
  3 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2021-07-27 19:46 UTC (permalink / raw)
  To: davem, kuba
  Cc: bjorn.andersson, evgreen, cpratapa, subashab, elder, netdev,
	linux-kernel

We ignore any IPA interrupt that has no handler.  If any interrupt
conditions without a handler exist when an IPA interrupt occurs,
clear those conditions.  Add a debug message to report which ones
are being cleared.

Signed-off-by: Alex Elder <elder@linaro.org>
---
 drivers/net/ipa/ipa_interrupt.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index 7dee4ebaf5a95..c12d0c33557cd 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -79,6 +79,7 @@ static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt)
 {
 	struct ipa *ipa = interrupt->ipa;
 	u32 enabled = interrupt->enabled;
+	u32 pending;
 	u32 offset;
 	u32 mask;
 
@@ -87,8 +88,8 @@ static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt)
 	 * only the enabled ones.
 	 */
 	offset = ipa_reg_irq_stts_offset(ipa->version);
-	mask = ioread32(ipa->reg_virt + offset);
-	while ((mask &= enabled)) {
+	pending = ioread32(ipa->reg_virt + offset);
+	while ((mask = pending & enabled)) {
 		do {
 			u32 irq_id = __ffs(mask);
 
@@ -96,7 +97,17 @@ static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt)
 
 			ipa_interrupt_process(interrupt, irq_id);
 		} while (mask);
-		mask = ioread32(ipa->reg_virt + offset);
+		pending = ioread32(ipa->reg_virt + offset);
+	}
+
+	/* If any disabled interrupts are pending, clear them */
+	if (pending) {
+		struct device *dev = &ipa->pdev->dev;
+
+		dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n",
+			pending);
+		offset = ipa_reg_irq_clr_offset(ipa->version);
+		iowrite32(pending, ipa->reg_virt + offset);
 	}
 }
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 3/4] net: ipa: get rid of some unneeded IPA interrupt code
  2021-07-27 19:46 [PATCH net-next 0/4] net: ipa: IPA interrupt cleanup Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 1/4] net: ipa: make IPA interrupt handler threaded only Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 2/4] net: ipa: clear disabled IPA interrupt conditions Alex Elder
@ 2021-07-27 19:46 ` Alex Elder
  2021-07-27 19:46 ` [PATCH net-next 4/4] net: ipa: kill ipa_interrupt_process_all() Alex Elder
  3 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2021-07-27 19:46 UTC (permalink / raw)
  To: davem, kuba
  Cc: bjorn.andersson, evgreen, cpratapa, subashab, elder, netdev,
	linux-kernel

The pending IPA interrupts are checked by ipa_isr_thread(), and
interrupts are processed only if an enabled interrupt has a
condition pending.  But ipa_interrupt_process_all() now makes the
same check, so the one in ipa_isr_thread() can just be skipped.

Also in ipa_isr_thread(), any interrupt conditions pending which are
not enabled are cleared.  Here too, ipa_interrupt_process_all() now
clears such excess interrupt conditions, so ipa_isr_thread() doesn't
have to.

Signed-off-by: Alex Elder <elder@linaro.org>
---
 drivers/net/ipa/ipa_interrupt.c | 17 +----------------
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index c12d0c33557cd..d149e496ffa72 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -116,26 +116,11 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
 {
 	struct ipa_interrupt *interrupt = dev_id;
 	struct ipa *ipa = interrupt->ipa;
-	u32 offset;
-	u32 mask;
 
 	ipa_clock_get(ipa);
 
-	offset = ipa_reg_irq_stts_offset(ipa->version);
-	mask = ioread32(ipa->reg_virt + offset);
-	if (mask & interrupt->enabled) {
-		ipa_interrupt_process_all(interrupt);
-		goto out_clock_put;
-	}
+	ipa_interrupt_process_all(interrupt);
 
-	/* Nothing in the mask was supposed to cause an interrupt */
-	offset = ipa_reg_irq_clr_offset(ipa->version);
-	iowrite32(mask, ipa->reg_virt + offset);
-
-	dev_err(&ipa->pdev->dev, "%s: unexpected interrupt, mask 0x%08x\n",
-		__func__, mask);
-
-out_clock_put:
 	ipa_clock_put(ipa);
 
 	return IRQ_HANDLED;
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 4/4] net: ipa: kill ipa_interrupt_process_all()
  2021-07-27 19:46 [PATCH net-next 0/4] net: ipa: IPA interrupt cleanup Alex Elder
                   ` (2 preceding siblings ...)
  2021-07-27 19:46 ` [PATCH net-next 3/4] net: ipa: get rid of some unneeded IPA interrupt code Alex Elder
@ 2021-07-27 19:46 ` Alex Elder
  3 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2021-07-27 19:46 UTC (permalink / raw)
  To: davem, kuba
  Cc: bjorn.andersson, evgreen, cpratapa, subashab, elder, netdev,
	linux-kernel

Now that ipa_isr_thread() is a simple wrapper that gets a clock
reference around ipa_interrupt_process_all(), get rid of the
called function and just open-code it in ipa_isr_thread().

Signed-off-by: Alex Elder <elder@linaro.org>
---
 drivers/net/ipa/ipa_interrupt.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c
index d149e496ffa72..aa37f03f4557f 100644
--- a/drivers/net/ipa/ipa_interrupt.c
+++ b/drivers/net/ipa/ipa_interrupt.c
@@ -74,15 +74,18 @@ static void ipa_interrupt_process(struct ipa_interrupt *interrupt, u32 irq_id)
 		iowrite32(mask, ipa->reg_virt + offset);
 }
 
-/* Process all IPA interrupt types that have been signaled */
-static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt)
+/* IPA IRQ handler is threaded */
+static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
 {
+	struct ipa_interrupt *interrupt = dev_id;
 	struct ipa *ipa = interrupt->ipa;
 	u32 enabled = interrupt->enabled;
 	u32 pending;
 	u32 offset;
 	u32 mask;
 
+	ipa_clock_get(ipa);
+
 	/* The status register indicates which conditions are present,
 	 * including conditions whose interrupt is not enabled.  Handle
 	 * only the enabled ones.
@@ -109,17 +112,6 @@ static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt)
 		offset = ipa_reg_irq_clr_offset(ipa->version);
 		iowrite32(pending, ipa->reg_virt + offset);
 	}
-}
-
-/* IPA IRQ handler is threaded */
-static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
-{
-	struct ipa_interrupt *interrupt = dev_id;
-	struct ipa *ipa = interrupt->ipa;
-
-	ipa_clock_get(ipa);
-
-	ipa_interrupt_process_all(interrupt);
 
 	ipa_clock_put(ipa);
 
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-07-27 19:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-27 19:46 [PATCH net-next 0/4] net: ipa: IPA interrupt cleanup Alex Elder
2021-07-27 19:46 ` [PATCH net-next 1/4] net: ipa: make IPA interrupt handler threaded only Alex Elder
2021-07-27 19:46 ` [PATCH net-next 2/4] net: ipa: clear disabled IPA interrupt conditions Alex Elder
2021-07-27 19:46 ` [PATCH net-next 3/4] net: ipa: get rid of some unneeded IPA interrupt code Alex Elder
2021-07-27 19:46 ` [PATCH net-next 4/4] net: ipa: kill ipa_interrupt_process_all() Alex Elder

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).