linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] irq: Add untracked irq handler
@ 2016-06-17 22:00 Keith Busch
  2016-06-17 22:00 ` [PATCH 2/2] vmd: use " Keith Busch
  2016-06-18  8:07 ` [tip:irq/core] genirq: Add " tip-bot for Keith Busch
  0 siblings, 2 replies; 5+ messages in thread
From: Keith Busch @ 2016-06-17 22:00 UTC (permalink / raw)
  To: LKML, Thomas Gleixner, linux-pci; +Cc: Bjorn Helgaas, Jon Derrick, Keith Busch

This adds a software irq handler for controllers that multiplex
interrupts from multiple devices, but don't know which device generated
the interrupt. For these devices, the irq handler that demuxes must
check every action for every software irq using the same h/w irq in order
to find out which device generated the interrupt. This will inevitably
trigger spurious interrupt detection if we are noting the irq.

The new irq handler does not track the handling for spurious interrupt
detection. An irq that uses this also won't get stats tracked since it
didn't generate the interrupt, nor added to randomness since they are
not random.

Signed-off-by: Keith Busch <keith.busch@intel.com>
---
 include/linux/irq.h    |  1 +
 kernel/irq/chip.c      | 43 +++++++++++++++++++++++++++++++++++++++++++
 kernel/irq/handle.c    | 18 ++++++++++++++----
 kernel/irq/internals.h |  1 +
 4 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 4d758a7..cd7b94e 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -482,6 +482,7 @@ extern void handle_fasteoi_irq(struct irq_desc *desc);
 extern void handle_edge_irq(struct irq_desc *desc);
 extern void handle_edge_eoi_irq(struct irq_desc *desc);
 extern void handle_simple_irq(struct irq_desc *desc);
+extern void handle_untracked_irq(struct irq_desc *desc);
 extern void handle_percpu_irq(struct irq_desc *desc);
 extern void handle_percpu_devid_irq(struct irq_desc *desc);
 extern void handle_bad_irq(struct irq_desc *desc);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 2f9f2b0..584e5e8 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -426,6 +426,49 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(handle_simple_irq);
 
