blob: 82fabeec3c48f0f98eab7107eddd2a53e39d0b14 [file] [log] [blame]
Joel Stanley2b0f7b42016-07-19 23:26:28 +09301From e51e878aac1ea5018c7accac28afa4db8c620489 Mon Sep 17 00:00:00 2001
2From: Samuel Mendoza-Jonas <sam@mendozajonas.com>
3Date: Wed, 13 Jul 2016 11:15:41 +1000
4Subject: [PATCH 09/10] tty/hvc: Use IRQF_SHARED for OPAL hvc consoles
5
6Commit 2def86a7200c
7("hvc: Convert to using interrupts instead of opal events")
8enabled the use of interrupts in the hvc_driver for OPAL platforms.
9However on machines with more than one hvc console, any console after
10the first will fail to register an interrupt handler in
11notifier_add_irq() since all consoles share the same IRQ number but do
12not set the IRQF_SHARED flag:
13
14[ 51.179907] genirq: Flags mismatch irq 31. 00000000 (hvc_console) vs.
1500000000 (hvc_console)
16[ 51.180010] hvc_open: request_irq failed with rc -16.
17
18This error propagates up to hvc_open() and the console is closed, but
19OPAL will still generate interrupts that are not handled, leading to
20rcu_sched stall warnings.
21
22Set IRQF_SHARED when calling request_irq, allowing additional consoles
23to start properly. This is only set for consoles handled by
24hvc_opal_probe(), leaving other types unaffected.
25
26Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
27Cc: <stable@vger.kernel.org> # 4.1.x-
28Signed-off-by: Joel Stanley <joel@jms.id.au>
29---
30 drivers/tty/hvc/hvc_console.h | 1 +
31 drivers/tty/hvc/hvc_irq.c | 7 +++++--
32 drivers/tty/hvc/hvc_opal.c | 3 +++
33 3 files changed, 9 insertions(+), 2 deletions(-)
34
35diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h
36index 913101980827..798c48d0d32c 100644
37--- a/drivers/tty/hvc/hvc_console.h
38+++ b/drivers/tty/hvc/hvc_console.h
39@@ -60,6 +60,7 @@ struct hvc_struct {
40 struct winsize ws;
41 struct work_struct tty_resize;
42 struct list_head next;
43+ unsigned long flags;
44 };
45
46 /* implemented by a low level driver */
47diff --git a/drivers/tty/hvc/hvc_irq.c b/drivers/tty/hvc/hvc_irq.c
48index c9adb0559f61..57d9df7ee1c9 100644
49--- a/drivers/tty/hvc/hvc_irq.c
50+++ b/drivers/tty/hvc/hvc_irq.c
51@@ -14,6 +14,9 @@ static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
52 /* if hvc_poll request a repoll, then kick the hvcd thread */
53 if (hvc_poll(dev_instance))
54 hvc_kick();
55+ /* We're safe to always return IRQ_HANDLED as the hvcd thread will
56+ * iterate through each hvc_struct
57+ */
58 return IRQ_HANDLED;
59 }
60
61@@ -28,8 +31,8 @@ int notifier_add_irq(struct hvc_struct *hp, int irq)
62 hp->irq_requested = 0;
63 return 0;
64 }
65- rc = request_irq(irq, hvc_handle_interrupt, 0,
66- "hvc_console", hp);
67+ rc = request_irq(irq, hvc_handle_interrupt, hp->flags,
68+ "hvc_console", hp);
69 if (!rc)
70 hp->irq_requested = 1;
71 return rc;
72diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
73index 276b796b24e4..510799311099 100644
74--- a/drivers/tty/hvc/hvc_opal.c
75+++ b/drivers/tty/hvc/hvc_opal.c
76@@ -230,6 +230,9 @@ static int hvc_opal_probe(struct platform_device *dev)
77 hp = hvc_alloc(termno, irq, ops, MAX_VIO_PUT_CHARS);
78 if (IS_ERR(hp))
79 return PTR_ERR(hp);
80+
81+ /* hvc consoles on powernv may need to share a single irq */
82+ hp->flags = IRQF_SHARED;
83 dev_set_drvdata(&dev->dev, hp);
84
85 return 0;
86--
872.8.1
88