diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-05 18:56:28 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-05 22:29:02 -0500 |
commit | b881d53770e68f3f9b6097a61dd1685180393f20 (patch) | |
tree | 4a4a05083e2cb58ab45c33e3632e0eabd832b54d /drivers/input | |
parent | 6c8afa88adce613c23f27e719f805cc2a6441b07 (diff) |
Input: evdev - do not queue SYN_DROPPED if queue is empty
There is no point in queueing EV_SYN/SYN_DROPPED on clock type change when
there are no events in the client's queue and doing so confuses tests in
libinput package, so let's not do that.
Reported-and-tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/evdev.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e7cee3880b75..a18f41b89b6a 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -108,10 +108,8 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) | |||
108 | client->head = head; | 108 | client->head = head; |
109 | } | 109 | } |
110 | 110 | ||
111 | /* queue SYN_DROPPED event and flush queue if flush parameter is true */ | 111 | static void __evdev_queue_syn_dropped(struct evdev_client *client) |
112 | static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) | ||
113 | { | 112 | { |
114 | unsigned long flags; | ||
115 | struct input_event ev; | 113 | struct input_event ev; |
116 | ktime_t time; | 114 | ktime_t time; |
117 | 115 | ||
@@ -126,11 +124,6 @@ static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) | |||
126 | ev.code = SYN_DROPPED; | 124 | ev.code = SYN_DROPPED; |
127 | ev.value = 0; | 125 | ev.value = 0; |
128 | 126 | ||
129 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
130 | |||
131 | if (flush) | ||
132 | client->packet_head = client->head = client->tail; | ||
133 | |||
134 | client->buffer[client->head++] = ev; | 127 | client->buffer[client->head++] = ev; |
135 | client->head &= client->bufsize - 1; | 128 | client->head &= client->bufsize - 1; |
136 | 129 | ||
@@ -139,12 +132,21 @@ static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) | |||
139 | client->tail = (client->head - 1) & (client->bufsize - 1); | 132 | client->tail = (client->head - 1) & (client->bufsize - 1); |
140 | client->packet_head = client->tail; | 133 | client->packet_head = client->tail; |
141 | } | 134 | } |
135 | } | ||
136 | |||
137 | static void evdev_queue_syn_dropped(struct evdev_client *client) | ||
138 | { | ||
139 | unsigned long flags; | ||
142 | 140 | ||
141 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
142 | __evdev_queue_syn_dropped(client); | ||
143 | spin_unlock_irqrestore(&client->buffer_lock, flags); | 143 | spin_unlock_irqrestore(&client->buffer_lock, flags); |
144 | } | 144 | } |
145 | 145 | ||
146 | static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) | 146 | static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) |
147 | { | 147 | { |
148 | unsigned long flags; | ||
149 | |||
148 | if (client->clk_type == clkid) | 150 | if (client->clk_type == clkid) |
149 | return 0; | 151 | return 0; |
150 | 152 | ||
@@ -163,8 +165,18 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) | |||
163 | return -EINVAL; | 165 | return -EINVAL; |
164 | } | 166 | } |
165 | 167 | ||
166 | /* Flush pending events and queue SYN_DROPPED event.*/ | 168 | /* |
167 | evdev_queue_syn_dropped(client, true); | 169 | * Flush pending events and queue SYN_DROPPED event, |
170 | * but only if the queue is not empty. | ||
171 | */ | ||
172 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
173 | |||
174 | if (client->head != client->tail) { | ||
175 | client->packet_head = client->head = client->tail; | ||
176 | __evdev_queue_syn_dropped(client); | ||
177 | } | ||
178 | |||
179 | spin_unlock_irqrestore(&client->buffer_lock, flags); | ||
168 | 180 | ||
169 | return 0; | 181 | return 0; |
170 | } | 182 | } |
@@ -803,7 +815,7 @@ static int evdev_handle_get_val(struct evdev_client *client, | |||
803 | 815 | ||
804 | ret = bits_to_user(mem, maxbit, maxlen, p, compat); | 816 | ret = bits_to_user(mem, maxbit, maxlen, p, compat); |
805 | if (ret < 0) | 817 | if (ret < 0) |
806 | evdev_queue_syn_dropped(client, false); | 818 | evdev_queue_syn_dropped(client); |
807 | 819 | ||
808 | kfree(mem); | 820 | kfree(mem); |
809 | 821 | ||