]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.7.3/input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.7.3 / input-i8042-break-load-dependency-between-atkbd-psmouse-and-i8042.patch
1 From 4097461897df91041382ff6fcd2bfa7ee6b2448c Mon Sep 17 00:00:00 2001
2 From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
3 Date: Mon, 25 Jul 2016 11:36:54 -0700
4 Subject: Input: i8042 - break load dependency between atkbd/psmouse and i8042
5
6 From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
7
8 commit 4097461897df91041382ff6fcd2bfa7ee6b2448c upstream.
9
10 As explained in 1407814240-4275-1-git-send-email-decui@microsoft.com we
11 have a hard load dependency between i8042 and atkbd which prevents
12 keyboard from working on Gen2 Hyper-V VMs.
13
14 > hyperv_keyboard invokes serio_interrupt(), which needs a valid serio
15 > driver like atkbd.c. atkbd.c depends on libps2.c because it invokes
16 > ps2_command(). libps2.c depends on i8042.c because it invokes
17 > i8042_check_port_owner(). As a result, hyperv_keyboard actually
18 > depends on i8042.c.
19 >
20 > For a Generation 2 Hyper-V VM (meaning no i8042 device emulated), if a
21 > Linux VM (like Arch Linux) happens to configure CONFIG_SERIO_I8042=m
22 > rather than =y, atkbd.ko can't load because i8042.ko can't load(due to
23 > no i8042 device emulated) and finally hyperv_keyboard can't work and
24 > the user can't input: https://bugs.archlinux.org/task/39820
25 > (Ubuntu/RHEL/SUSE aren't affected since they use CONFIG_SERIO_I8042=y)
26
27 To break the dependency we move away from using i8042_check_port_owner()
28 and instead allow serio port owner specify a mutex that clients should use
29 to serialize PS/2 command stream.
30
31 Reported-by: Mark Laws <mdl@60hz.org>
32 Tested-by: Mark Laws <mdl@60hz.org>
33 Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
34 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
35
36 ---
37 drivers/input/serio/i8042.c | 16 +---------------
38 drivers/input/serio/libps2.c | 10 ++++------
39 include/linux/i8042.h | 6 ------
40 include/linux/serio.h | 24 +++++++++++++++++++-----
41 4 files changed, 24 insertions(+), 32 deletions(-)
42
43 --- a/drivers/input/serio/i8042.c
44 +++ b/drivers/input/serio/i8042.c
45 @@ -1277,6 +1277,7 @@ static int __init i8042_create_kbd_port(
46 serio->start = i8042_start;
47 serio->stop = i8042_stop;
48 serio->close = i8042_port_close;
49 + serio->ps2_cmd_mutex = &i8042_mutex;
50 serio->port_data = port;
51 serio->dev.parent = &i8042_platform_device->dev;
52 strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
53 @@ -1373,21 +1374,6 @@ static void i8042_unregister_ports(void)
54 }
55 }
56
57 -/*
58 - * Checks whether port belongs to i8042 controller.
59 - */
60 -bool i8042_check_port_owner(const struct serio *port)
61 -{
62 - int i;
63 -
64 - for (i = 0; i < I8042_NUM_PORTS; i++)
65 - if (i8042_ports[i].serio == port)
66 - return true;
67 -
68 - return false;
69 -}
70 -EXPORT_SYMBOL(i8042_check_port_owner);
71 -
72 static void i8042_free_irqs(void)
73 {
74 if (i8042_aux_irq_registered)
75 --- a/drivers/input/serio/libps2.c
76 +++ b/drivers/input/serio/libps2.c
77 @@ -56,19 +56,17 @@ EXPORT_SYMBOL(ps2_sendbyte);
78
79 void ps2_begin_command(struct ps2dev *ps2dev)
80 {
81 - mutex_lock(&ps2dev->cmd_mutex);
82 + struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
83
84 - if (i8042_check_port_owner(ps2dev->serio))
85 - i8042_lock_chip();
86 + mutex_lock(m);
87 }
88 EXPORT_SYMBOL(ps2_begin_command);
89
90 void ps2_end_command(struct ps2dev *ps2dev)
91 {
92 - if (i8042_check_port_owner(ps2dev->serio))
93 - i8042_unlock_chip();
94 + struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
95
96 - mutex_unlock(&ps2dev->cmd_mutex);
97 + mutex_unlock(m);
98 }
99 EXPORT_SYMBOL(ps2_end_command);
100
101 --- a/include/linux/i8042.h
102 +++ b/include/linux/i8042.h
103 @@ -62,7 +62,6 @@ struct serio;
104 void i8042_lock_chip(void);
105 void i8042_unlock_chip(void);
106 int i8042_command(unsigned char *param, int command);
107 -bool i8042_check_port_owner(const struct serio *);
108 int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
109 struct serio *serio));
110 int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
111 @@ -83,11 +82,6 @@ static inline int i8042_command(unsigned
112 return -ENODEV;
113 }
114
115 -static inline bool i8042_check_port_owner(const struct serio *serio)
116 -{
117 - return false;
118 -}
119 -
120 static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
121 struct serio *serio))
122 {
123 --- a/include/linux/serio.h
124 +++ b/include/linux/serio.h
125 @@ -31,7 +31,8 @@ struct serio {
126
127 struct serio_device_id id;
128
129 - spinlock_t lock; /* protects critical sections from port's interrupt handler */
130 + /* Protects critical sections from port's interrupt handler */
131 + spinlock_t lock;
132
133 int (*write)(struct serio *, unsigned char);
134 int (*open)(struct serio *);
135 @@ -40,16 +41,29 @@ struct serio {
136 void (*stop)(struct serio *);
137
138 struct serio *parent;
139 - struct list_head child_node; /* Entry in parent->children list */
140 + /* Entry in parent->children list */
141 + struct list_head child_node;
142 struct list_head children;
143 - unsigned int depth; /* level of nesting in serio hierarchy */
144 + /* Level of nesting in serio hierarchy */
145 + unsigned int depth;
146
147 - struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */
148 - struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
149 + /*
150 + * serio->drv is accessed from interrupt handlers; when modifying
151 + * caller should acquire serio->drv_mutex and serio->lock.
152 + */
153 + struct serio_driver *drv;
154 + /* Protects serio->drv so attributes can pin current driver */
155 + struct mutex drv_mutex;
156
157 struct device dev;
158
159 struct list_head node;
160 +
161 + /*
162 + * For use by PS/2 layer when several ports share hardware and
163 + * may get indigestion when exposed to concurrent access (i8042).
164 + */
165 + struct mutex *ps2_cmd_mutex;
166 };
167 #define to_serio_port(d) container_of(d, struct serio, dev)
168