diff mbox series

[3/3] irqchip/loongson-pch-pic: Reserve legacy LPC irqs

Message ID 1599624552-17523-3-git-send-email-chenhc@lemote.com
State New
Headers show
Series [1/3] MIPS: Loongson64: Increase NR_IRQS to 320 | expand

Commit Message

Huacai Chen Sept. 9, 2020, 4:09 a.m. UTC
Reserve legacy LPC irqs (0~15) to avoid spurious interrupts.

Cc: stable@vger.kernel.org
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
 drivers/irqchip/irq-loongson-pch-pic.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

Comments

Marc Zyngier Sept. 11, 2020, 7:50 a.m. UTC | #1
On 2020-09-11 05:13, Huacai Chen wrote:
> Hi, Marc,
> 
> On Thu, Sep 10, 2020 at 6:08 PM Marc Zyngier <maz@kernel.org> wrote:
>> 
>> On 2020-09-09 05:09, Huacai Chen wrote:
>> > Reserve legacy LPC irqs (0~15) to avoid spurious interrupts.
>> 
>> How can they be spurious? Why are they enabled the first place?
>> 
>> This looks like you are papering over a much bigger issue.
> The spurious interrupts are probably occurred after kdump and the irq
> number is in legacy LPC ranges. I think this is because the old kernel
> doesn't (and it can't) disable devices properly so there are stale
> interrupts in the kdump case.

I don't really understand why the old kernel can't turn the interrupts
off. Most architectures are able t, why not yours?

Finally, why don't you just shut these interrupts off the first place
in the interrupt controller init? Adding a whole lot of kernel
data structures as a band-aid doesn't strike me as the best possible
idea. Not to mention that if they keep firing, all you are doing
is adding extra overhead.

         M.
diff mbox series

Patch

diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c
index 9bf6b9a..9f6719c 100644
--- a/drivers/irqchip/irq-loongson-pch-pic.c
+++ b/drivers/irqchip/irq-loongson-pch-pic.c
@@ -35,6 +35,7 @@ 
 
 struct pch_pic {
 	void __iomem		*base;
+	struct irq_domain	*lpc_domain;
 	struct irq_domain	*pic_domain;
 	u32			ht_vec_base;
 	raw_spinlock_t		pic_lock;
@@ -184,9 +185,9 @@  static void pch_pic_reset(struct pch_pic *priv)
 static int pch_pic_of_init(struct device_node *node,
 				struct device_node *parent)
 {
+	int i, base, err;
 	struct pch_pic *priv;
 	struct irq_domain *parent_domain;
-	int err;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -213,6 +214,22 @@  static int pch_pic_of_init(struct device_node *node,
 		goto iounmap_base;
 	}
 
+	base = irq_alloc_descs(-1, 0, NR_IRQS_LEGACY, 0);
+	if (base < 0) {
+		pr_err("Failed to allocate LPC IRQ numbers\n");
+		goto iounmap_base;
+	}
+
+	priv->lpc_domain = irq_domain_add_legacy(node, NR_IRQS_LEGACY, 0, 0,
+						 &irq_domain_simple_ops, NULL);
+	if (!priv->lpc_domain) {
+		pr_err("Failed to add irqdomain for LPC controller");
+		goto iounmap_base;
+	}
+
+	for (i = 0; i < NR_IRQS_LEGACY; i++)
+		irq_set_chip_and_handler(i, &dummy_irq_chip, handle_simple_irq);
+
 	priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
 						       PIC_COUNT,
 						       of_node_to_fwnode(node),