On Thu, Dec 31, 2015 at 03:36:47AM +0530, Aniroop Mathur wrote: > 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. > This in turn saves space of partial events in evdev handler buffer > and reduces evdev client reading requests. Let's add a few people who write consumer code to see if this is something that they consider useful. > > Signed-off-by: Aniroop Mathur <a.mathur@xxxxxxxxxxx> > --- > drivers/input/evdev.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 45 insertions(+), 4 deletions(-) > > diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c > index e9ae3d5..e7b612e 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 whether partial events need to be dropped */ > unsigned long *evmasks[EV_CNT]; > unsigned int bufsize; > struct input_event buffer[]; > @@ -192,6 +193,7 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) > { > unsigned long flags; > unsigned int clk_type; > + struct input_event *ev; > > switch (clkid) { > > @@ -218,6 +220,17 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) > spin_lock_irqsave(&client->buffer_lock, flags); > > if (client->head != client->tail) { > + > + /* > + * Set drop_pevent to true if last event packet is > + * not stored completely in buffer. > + */ > + client->head--; > + client->head &= client->bufsize - 1; > + ev = &client->buffer[client->head]; > + if (!(ev->type == EV_SYN && ev->code == SYN_REPORT)) > + client->drop_pevent = true; > + > client->packet_head = client->head = client->tail; > __evdev_queue_syn_dropped(client); > } > @@ -228,31 +241,51 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) > return 0; > } > > -static void __pass_event(struct evdev_client *client, > +static bool __pass_event(struct evdev_client *client, > const struct input_event *event) > { > + struct input_event *prev_ev; > + > client->buffer[client->head++] = *event; > 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. > + * This effectively "drops" all unconsumed events, storing > + * EV_SYN/SYN_DROPPED and the newest event in the queue but > + * only if it is not part of partial packet. > + * Set drop_pevent to true if last event packet is not stored > + * completely in buffer and set to false if SYN_REPORT occurs. > */ > + > client->tail = (client->head - 2) & (client->bufsize - 1); > > + prev_ev = &client->buffer[client->tail]; > + if (!(prev_ev->type == EV_SYN && prev_ev->code == SYN_REPORT)) { > + client->drop_pevent = true; > + client->head--; > + client->head &= 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->drop_pevent = false; > + return true; > + } > } > > if (event->type == EV_SYN && event->code == SYN_REPORT) { > client->packet_head = client->head; > kill_fasync(&client->fasync, SIGIO, POLL_IN); > } > + > + return false; > } > > static void evdev_pass_values(struct evdev_client *client, > @@ -284,10 +317,18 @@ static void evdev_pass_values(struct evdev_client *client, > wakeup = true; > } > > + /* drop partial events until SYN_REPORT occurs */ > + if (client->drop_pevent) { > + if (v->type == EV_SYN && v->code == SYN_REPORT) > + client->drop_pevent = false; > + continue; > + } > + > event.type = v->type; > event.code = v->code; > event.value = v->value; > - __pass_event(client, &event); > + if (__pass_event(client, &event)) > + wakeup = false; > } > > spin_unlock(&client->buffer_lock); > -- > 2.6.2 > -- Dmitry -- To unsubscribe from this list: send the line "unsubscribe linux-input" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html