+/**
+ *	handle_untracked_irq - Simple and software-decoded IRQs.
+ *	@desc:	the interrupt description structure for this irq
+ *
+ *	Untracked interrupts are sent from a demultiplexing interrupt
+ *	handler when the demultiplexer does not know which device it its
+ *	multiplexed irq domain generated the interrupt. IRQ's handled
+ *	through here are not subjected to stats tracking, randomness, or
+ *	spurious interrupt detection.
+ *
+ *	Note: Like handle_simple_irq, the caller is expected to handle
+ *	the ack, clear, mask and unmask issues if necessary.
+ */
+void handle_untracked_irq(struct irq_desc *desc)
+{
+	unsigned int flags = 0;
+
+	raw_spin_lock(&desc->lock);
+
+	if (!irq_may_run(desc))
+		goto out_unlock;
+
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+
+	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
+		desc->istate |= IRQS_PENDING;
+		goto out_unlock;
+	}
+
+	desc->istate &= ~IRQS_PENDING;
+	irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+	raw_spin_unlock(&desc->lock);
+
+	__handle_irq_event_percpu(desc, &flags);
+
+	raw_spin_lock(&desc->lock);
+	irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+
+out_unlock:
+	raw_spin_unlock(&desc->lock);
+}
+EXPORT_SYMBOL_GPL(handle_untracked_irq);
+
 /*
  * Called unconditionally from handle_level_irq() and only for oneshot
  * interrupts from handle_fasteoi_irq()
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a15b548..d3f2490 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -132,10 +132,10 @@ void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
 	wake_up_process(action->thread);
 }
 
-irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags)
 {
 	irqreturn_t retval = IRQ_NONE;
-	unsigned int flags = 0, irq = desc->irq_data.irq;
+	unsigned int irq = desc->irq_data.irq;
 	struct irqaction *action;
 
 	for_each_action_of_desc(desc, action) {
@@ -164,7 +164,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
-			flags |= action->flags;
+			*flags |= action->flags;
 			break;
 
 		default:
@@ -174,7 +174,17 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
 		retval |= res;
 	}
 
-	add_interrupt_randomness(irq, flags);
+	return retval;
+}
+
+irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+{
+	irqreturn_t retval;
+	unsigned int flags = 0;
+
+	retval = __handle_irq_event_percpu(desc, &flags);
+
+	add_interrupt_randomness(desc->irq_data.irq, flags);
 
 	if (!noirqdebug)
 		note_interrupt(desc, retval);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 09be2c9..d788150 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -83,6 +83,7 @@ extern void irq_mark_irq(unsigned int irq);
 
 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
 
+irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags);
 irqreturn_t handle_irq_event_percpu(struct irq_desc *desc);
 irqreturn_t handle_irq_event(struct irq_desc *desc);
 
-- 
2.7.2

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

* [PATCH 2/2] vmd: use untracked irq handler
  2016-06-17 22:00 [PATCH 1/2] irq: Add untracked irq handler Keith Busch
@ 2016-06-17 22:00 ` Keith Busch
  2016-06-17 23:00   ` Bjorn Helgaas
  2016-06-18  8:07   ` [tip:irq/core] x86/PCI/VMD: Use " tip-bot for Keith Busch
  2016-06-18  8:07 ` [tip:irq/core] genirq: Add " tip-bot for Keith Busch
  1 sibling, 2 replies; 5+ messages in thread
From: Keith Busch @ 2016-06-17 22:00 UTC (permalink / raw)
  To: LKML, Thomas Gleixner, linux-pci; +Cc: Bjorn Helgaas, Jon Derrick, Keith Busch

There is no way to know which device in a VMD tiggered an interrupt
without invoking every registered driver's actions. This uses the
untracked irq handler so that a less used device does not trigger
spurious interrupt.

We have been previously recommending users enable "noirqdebug", but do
not want to force a system setting just to keep this domain functional.

Signed-off-by: Keith Busch <keith.busch@intel.com>
---
 arch/x86/pci/vmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
index 7792aba..613cac7 100644
--- a/arch/x86/pci/vmd.c
+++ b/arch/x86/pci/vmd.c
@@ -195,7 +195,7 @@ static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
 	vmdirq->virq = virq;
 
 	irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip,
-			    vmdirq, handle_simple_irq, vmd, NULL);
+			    vmdirq, handle_untracked_irq, vmd, NULL);
 	return 0;
 }
 
-- 
2.7.2

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

* Re: [PATCH 2/2] vmd: use untracked irq handler
  2016-06-17 22:00 ` [PATCH 2/2] vmd: use " Keith Busch
@ 2016-06-17 23:00   ` Bjorn Helgaas
  2016-06-18  8:07   ` [tip:irq/core] x86/PCI/VMD: Use " tip-bot for Keith Busch
  1 sibling, 0 replies; 5+ messages in thread
From: Bjorn Helgaas @ 2016-06-17 23:00 UTC (permalink / raw)
  To: Keith Busch; +Cc: LKML, Thomas Gleixner, linux-pci, Bjorn Helgaas, Jon Derrick

On Fri, Jun 17, 2016 at 04:00:21PM -0600, Keith Busch wrote:
> There is no way to know which device in a VMD tiggered an interrupt

s/tiggered/triggered/

> without invoking every registered driver's actions. This uses the
> untracked irq handler so that a less used device does not trigger
> spurious interrupt.
> 
> We have been previously recommending users enable "noirqdebug", but do
> not want to force a system setting just to keep this domain functional.

I applaud that goal.

> Signed-off-by: Keith Busch <keith.busch@intel.com>

Since this depends on the previous patch and I'm not qualified to review
that one, I'll ack this and somebody else can merge both or none:

Acked-by: Bjorn Helgaas <bhelgaas@google.com>

> ---
>  arch/x86/pci/vmd.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
> index 7792aba..613cac7 100644
> --- a/arch/x86/pci/vmd.c
> +++ b/arch/x86/pci/vmd.c
> @@ -195,7 +195,7 @@ static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
>  	vmdirq->virq = virq;
>  
>  	irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip,
> -			    vmdirq, handle_simple_irq, vmd, NULL);
> +			    vmdirq, handle_untracked_irq, vmd, NULL);
>  	return 0;
>  }
>  
> -- 
> 2.7.2
> 

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

* [tip:irq/core] genirq: Add untracked irq handler
  2016-06-17 22:00 [PATCH 1/2] irq: Add untracked irq handler Keith Busch
  2016-06-17 22:00 ` [PATCH 2/2] vmd: use " Keith Busch
@ 2016-06-18  8:07 ` tip-bot for Keith Busch
  1 sibling, 0 replies; 5+ messages in thread
From: tip-bot for Keith Busch @ 2016-06-18  8:07 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, keith.busch, mingo, jonathan.derrick, linux-kernel, bhelgaas, hpa

Commit-ID:  edd14cfebc4404698544d407ecf8eda6e19aa19e
Gitweb:     http://git.kernel.org/tip/edd14cfebc4404698544d407ecf8eda6e19aa19e
Author:     Keith Busch <keith.busch@intel.com>
AuthorDate: Fri, 17 Jun 2016 16:00:20 -0600
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Sat, 18 Jun 2016 10:00:55 +0200

genirq: Add untracked irq handler

This adds a software irq handler for controllers that multiplex
interrupts from multiple devices, but don't know which device generated
the interrupt. For these devices, the irq handler that demuxes must
check every action for every software irq using the same h/w irq in order
to find out which device generated the interrupt. This will inevitably
trigger spurious interrupt detection if we are noting the irq.

The new irq handler does not track the handling for spurious interrupt
detection. An irq that uses this also won't get stats tracked since it
didn't generate the interrupt, nor added to randomness since they are
not random.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org
Cc: Jon Derrick <jonathan.derrick@intel.com>
Link: http://lkml.kernel.org/r/1466200821-29159-1-git-send-email-keith.busch@intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/irq.h    |  1 +
 kernel/irq/chip.c      | 43 +++++++++++++++++++++++++++++++++++++++++++
 kernel/irq/handle.c    | 18 ++++++++++++++----
 kernel/irq/internals.h |  1 +
 4 files changed, 59 insertions(+), 4 deletions(-)

diff --git a/include/linux/irq.h b/include/linux/irq.h
index 6c92a84..562cef0 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -484,6 +484,7 @@ extern void handle_fasteoi_irq(struct irq_desc *desc);
 extern void handle_edge_irq(struct irq_desc *desc);
 extern void handle_edge_eoi_irq(struct irq_desc *desc);
 extern void handle_simple_irq(struct irq_desc *desc);
+extern void handle_untracked_irq(struct irq_desc *desc);
 extern void handle_percpu_irq(struct irq_desc *desc);
 extern void handle_percpu_devid_irq(struct irq_desc *desc);
 extern void handle_bad_irq(struct irq_desc *desc);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index ad81314..b4c1bc7 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -426,6 +426,49 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(handle_simple_irq);
 
+/**
+ *	handle_untracked_irq - Simple and software-decoded IRQs.
+ *	@desc:	the interrupt description structure for this irq
+ *
+ *	Untracked interrupts are sent from a demultiplexing interrupt
+ *	handler when the demultiplexer does not know which device it its
+ *	multiplexed irq domain generated the interrupt. IRQ's handled
+ *	through here are not subjected to stats tracking, randomness, or
+ *	spurious interrupt detection.
+ *
+ *	Note: Like handle_simple_irq, the caller is expected to handle
+ *	the ack, clear, mask and unmask issues if necessary.
+ */
+void handle_untracked_irq(struct irq_desc *desc)
+{
+	unsigned int flags = 0;
+
+	raw_spin_lock(&desc->lock);
+
+	if (!irq_may_run(desc))
+		goto out_unlock;
+
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+
+	if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
+		desc->istate |= IRQS_PENDING;
+		goto out_unlock;
+	}
+
+	desc->istate &= ~IRQS_PENDING;
+	irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+	raw_spin_unlock(&desc->lock);
+
+	__handle_irq_event_percpu(desc, &flags);
+
+	raw_spin_lock(&desc->lock);
+	irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+
+out_unlock:
+	raw_spin_unlock(&desc->lock);
+}
+EXPORT_SYMBOL_GPL(handle_untracked_irq);
+
 /*
  * Called unconditionally from handle_level_irq() and only for oneshot
  * interrupts from handle_fasteoi_irq()
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index a15b548..d3f2490 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -132,10 +132,10 @@ void __irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
 	wake_up_process(action->thread);
 }
 
-irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags)
 {
 	irqreturn_t retval = IRQ_NONE;
-	unsigned int flags = 0, irq = desc->irq_data.irq;
+	unsigned int irq = desc->irq_data.irq;
 	struct irqaction *action;
 
 	for_each_action_of_desc(desc, action) {
@@ -164,7 +164,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
-			flags |= action->flags;
+			*flags |= action->flags;
 			break;
 
 		default:
@@ -174,7 +174,17 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
 		retval |= res;
 	}
 
-	add_interrupt_randomness(irq, flags);
+	return retval;
+}
+
+irqreturn_t handle_irq_event_percpu(struct irq_desc *desc)
+{
+	irqreturn_t retval;
+	unsigned int flags = 0;
+
+	retval = __handle_irq_event_percpu(desc, &flags);
+
+	add_interrupt_randomness(desc->irq_data.irq, flags);
 
 	if (!noirqdebug)
 		note_interrupt(desc, retval);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index d5edcdc..0c6f35b 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -84,6 +84,7 @@ extern void irq_mark_irq(unsigned int irq);
 
 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
 
+irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags);
 irqreturn_t handle_irq_event_percpu(struct irq_desc *desc);
 irqreturn_t handle_irq_event(struct irq_desc *desc);
 

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

* [tip:irq/core] x86/PCI/VMD: Use untracked irq handler
  2016-06-17 22:00 ` [PATCH 2/2] vmd: use " Keith Busch
  2016-06-17 23:00   ` Bjorn Helgaas
@ 2016-06-18  8:07   ` tip-bot for Keith Busch
  1 sibling, 0 replies; 5+ messages in thread
From: tip-bot for Keith Busch @ 2016-06-18  8:07 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: bhelgaas, jonathan.derrick, keith.busch, tglx, linux-kernel, mingo, hpa

Commit-ID:  30ce0350381351646ef86b64e6d3840b3869833b
Gitweb:     http://git.kernel.org/tip/30ce0350381351646ef86b64e6d3840b3869833b
Author:     Keith Busch <keith.busch@intel.com>
AuthorDate: Fri, 17 Jun 2016 16:00:21 -0600
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Sat, 18 Jun 2016 10:00:55 +0200

x86/PCI/VMD: Use untracked irq handler

There is no way to know which device in a VMD triggered an interrupt
without invoking every registered driver's actions. This uses the
untracked irq handler so that a less used device does not trigger
spurious interrupt.

We have been previously recommending users to enable "noirqdebug", but do
not want to force a system setting just to keep this domain functional.

Signed-off-by: Keith Busch <keith.busch@intel.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org
Cc: Jon Derrick <jonathan.derrick@intel.com>
Link: http://lkml.kernel.org/r/1466200821-29159-2-git-send-email-keith.busch@intel.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 arch/x86/pci/vmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/pci/vmd.c b/arch/x86/pci/vmd.c
index 7792aba..613cac7 100644
--- a/arch/x86/pci/vmd.c
+++ b/arch/x86/pci/vmd.c
@@ -195,7 +195,7 @@ static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
 	vmdirq->virq = virq;
 
 	irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip,
-			    vmdirq, handle_simple_irq, vmd, NULL);
+			    vmdirq, handle_untracked_irq, vmd, NULL);
 	return 0;
 }
 

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

end of thread, other threads:[~2016-06-18  8:07 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-17 22:00 [PATCH 1/2] irq: Add untracked irq handler Keith Busch
2016-06-17 22:00 ` [PATCH 2/2] vmd: use " Keith Busch
2016-06-17 23:00   ` Bjorn Helgaas
2016-06-18  8:07   ` [tip:irq/core] x86/PCI/VMD: Use " tip-bot for Keith Busch
2016-06-18  8:07 ` [tip:irq/core] genirq: Add " tip-bot for Keith Busch

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