From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Date: Thu, 5 Feb 2015 23:56:28 +0000 (-0800)
Subject: Input: evdev - do not queue SYN_DROPPED if queue is empty
X-Git-Tag: firefly_0821_release~176^2~541^2~101^2~1
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=b881d53770e68f3f9b6097a61dd1685180393f20;p=firefly-linux-kernel-4.4.55.git

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>
---

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);