Commit 63a6404d authored by Henrik Rydberg's avatar Henrik Rydberg Committed by Dmitry Torokhov

Input: evdev - use driver hint to compute size of event buffer

Some devices, in particular MT devices, produce a lot of data.  This
may lead to overflowing of the event queues in evdev driver, which
by default are fairly small. Let the drivers hint the average number
of events per packet generated by the device, and use that information
when computing the buffer size evdev should use for the device.
Signed-off-by: default avatarHenrik Rydberg <rydberg@euromail.se>
Acked-by: default avatarChase Douglas <chase.douglas@canonical.com>
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
parent b58f7086
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
#define EVDEV_MINOR_BASE 64 #define EVDEV_MINOR_BASE 64
#define EVDEV_MINORS 32 #define EVDEV_MINORS 32
#define EVDEV_MIN_BUFFER_SIZE 64 #define EVDEV_MIN_BUFFER_SIZE 64U
#define EVDEV_BUF_PACKETS 8
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -245,7 +246,11 @@ static int evdev_release(struct inode *inode, struct file *file) ...@@ -245,7 +246,11 @@ static int evdev_release(struct inode *inode, struct file *file)
static unsigned int evdev_compute_buffer_size(struct input_dev *dev) static unsigned int evdev_compute_buffer_size(struct input_dev *dev)
{ {
return EVDEV_MIN_BUFFER_SIZE; unsigned int n_events =
max(dev->hint_events_per_packet * EVDEV_BUF_PACKETS,
EVDEV_MIN_BUFFER_SIZE);
return roundup_pow_of_two(n_events);
} }
static int evdev_open(struct inode *inode, struct file *file) static int evdev_open(struct inode *inode, struct file *file)
......
...@@ -1063,6 +1063,10 @@ struct ff_effect { ...@@ -1063,6 +1063,10 @@ struct ff_effect {
* @sndbit: bitmap of sound effects supported by the device * @sndbit: bitmap of sound effects supported by the device
* @ffbit: bitmap of force feedback effects supported by the device * @ffbit: bitmap of force feedback effects supported by the device
* @swbit: bitmap of switches present on the device * @swbit: bitmap of switches present on the device
* @hint_events_per_packet: average number of events generated by the
* device in a packet (between EV_SYN/SYN_REPORT events). Used by
* event handlers to estimate size of the buffer needed to hold
* events.
* @keycodemax: size of keycode table * @keycodemax: size of keycode table
* @keycodesize: size of elements in keycode table * @keycodesize: size of elements in keycode table
* @keycode: map of scancodes to keycodes for this device * @keycode: map of scancodes to keycodes for this device
...@@ -1140,6 +1144,8 @@ struct input_dev { ...@@ -1140,6 +1144,8 @@ struct input_dev {
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)]; unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)]; unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int hint_events_per_packet;
unsigned int keycodemax; unsigned int keycodemax;
unsigned int keycodesize; unsigned int keycodesize;
void *keycode; void *keycode;
...@@ -1408,6 +1414,21 @@ static inline void input_mt_sync(struct input_dev *dev) ...@@ -1408,6 +1414,21 @@ static inline void input_mt_sync(struct input_dev *dev)
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code); void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
/**
* input_set_events_per_packet - tell handlers about the driver event rate
* @dev: the input device used by the driver
* @n_events: the average number of events between calls to input_sync()
*
* If the event rate sent from a device is unusually large, use this
* function to set the expected event rate. This will allow handlers
* to set up an appropriate buffer size for the event stream, in order
* to minimize information loss.
*/
static inline void input_set_events_per_packet(struct input_dev *dev, int n_events)
{
dev->hint_events_per_packet = n_events;
}
static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat) static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
{ {
dev->absmin[axis] = min; dev->absmin[axis] = min;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment