diff options
| -rw-r--r-- | drivers/input/evdev.c | 34 |
1 files changed, 23 insertions, 11 deletions
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) | |||
| 108 | client->head = head; | 108 | client->head = head; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /* queue SYN_DROPPED event and flush queue if flush parameter is true */ | 111 | static void __evdev_queue_syn_dropped(struct evdev_client *client) |
| 112 | static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) | ||
| 113 | { | 112 | { |
| 114 | unsigned long flags; | ||
| 115 | struct input_event ev; | 113 | struct input_event ev; |
| 116 | ktime_t time; | 114 | ktime_t time; |
| 117 | 115 | ||
| @@ -126,11 +124,6 @@ static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) | |||
| 126 | ev.code = SYN_DROPPED; | 124 | ev.code = SYN_DROPPED; |
| 127 | ev.value = 0; | 125 | ev.value = 0; |
| 128 | 126 | ||
| 129 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
| 130 | |||
| 131 | if (flush) | ||
| 132 | client->packet_head = client->head = client->tail; | ||
| 133 | |||
| 134 | client->buffer[client->head++] = ev; | 127 | client->buffer[client->head++] = ev; |
| 135 | client->head &= client->bufsize - 1; | 128 | client->head &= client->bufsize - 1; |
| 136 | 129 | ||
| @@ -139,12 +132,21 @@ static void evdev_queue_syn_dropped(struct evdev_client *client, bool flush) | |||
| 139 | client->tail = (client->head - 1) & (client->bufsize - 1); | 132 | client->tail = (client->head - 1) & (client->bufsize - 1); |
| 140 | client->packet_head = client->tail; | 133 | client->packet_head = client->tail; |
| 141 | } | 134 | } |
| 135 | } | ||
| 136 | |||
| 137 | static void evdev_queue_syn_dropped(struct evdev_client *client) | ||
| 138 | { | ||
| 139 | unsigned long flags; | ||
| 142 | 140 | ||
| 141 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
| 142 | __evdev_queue_syn_dropped(client); | ||
| 143 | spin_unlock_irqrestore(&client->buffer_lock, flags); | 143 | spin_unlock_irqrestore(&client->buffer_lock, flags); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) | 146 | static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) |
| 147 | { | 147 | { |
| 148 | unsigned long flags; | ||
| 149 | |||
| 148 | if (client->clk_type == clkid) | 150 | if (client->clk_type == clkid) |
| 149 | return 0; | 151 | return 0; |
| 150 | 152 | ||
| @@ -163,8 +165,18 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid) | |||
| 163 | return -EINVAL; | 165 | return -EINVAL; |
| 164 | } | 166 | } |
| 165 | 167 | ||
| 166 | /* Flush pending events and queue SYN_DROPPED event.*/ | 168 | /* |
| 167 | evdev_queue_syn_dropped(client, true); | 169 | * Flush pending events and queue SYN_DROPPED event, |
| 170 | * but only if the queue is not empty. | ||
| 171 | */ | ||
| 172 | spin_lock_irqsave(&client->buffer_lock, flags); | ||
| 173 | |||
| 174 | if (client->head != client->tail) { | ||
| 175 | client->packet_head = client->head = client->tail; | ||
| 176 | __evdev_queue_syn_dropped(client); | ||
| 177 | } | ||
| 178 | |||
| 179 | spin_unlock_irqrestore(&client->buffer_lock, flags); | ||
| 168 | 180 | ||
| 169 | return 0; | 181 | return 0; |
| 170 | } | 182 | } |
| @@ -803,7 +815,7 @@ static int evdev_handle_get_val(struct evdev_client *client, | |||
| 803 | 815 | ||
| 804 | ret = bits_to_user(mem, maxbit, maxlen, p, compat); | 816 | ret = bits_to_user(mem, maxbit, maxlen, p, compat); |
| 805 | if (ret < 0) | 817 | if (ret < 0) |
| 806 | evdev_queue_syn_dropped(client, false); | 818 | evdev_queue_syn_dropped(client); |
| 807 | 819 | ||
| 808 | kfree(mem); | 820 | kfree(mem); |
| 809 | 821 | ||
