lkml.org 
[lkml]   [2012]   [Sep]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 06/20] Input: evdev - Add the events() callback
    Date
    By sending a full frame of events at the same time, the irqsoff
    latency at heavy load is brought down from 200 us to 100 us.

    Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
    ---
    drivers/input/evdev.c | 68 +++++++++++++++++++++++++++++++++++----------------
    1 file changed, 47 insertions(+), 21 deletions(-)

    diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
    index a0692c5..118d030 100644
    --- a/drivers/input/evdev.c
    +++ b/drivers/input/evdev.c
    @@ -54,16 +54,9 @@ struct evdev_client {
    static struct evdev *evdev_table[EVDEV_MINORS];
    static DEFINE_MUTEX(evdev_table_mutex);

    -static void evdev_pass_event(struct evdev_client *client,
    - struct input_event *event,
    - ktime_t mono, ktime_t real)
    +static void __pass_event(struct evdev_client *client,
    + const struct input_event *event)
    {
    - event->time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
    - mono : real);
    -
    - /* Interrupts are disabled, just acquire the lock. */
    - spin_lock(&client->buffer_lock);
    -
    client->buffer[client->head++] = *event;
    client->head &= client->bufsize - 1;

    @@ -86,42 +79,74 @@ static void evdev_pass_event(struct evdev_client *client,
    client->packet_head = client->head;
    kill_fasync(&client->fasync, SIGIO, POLL_IN);
    }
    +}
    +
    +static void evdev_pass_values(struct evdev_client *client,
    + const struct input_value *vals, unsigned int count,
    + ktime_t mono, ktime_t real)
    +{
    + struct evdev *evdev = client->evdev;
    + const struct input_value *v;
    + struct input_event event;
    + bool wakeup = false;
    +
    + event.time = ktime_to_timeval(client->clkid == CLOCK_MONOTONIC ?
    + mono : real);
    +
    + /* Interrupts are disabled, just acquire the lock. */
    + spin_lock(&client->buffer_lock);
    +
    + for (v = vals; v != vals + count; v++) {
    + event.type = v->type;
    + event.code = v->code;
    + event.value = v->value;
    + __pass_event(client, &event);
    + if (v->type == EV_SYN && v->code == SYN_REPORT)
    + wakeup = true;
    + }

    spin_unlock(&client->buffer_lock);
    +
    + if (wakeup)
    + wake_up_interruptible(&evdev->wait);
    }

    /*
    - * Pass incoming event to all connected clients.
    + * Pass incoming events to all connected clients.
    */
    -static void evdev_event(struct input_handle *handle,
    - unsigned int type, unsigned int code, int value)
    +static void evdev_events(struct input_handle *handle,
    + const struct input_value *vals, unsigned int count)
    {
    struct evdev *evdev = handle->private;
    struct evdev_client *client;
    - struct input_event event;
    ktime_t time_mono, time_real;

    time_mono = ktime_get();
    time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());

    - event.type = type;
    - event.code = code;
    - event.value = value;
    -
    rcu_read_lock();

    client = rcu_dereference(evdev->grab);

    if (client)
    - evdev_pass_event(client, &event, time_mono, time_real);
    + evdev_pass_values(client, vals, count, time_mono, time_real);
    else
    list_for_each_entry_rcu(client, &evdev->client_list, node)
    - evdev_pass_event(client, &event, time_mono, time_real);
    + evdev_pass_values(client, vals, count,
    + time_mono, time_real);

    rcu_read_unlock();
    +}

    - if (type == EV_SYN && code == SYN_REPORT)
    - wake_up_interruptible(&evdev->wait);
    +/*
    + * Pass incoming event to all connected clients.
    + */
    +static void evdev_event(struct input_handle *handle,
    + unsigned int type, unsigned int code, int value)
    +{
    + struct input_value vals[] = { { type, code, value } };
    +
    + evdev_events(handle, vals, 1);
    }

    static int evdev_fasync(int fd, struct file *file, int on)
    @@ -1050,6 +1075,7 @@ MODULE_DEVICE_TABLE(input, evdev_ids);

    static struct input_handler evdev_handler = {
    .event = evdev_event,
    + .events = evdev_events,
    .connect = evdev_connect,
    .disconnect = evdev_disconnect,
    .fops = &evdev_fops,
    --
    1.7.12


    \
     
     \ /
      Last update: 2012-09-01 22:41    [W:0.034 / U:60.868 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site