diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-06 02:56:28 +0300 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-02-06 06:29:02 +0300 |
commit | b881d53770e68f3f9b6097a61dd1685180393f20 (patch) | |
tree | 4a4a05083e2cb58ab45c33e3632e0eabd832b54d | |
parent | 6c8afa88adce613c23f27e719f805cc2a6441b07 (diff) | |
download | linux-b881d53770e68f3f9b6097a61dd1685180393f20.tar.xz |
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>
-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) client->head = head; } -/* queue SYN_DROPPED event and flush queue if flush parameter is true */ -static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) +static void __evdev_queue_syn_dropped(struct evdev_client *client) { - unsigned long flags; struct input_event ev; ktime_t time; @@ -126,11 +124,6 @@ static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) ev.code = SYN_DROPPED; ev.value = 0; - spin_lock_irqsave(&client->buffer_lock, flags); - - if (flush) - client->packet_head = client->head = client->tail; - client->buffer[client->head++] = ev; client->head &= client->bufsize - 1; @@ -139,12 +132,21 @@ static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) client->tail = (client->head - 1) & (client->bufsize - 1); client->packet_head = client->tail; } +} + +static void evdev_queue_syn_dropped(struct evdev_client *client) +{ + unsigned long flags; + spin_lock_irqsave(&client->buffer_lock, flags); + __evdev_queue_syn_dropped(client); spin_unlock_irqrestore(&client->buffer_lock, flags); } static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) { + unsigned long flags; + if (client->clk_type == clkid) return 0; @@ -163,8 +165,18 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) return -EINVAL; } - /* Flush pending events and queue SYN_DROPPED event.*/ - evdev_queue_syn_dropped(client, true); + /* + * Flush pending events and queue SYN_DROPPED event, + * but only if the queue is not empty. + */ + spin_lock_irqsave(&client->buffer_lock, flags); + + if (client->head != client->tail) { + client->packet_head = client->head = client->tail; + __evdev_queue_syn_dropped(client); + } + + spin_unlock_irqrestore(&client->buffer_lock, flags); return 0; } @@ -803,7 +815,7 @@ static int evdev_handle_get_val(struct evdev_client *client, ret = bits_to_user(mem, maxbit, maxlen, p, compat); if (ret < 0) - evdev_queue_syn_dropped(client, false); + evdev_queue_syn_dropped(client); kfree(mem); |