From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934334AbcAML6r (ORCPT ); Wed, 13 Jan 2016 06:58:47 -0500 Received: from mailout1.samsung.com ([203.254.224.24]:33286 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933914AbcAML6p (ORCPT ); Wed, 13 Jan 2016 06:58:45 -0500 X-AuditID: cbfee61b-f793c6d00000236c-86-56963bf26599 From: Aniroop Mathur To: dmitry.torokhov@gmail.com Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, aniroop.mathur@gmail.com, s.samuel@samsung.com, r.mahale@samsung.com, Aniroop Mathur Subject: [PATCH] [v5]Input: evdev: fix bug of dropping full valid packet after syn_dropped Date: Wed, 13 Jan 2016 17:27:41 +0530 Message-id: <1452686262-6684-1-git-send-email-a.mathur@samsung.com> X-Mailer: git-send-email 1.7.9.5 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrEJMWRmVeSWpSXmKPExsVy+t9jQd3P1tPCDH42MVtc/HGOxeLn7hks FocXvWC0uPnpG6vF5V1z2CxOvWtgsti89yqLA7vHzll32T36tqxi9Pi8SS6AOYrLJiU1J7Ms tUjfLoErY9PMf0wF6yQrNn+ewtLAeEqki5GTQ0LAROLH81nMELaYxIV769m6GLk4hARmMUqs WXWBBcL5ySjx+sAVoCoODjYBbYn3n9lAGkQEZCU6joM0c3EwC6xjlJj45SAbSI2wQIxE62Vj EJNFQFXi6MVokHJeAWeJyw/XgVVICChIzJlkM4GRewEjwypGidSC5ILipPRco7zUcr3ixNzi 0rx0veT83E2M4JB4Jr2D8fAu90OMAhyMSjy8HbOmhgmxJpYVV+YeYpTgYFYS4T1vOC1MiDcl sbIqtSg/vqg0J7X4EKM0B4uSOO++S5FhQgLpiSWp2ampBalFMFkmDk6pBkaNHf+/z5r/RYSt zVVfTXLp3ZKfAafm22Zsj7lZY57Gy2xsHRZvcm9O2fMLiRGW7MYiu82yYlcpxtzduWhV/7cZ x4yKLj7sOqQVH2QpXHHPYaeg/RKHG24nlAqiw4/UbX+zn0O6V63wxY5PfeeNdzlrPb6irC6z q2nBPfkur8rNxR84k1rZlJVYijMSDbWYi4oTAearDI4FAgAA Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If last event in old queue that was dropped was EV_SYN/SYN_REPORT, then lets generate EV_SYN/SYN_REPORT immediately after queing EV_SYN/SYN_DROPPED so that clients would not ignore next valid full packet events. Signed-off-by: Aniroop Mathur --- drivers/input/evdev.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e9ae3d5..0bc7b98 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -156,7 +156,12 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type) static void __evdev_queue_syn_dropped(struct evdev_client *client) { struct input_event ev; + struct input_event *prev_ev; ktime_t time; + unsigned int mask = client->bufsize - 1; + + /* store previous event */ + prev_ev = &client->buffer[(client->head - 1) & mask]; time = client->clk_type == EV_CLK_REAL ? ktime_get_real() : @@ -170,13 +175,28 @@ static void __evdev_queue_syn_dropped(struct evdev_client *client) ev.value = 0; client->buffer[client->head++] = ev; - client->head &= client->bufsize - 1; + client->head &= mask; if (unlikely(client->head == client->tail)) { /* drop queue but keep our SYN_DROPPED event */ - client->tail = (client->head - 1) & (client->bufsize - 1); + client->tail = (client->head - 1) & mask; client->packet_head = client->tail; } + + /* + * If last packet was completely stored, then queue SYN_REPORT + * so that clients would not ignore next valid full packet + */ + if (prev_ev->type == EV_SYN && prev_ev->code == SYN_REPORT) { + prev_ev->time = ev.time; + client->buffer[client->head++] = *prev_ev; + client->head &= mask; + client->packet_head = client->head; + + /* drop queue but keep our SYN_DROPPED & SYN_REPORT event */ + if (unlikely(client->head == client->tail)) + client->tail = (client->head - 2) & mask; + } } static void evdev_queue_syn_dropped(struct evdev_client *client) @@ -235,18 +255,19 @@ static void __pass_event(struct evdev_client *client, client->head &= client->bufsize - 1; if (unlikely(client->head == client->tail)) { + client->packet_head = client->tail; + __evdev_queue_syn_dropped(client); + /* - * This effectively "drops" all unconsumed events, leaving - * EV_SYN/SYN_DROPPED plus the newest event in the queue. + * Store newest event in the queue, + * but if it is SYN_REPORT then it is already stored by + * __evdev_queue_syn_dropped, so should not be stored again. + * As buffer overrun just occurred so no need to check here. */ - client->tail = (client->head - 2) & (client->bufsize - 1); - - client->buffer[client->tail].time = event->time; - client->buffer[client->tail].type = EV_SYN; - client->buffer[client->tail].code = SYN_DROPPED; - client->buffer[client->tail].value = 0; - - client->packet_head = client->tail; + if (event->type != EV_SYN && event->code != SYN_REPORT) { + client->buffer[client->head++] = *event; + client->head &= client->bufsize - 1; + } } if (event->type == EV_SYN && event->code == SYN_REPORT) { -- 1.7.9.5