From patchwork Mon Jan 4 21:56:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aniroop Mathur X-Patchwork-Id: 7951441 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 5A8DD9F1C0 for ; Mon, 4 Jan 2016 21:55:08 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5C9D620320 for ; Mon, 4 Jan 2016 21:55:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1CC932034A for ; Mon, 4 Jan 2016 21:55:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751938AbcADVzE (ORCPT ); Mon, 4 Jan 2016 16:55:04 -0500 Received: from mail-pf0-f178.google.com ([209.85.192.178]:36793 "EHLO mail-pf0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751862AbcADVzD (ORCPT ); Mon, 4 Jan 2016 16:55:03 -0500 Received: by mail-pf0-f178.google.com with SMTP id 65so163308802pff.3; Mon, 04 Jan 2016 13:55:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id; bh=L/WdhWGiIDMFSVPf+3mHQfwCyoZHjxScYjLPwfrRnU8=; b=k7QVORMUjVUsCVpUpa4sZCPgAKUwlI6aSGEWlCUkFFTaER1vZuH7SIV8JhzKEtEl5N AG9YzaeXM/Rbc5YwZpVnTfvouruWdAuWpxeJWAwVby6Vj8owqW2ead1AE2zGDGs9MSF+ AqMXaPWICwixPqq4DJiA1tPaf0pJRaQKCb2y39B7dH/9midU0GMy2TQniOIL6YVJJSzs fW1Sh4Mdk6SJBsSiWKVEw2QqGSzJF06U0aFrVNSay7+EWIS3XXpHENXPq+14sy6YM1V6 XfKYNM+XAqwutJ8cqy7ypqWZySXRhCQwJHskEtE6HIgx6WMF4GXNj4PGD1sHyV9CqybT BC5g== X-Received: by 10.98.72.75 with SMTP id v72mr60845419pfa.106.1451944503243; Mon, 04 Jan 2016 13:55:03 -0800 (PST) Received: from Aniroops-MacBook-Pro.local.name ([203.122.1.49]) by smtp.gmail.com with ESMTPSA id e66sm123135745pfb.35.2016.01.04.13.54.59 (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 04 Jan 2016 13:55:02 -0800 (PST) From: Aniroop Mathur To: dmitry.torokhov@gmail.com, benjamin.tissoires@gmail.com, peter.hutterer@who-t.net Cc: dh.herrmann@gmail.com, rydberg@bitmath.org, aniroop.mathur@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Aniroop Mathur Subject: [PATCH] [v4]Input: evdev - drop partial events after emptying the buffer Date: Tue, 5 Jan 2016 03:26:41 +0530 Message-Id: <1451944601-1376-1-git-send-email-a.mathur@samsung.com> X-Mailer: git-send-email 2.6.2 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch introduces concept to drop partial events in evdev handler itself after emptying the buffer which are dropped by all evdev clients in userspace after SYN_DROPPED occurs and this in turn reduces evdev client reading requests plus saves memory space filled by partial events in evdev handler buffer. Also, this patch prevents dropping of full packet by evdev client after SYN_DROPPED occurs in case last stored event was SYN_REPORT. (like after clock change request) --- Please ignore v3. Signed-off-by: Aniroop Mathur --- drivers/input/evdev.c | 53 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index e9ae3d5..15b6eb2 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -58,6 +58,7 @@ struct evdev_client { struct list_head node; unsigned int clk_type; bool revoked; + bool drop_pevent; /* specifies if partial events need to be dropped */ unsigned long *evmasks[EV_CNT]; unsigned int bufsize; struct input_event buffer[]; @@ -156,7 +157,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 +176,33 @@ 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 is NOT fully stored, set drop_pevent to true to + * ignore partial events and if last packet is fully stored, queue + * SYN_REPORT so that clients would not ignore next full packet. + */ + if (prev_ev->type != EV_SYN && prev_ev->code != SYN_REPORT) { + client->drop_pevent = true; + } else 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; + client->packet_head = client->tail; + } + } } static void evdev_queue_syn_dropped(struct evdev_client *client) @@ -235,18 +261,8 @@ static void __pass_event(struct evdev_client *client, client->head &= client->bufsize - 1; if (unlikely(client->head == client->tail)) { - /* - * This effectively "drops" all unconsumed events, leaving - * EV_SYN/SYN_DROPPED plus the newest event in the queue. - */ - 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; + __evdev_queue_syn_dropped(client); } if (event->type == EV_SYN && event->code == SYN_REPORT) { @@ -284,6 +300,17 @@ static void evdev_pass_values(struct evdev_client *client, wakeup = true; } + /* + * drop partial events of last packet but queue SYN_REPORT + * so that clients would not ignore extra full packet. + */ + if (client->drop_pevent) { + if (v->type == EV_SYN && v->code == SYN_REPORT) + client->drop_pevent = false; + else + continue; + } + event.type = v->type; event.code = v->code; event.value = v->value;