* [PATCH v2 0/3] input: Dynamic Minor Numbers @ 2012-09-20 17:52 David Herrmann 2012-09-20 17:52 ` [PATCH v2 1/3] input: add dynamic-minor allocation helpers David Herrmann ` (3 more replies) 0 siblings, 4 replies; 10+ messages in thread From: David Herrmann @ 2012-09-20 17:52 UTC (permalink / raw) To: linux-input Cc: Dmitry Torokhov, linux-kernel, Bernie Thompson, David Herrmann Hi This is version 2 of the Dynamic Minor Numbers support for input devices. Version 1 can be found here: http://thread.gmane.org/gmane.linux.kernel.input/26842 For historical reasons, each input-handler (like evdev, joydev etc.) gets 32 minor numbers assigned statically. That means, if we have more than 32 input devices, then there will not be any /dev/input/eventX device that user-space can use to access the device. While 32 devices were enough for a long time, multi-seat machines currently cannot create more than 8 seats due to this restriction (assuming 3 devices per seat plus some static devices). This patchset allows input-handlers to allocate dynamic minor numbers if they run out of static numbers. Patch #1 adds the infrastructure to the input core, patch #2 makes sure we allow enough devices so we actually have room for dynamic minor numbers and patch #3 converts evdev to use it. Unused static minors numbers are never used for the dynamic minor numbers pool. So existing user-space does not break. But old user-space (not using udev) will not be able to use the new devices. Existing user-space with udev support will be able to use it, but the xserver currently crashes when more than 40 devices are added (which is unrelated to this patch). If you want to test it, you can use this tool which creates dummy input devices via uinput: https://gist.github.com/3756232 Example output for 'ls -la /dev/input': https://gist.github.com/3755663 I fixed minor coding-style issues since version 1 and a NULL-dereference in input_minor_alloc(). Regards David David Herrmann (3): input: add dynamic-minor allocation helpers input: increase INPUT_DEVICES to 512 to allow dynamic minors input: evdev: use dynamic-minors if running out of static minors drivers/input/evdev.c | 95 +++++++++++++++------------- drivers/input/input.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/input.h | 5 ++ 3 files changed, 222 insertions(+), 45 deletions(-) -- 1.7.12 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/3] input: add dynamic-minor allocation helpers 2012-09-20 17:52 [PATCH v2 0/3] input: Dynamic Minor Numbers David Herrmann @ 2012-09-20 17:52 ` David Herrmann 2012-09-20 17:52 ` [PATCH v2 2/3] input: increase INPUT_DEVICES to 512 to allow dynamic minors David Herrmann ` (2 subsequent siblings) 3 siblings, 0 replies; 10+ messages in thread From: David Herrmann @ 2012-09-20 17:52 UTC (permalink / raw) To: linux-input Cc: Dmitry Torokhov, linux-kernel, Bernie Thompson, David Herrmann Every input-handler-backend like evdev and joydev were allocated 32 minor numbers for historical reasons. This is a very low limit for modern linux desktops and prevents new technologies like multi-seat from becoming more useful. This introduces four new global helpers that allow input-handler-backends to allocate minors dynamically. New backends can even drop any static-minor support and allocate all minors dynamically through this API. All minors that are available beyond the minors-range used for static allocations can be allocated by this API. The maximum number of devices is still limited by INPUT_DEVICES+register_chrdev() but can now be extended to increase the dynamic-minors range. This patch is fully backwards-compatible and all handlers can be converted to use this API without breaking backwards-compatiblity. However, new devices using dynamically allocated minor numbers might not be visible to old user-space programs that do not use libudev or similar. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> --- drivers/input/input.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++++- include/linux/input.h | 5 ++ 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index 8921c61..2741ce1 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -45,7 +45,14 @@ static LIST_HEAD(input_handler_list); */ static DEFINE_MUTEX(input_mutex); +/* + * Please note that everything beyond the size of this array is used for + * dynamic minor allocations. Please also avoid adding new users to this array. + * Instead of relying on static minor-allocations, you should use dynamic minors + * exlusively. See input_minor_alloc(). + */ static struct input_handler *input_table[8]; +#define INPUT_TABLE_SIZE ARRAY_SIZE(input_table) static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max) @@ -2090,18 +2097,171 @@ void input_unregister_handle(struct input_handle *handle) } EXPORT_SYMBOL(input_unregister_handle); +/* + * Dynamic Minors + * Historically, each handler-backend gets 32 minors allocated. This was enough + * in old times, but today we often want more input devices. Therefore, if you + * run out of minors, you can request new dynamic minors from the input core. + * These are above an upper limit so they do not collide with static minors. + * Furthermore, you can save an arbitrary data pointer with them so you don't + * have to keep a list of dynamic minors yourself. + * + * There can be up to INPUT_TABLE_SIZE static minor users with 32 minors for + * each. Therefore, we start allocating dynamic minors beyond + * INPUT_TABLE_SIZE << 5. But we still must make sure we are below INPUT_DEVICES + * which is the upper limit and maximum minor size that we allocate on startup. + */ + +#define INPUT_MINOR_DYNAMIC_START (INPUT_TABLE_SIZE << 5) + +struct input_minor { + struct input_handler *handler; + void *data; +}; + +static DEFINE_MUTEX(dynamic_minors_lock); +static size_t dynamic_minors_size; +static struct input_minor *dynamic_minors; + +int input_minor_alloc(struct input_handler *handler, void *data) +{ + struct input_minor *narray; + unsigned int i, nsize; + int minor = -1, ret; + + if (!handler) + return -EINVAL; + + mutex_lock(&dynamic_minors_lock); + + for (i = 0; i < dynamic_minors_size; ++i) { + if (!dynamic_minors[i].handler) { + minor = i; + break; + } + } + + if (minor < 0) { + nsize = dynamic_minors_size * 2; + if (!nsize) + nsize = 32; + narray = krealloc(dynamic_minors, + nsize * sizeof(*dynamic_minors), + GFP_KERNEL); + if (!narray) { + ret = -ENOMEM; + goto out_unlock; + } + + memset(&narray[dynamic_minors_size], 0, + sizeof(*dynamic_minors) * (nsize - dynamic_minors_size)); + + minor = dynamic_minors_size; + dynamic_minors = narray; + dynamic_minors_size = nsize; + } + + ret = minor + INPUT_MINOR_DYNAMIC_START; + if (ret >= INPUT_DEVICES) { + ret = -ENFILE; + goto out_unlock; + } + + dynamic_minors[minor].handler = handler; + dynamic_minors[minor].data = data; + +out_unlock: + mutex_unlock(&dynamic_minors_lock); + return ret; +} +EXPORT_SYMBOL(input_minor_alloc); + +void input_minor_free(int minor) +{ + if (minor < INPUT_MINOR_DYNAMIC_START) + return; + + mutex_lock(&dynamic_minors_lock); + + minor -= INPUT_MINOR_DYNAMIC_START; + if (minor >= dynamic_minors_size) + goto out_unlock; + + dynamic_minors[minor].handler = NULL; + dynamic_minors[minor].data = NULL; + +out_unlock: + mutex_unlock(&dynamic_minors_lock); +} +EXPORT_SYMBOL(input_minor_free); + +void *input_minor_get_data(int minor) +{ + void *res; + + if (minor < INPUT_MINOR_DYNAMIC_START) + return NULL; + + mutex_lock(&dynamic_minors_lock); + + minor -= INPUT_MINOR_DYNAMIC_START; + if (minor >= dynamic_minors_size) { + res = NULL; + goto out_unlock; + } + + res = dynamic_minors[minor].data; + +out_unlock: + mutex_unlock(&dynamic_minors_lock); + return res; +} +EXPORT_SYMBOL(input_minor_get_data); + +struct input_handler *input_minor_get_handler(int minor) +{ + void *res; + + if (minor < INPUT_MINOR_DYNAMIC_START) + return NULL; + + mutex_lock(&dynamic_minors_lock); + + minor -= INPUT_MINOR_DYNAMIC_START; + if (minor >= dynamic_minors_size) { + res = NULL; + goto out_unlock; + } + + res = dynamic_minors[minor].handler; + +out_unlock: + mutex_unlock(&dynamic_minors_lock); + return res; +} +EXPORT_SYMBOL(input_minor_get_handler); + static int input_open_file(struct inode *inode, struct file *file) { struct input_handler *handler; const struct file_operations *old_fops, *new_fops = NULL; int err; + unsigned int minor, minor_group; err = mutex_lock_interruptible(&input_mutex); if (err) return err; /* No load-on-demand here? */ - handler = input_table[iminor(inode) >> 5]; + + minor = iminor(inode); + minor_group = minor >> 5; + + if (minor_group < INPUT_TABLE_SIZE) + handler = input_table[minor_group]; + else + handler = input_minor_get_handler(minor); + if (handler) new_fops = fops_get(handler->fops); diff --git a/include/linux/input.h b/include/linux/input.h index 2740d08..3fa3d7b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1486,6 +1486,11 @@ void input_reset_device(struct input_dev *); int __must_check input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); +int input_minor_alloc(struct input_handler *, void *); +void input_minor_free(int); +void *input_minor_get_data(int); +struct input_handler *input_minor_get_handler(int); + int input_handler_for_each_handle(struct input_handler *, void *data, int (*fn)(struct input_handle *, void *)); -- 1.7.12 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/3] input: increase INPUT_DEVICES to 512 to allow dynamic minors 2012-09-20 17:52 [PATCH v2 0/3] input: Dynamic Minor Numbers David Herrmann 2012-09-20 17:52 ` [PATCH v2 1/3] input: add dynamic-minor allocation helpers David Herrmann @ 2012-09-20 17:52 ` David Herrmann 2012-09-20 17:52 ` [PATCH v2 3/3] input: evdev: use dynamic-minors if running out of static minors David Herrmann 2012-09-21 8:07 ` [PATCH v2 0/3] input: Dynamic Minor Numbers Dmitry Torokhov 3 siblings, 0 replies; 10+ messages in thread From: David Herrmann @ 2012-09-20 17:52 UTC (permalink / raw) To: linux-input Cc: Dmitry Torokhov, linux-kernel, Bernie Thompson, David Herrmann All minor numbers for input devices are currently reserved for static allocations. So increase the maximum number of input-devices to 512 to give room of 256 devices for dynamic-minor allocation. register_chrdev uses 256 as default limit so we need to change this function call to actually pass the new number of devices. This makes it also clearer how many minor numbers are actually allocated. Please note that this doesn't increase the memory footprint at all. The major/minor allocations are no longer realized by lookup-tables so we could even increase this to some insanely large value and wouldn't loose any performance here. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> --- drivers/input/input.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/input/input.c b/drivers/input/input.c index 2741ce1..f8d985f 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -32,7 +32,7 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_DESCRIPTION("Input core"); MODULE_LICENSE("GPL"); -#define INPUT_DEVICES 256 +#define INPUT_DEVICES 512 static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); @@ -2310,7 +2310,8 @@ static int __init input_init(void) if (err) goto fail1; - err = register_chrdev(INPUT_MAJOR, "input", &input_fops); + err = __register_chrdev(INPUT_MAJOR, 0, INPUT_DEVICES, "input", + &input_fops); if (err) { pr_err("unable to register char major %d", INPUT_MAJOR); goto fail2; -- 1.7.12 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 3/3] input: evdev: use dynamic-minors if running out of static minors 2012-09-20 17:52 [PATCH v2 0/3] input: Dynamic Minor Numbers David Herrmann 2012-09-20 17:52 ` [PATCH v2 1/3] input: add dynamic-minor allocation helpers David Herrmann 2012-09-20 17:52 ` [PATCH v2 2/3] input: increase INPUT_DEVICES to 512 to allow dynamic minors David Herrmann @ 2012-09-20 17:52 ` David Herrmann 2012-09-21 8:07 ` [PATCH v2 0/3] input: Dynamic Minor Numbers Dmitry Torokhov 3 siblings, 0 replies; 10+ messages in thread From: David Herrmann @ 2012-09-20 17:52 UTC (permalink / raw) To: linux-input Cc: Dmitry Torokhov, linux-kernel, Bernie Thompson, David Herrmann When 32 devices were registered and we are running out of minor numbers, then use the new dynamic-minor infrastructure to get more minor numbers. This is fully backwards compatible, except devices with dynamic minors might not be visible to old userspace programs. However, without this patch these devices aren't visible, either, so this is no problem at all. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> --- drivers/input/evdev.c | 95 ++++++++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6c58bff..2e8a0b1 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -12,6 +12,7 @@ #define EVDEV_MINOR_BASE 64 #define EVDEV_MINORS 32 +#define EVDEV_MINOR_MAX (EVDEV_MINOR_BASE + EVDEV_MINORS - 1) #define EVDEV_MIN_BUFFER_SIZE 64U #define EVDEV_BUF_PACKETS 8 @@ -53,6 +54,7 @@ struct evdev_client { static struct evdev *evdev_table[EVDEV_MINORS]; static DEFINE_MUTEX(evdev_table_mutex); +static struct input_handler evdev_handler; static void evdev_pass_event(struct evdev_client *client, struct input_event *event, @@ -287,23 +289,30 @@ static int evdev_open(struct inode *inode, struct file *file) { struct evdev *evdev; struct evdev_client *client; - int i = iminor(inode) - EVDEV_MINOR_BASE; + int i, minor = iminor(inode); unsigned int bufsize; int error; + struct input_handler *handler; - if (i >= EVDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&evdev_table_mutex); - if (error) - return error; - evdev = evdev_table[i]; - if (evdev) + i = minor - EVDEV_MINOR_BASE; + if (i >= EVDEV_MINORS) { + evdev = input_minor_get_data(minor); + handler = input_minor_get_handler(minor); + if (handler != &evdev_handler) + return -ENODEV; get_device(&evdev->dev); - mutex_unlock(&evdev_table_mutex); - - if (!evdev) - return -ENODEV; + } else { + error = mutex_lock_interruptible(&evdev_table_mutex); + if (error) + return error; + evdev = evdev_table[i]; + if (evdev) + get_device(&evdev->dev); + mutex_unlock(&evdev_table_mutex); + + if (!evdev) + return -ENODEV; + } bufsize = evdev_compute_buffer_size(evdev->handle.dev); @@ -915,24 +924,18 @@ static const struct file_operations evdev_fops = { .llseek = no_llseek, }; -static int evdev_install_chrdev(struct evdev *evdev) -{ - /* - * No need to do any locking here as calls to connect and - * disconnect are serialized by the input core - */ - evdev_table[evdev->minor] = evdev; - return 0; -} - static void evdev_remove_chrdev(struct evdev *evdev) { /* * Lock evdev table to prevent race with evdev_open() */ - mutex_lock(&evdev_table_mutex); - evdev_table[evdev->minor] = NULL; - mutex_unlock(&evdev_table_mutex); + if (evdev->minor > EVDEV_MINOR_MAX) { + input_minor_free(evdev->minor); + } else { + mutex_lock(&evdev_table_mutex); + evdev_table[evdev->minor] = NULL; + mutex_unlock(&evdev_table_mutex); + } } /* @@ -973,19 +976,33 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, int minor; int error; - for (minor = 0; minor < EVDEV_MINORS; minor++) - if (!evdev_table[minor]) + evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); + if (!evdev) + return -ENOMEM; + + /* + * No need to do any locking here as calls to connect and + * disconnect are serialized by the input core + */ + for (minor = 0; minor < EVDEV_MINORS; minor++) { + if (!evdev_table[minor]) { + evdev_table[minor] = evdev; + evdev->dev.devt = MKDEV(INPUT_MAJOR, + EVDEV_MINOR_BASE + minor); break; + } + } if (minor == EVDEV_MINORS) { - pr_err("no more free evdev devices\n"); - return -ENFILE; + minor = input_minor_alloc(handler, evdev); + if (minor < 0) { + pr_err("no more free evdev devices\n"); + kfree(evdev); + return minor; + } + evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); } - evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); - if (!evdev) - return -ENOMEM; - INIT_LIST_HEAD(&evdev->client_list); spin_lock_init(&evdev->client_lock); mutex_init(&evdev->mutex); @@ -1000,7 +1017,6 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, evdev->handle.handler = handler; evdev->handle.private = evdev; - evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; evdev->dev.release = evdev_free; @@ -1010,21 +1026,16 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, if (error) goto err_free_evdev; - error = evdev_install_chrdev(evdev); - if (error) - goto err_unregister_handle; - error = device_add(&evdev->dev); if (error) - goto err_cleanup_evdev; + goto err_unregister_handle; return 0; - err_cleanup_evdev: - evdev_cleanup(evdev); err_unregister_handle: input_unregister_handle(&evdev->handle); err_free_evdev: + evdev_cleanup(evdev); put_device(&evdev->dev); return error; } -- 1.7.12 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] input: Dynamic Minor Numbers 2012-09-20 17:52 [PATCH v2 0/3] input: Dynamic Minor Numbers David Herrmann ` (2 preceding siblings ...) 2012-09-20 17:52 ` [PATCH v2 3/3] input: evdev: use dynamic-minors if running out of static minors David Herrmann @ 2012-09-21 8:07 ` Dmitry Torokhov 2012-09-21 9:22 ` David Herrmann 2012-09-25 8:55 ` David Herrmann 3 siblings, 2 replies; 10+ messages in thread From: Dmitry Torokhov @ 2012-09-21 8:07 UTC (permalink / raw) To: David Herrmann; +Cc: linux-input, linux-kernel, Bernie Thompson Hi David, On Thu, Sep 20, 2012 at 07:52:00PM +0200, David Herrmann wrote: > Hi > > This is version 2 of the Dynamic Minor Numbers support for input devices. > Version 1 can be found here: > http://thread.gmane.org/gmane.linux.kernel.input/26842 > > For historical reasons, each input-handler (like evdev, joydev etc.) gets 32 > minor numbers assigned statically. That means, if we have more than 32 input > devices, then there will not be any /dev/input/eventX device that user-space can > use to access the device. > While 32 devices were enough for a long time, multi-seat machines currently > cannot create more than 8 seats due to this restriction (assuming 3 devices per > seat plus some static devices). > > This patchset allows input-handlers to allocate dynamic minor numbers if they > run out of static numbers. Patch #1 adds the infrastructure to the input core, > patch #2 makes sure we allow enough devices so we actually have room for dynamic > minor numbers and patch #3 converts evdev to use it. > > Unused static minors numbers are never used for the dynamic minor numbers pool. > So existing user-space does not break. But old user-space (not using udev) will > not be able to use the new devices. Thank you very much for working on this, unfortunately your patch extends the existing infrastructure handling of character devices in input core, which is quite rigid and sub-optimal. For a while now I wanted to stop input core from pre-creating character devices and multiplexing file operations and instead push more chardev handling tasks into individual input handlers and make they more independent from input core. So while I won't be taking your patch as is it was a great motivator to finally do something about current limitation and I would appreciate if you could take a look at the patch below and see if you have any issues with it. The main difference from your patch: - switch to cdev infrastructure and creating only devices that actually exist - this simplifies handling of opening non-existing devices as there won't be any; - use IDR/IDA framework for tracking minors; - mousedev and joydev also use dynamic minors. Thanks! -- Dmitry Input: extend the number of event (and other) devices From: Dmitry Torokhov <dmitry.torokhov@gmail.com> Extend the amount of character devices, such as eventX, mouseX and jsX, from a hard limit of 32 per input handler to about 1024 shared across all handlers. To be compatible with legacy installations input handlers will start creating char devices with minors in their legacy range, however once legacy range is exhausted they will start allocating minors from the dynamic range 256-1024. Because input handlers now do the majority of character devices handling and not register their file operations with input core format of /proc/bus/input/handlers was changed: "Minor=X" line was taken out. With dynamic minors is does not make much sense anyway and nobody was ever using it. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> --- drivers/input/evdev.c | 99 +++++++------------- drivers/input/input.c | 114 +++++++++++------------ drivers/input/joydev.c | 88 ++++++------------ drivers/input/mousedev.c | 224 ++++++++++++++++++++++++---------------------- include/linux/input.h | 9 +- 5 files changed, 237 insertions(+), 297 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 6c58bff..0bc4507 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -23,11 +23,11 @@ #include <linux/input/mt.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/cdev.h> #include "input-compat.h" struct evdev { int open; - int minor; struct input_handle handle; wait_queue_head_t wait; struct evdev_client __rcu *grab; @@ -35,6 +35,7 @@ struct evdev { spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + struct cdev cdev; bool exist; }; @@ -51,9 +52,6 @@ struct evdev_client { struct input_event buffer[]; }; -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) @@ -285,35 +283,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev) static int evdev_open(struct inode *inode, struct file *file) { - struct evdev *evdev; + struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); + unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); struct evdev_client *client; - int i = iminor(inode) - EVDEV_MINOR_BASE; - unsigned int bufsize; int error; - if (i >= EVDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&evdev_table_mutex); - if (error) - return error; - evdev = evdev_table[i]; - if (evdev) - get_device(&evdev->dev); - mutex_unlock(&evdev_table_mutex); - - if (!evdev) - return -ENODEV; - - bufsize = evdev_compute_buffer_size(evdev->handle.dev); - client = kzalloc(sizeof(struct evdev_client) + bufsize * sizeof(struct input_event), GFP_KERNEL); - if (!client) { - error = -ENOMEM; - goto err_put_evdev; - } + if (!client) + return -ENOMEM; client->bufsize = bufsize; spin_lock_init(&client->buffer_lock); @@ -327,13 +306,12 @@ static int evdev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); + get_device(&evdev->dev); return 0; err_free_client: evdev_detach_client(evdev, client); kfree(client); - err_put_evdev: - put_device(&evdev->dev); return error; } @@ -915,26 +893,6 @@ static const struct file_operations evdev_fops = { .llseek = no_llseek, }; -static int evdev_install_chrdev(struct evdev *evdev) -{ - /* - * No need to do any locking here as calls to connect and - * disconnect are serialized by the input core - */ - evdev_table[evdev->minor] = evdev; - return 0; -} - -static void evdev_remove_chrdev(struct evdev *evdev) -{ - /* - * Lock evdev table to prevent race with evdev_open() - */ - mutex_lock(&evdev_table_mutex); - evdev_table[evdev->minor] = NULL; - mutex_unlock(&evdev_table_mutex); -} - /* * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted @@ -953,7 +911,8 @@ static void evdev_cleanup(struct evdev *evdev) evdev_mark_dead(evdev); evdev_hangup(evdev); - evdev_remove_chrdev(evdev); + + cdev_del(&evdev->cdev); /* evdev is marked dead so no one else accesses evdev->open */ if (evdev->open) { @@ -964,43 +923,47 @@ static void evdev_cleanup(struct evdev *evdev) /* * Create new evdev device. Note that input core serializes calls - * to connect and disconnect so we don't need to lock evdev_table here. + * to connect and disconnect. */ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct evdev *evdev; int minor; + int dev_no; int error; - for (minor = 0; minor < EVDEV_MINORS; minor++) - if (!evdev_table[minor]) - break; - - if (minor == EVDEV_MINORS) { - pr_err("no more free evdev devices\n"); - return -ENFILE; + minor = input_get_new_minor(EVDEV_MINOR_BASE, 8 /*EVDEV_MINORS*/, true); + if (minor < 0) { + error = minor; + pr_err("failed to reserve new minor: %d\n", error); + return error; } evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); - if (!evdev) - return -ENOMEM; + if (!evdev) { + error = -ENOMEM; + goto err_free_minor; + } INIT_LIST_HEAD(&evdev->client_list); spin_lock_init(&evdev->client_lock); mutex_init(&evdev->mutex); init_waitqueue_head(&evdev->wait); - - dev_set_name(&evdev->dev, "event%d", minor); evdev->exist = true; - evdev->minor = minor; + + dev_no = minor; + /* Normalize device number if it falls into legacy range */ + if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) + dev_no -= EVDEV_MINOR_BASE; + dev_set_name(&evdev->dev, "event%d", dev_no); evdev->handle.dev = input_get_device(dev); evdev->handle.name = dev_name(&evdev->dev); evdev->handle.handler = handler; evdev->handle.private = evdev; - evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); + evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; evdev->dev.release = evdev_free; @@ -1010,7 +973,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, if (error) goto err_free_evdev; - error = evdev_install_chrdev(evdev); + cdev_init(&evdev->cdev, &evdev_fops); + error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); if (error) goto err_unregister_handle; @@ -1026,6 +990,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, input_unregister_handle(&evdev->handle); err_free_evdev: put_device(&evdev->dev); + err_free_minor: + input_free_minor(minor); return error; } @@ -1035,6 +1001,7 @@ static void evdev_disconnect(struct input_handle *handle) device_del(&evdev->dev); evdev_cleanup(evdev); + input_free_minor(MINOR(evdev->dev.devt)); input_unregister_handle(handle); put_device(&evdev->dev); } @@ -1050,8 +1017,6 @@ static struct input_handler evdev_handler = { .event = evdev_event, .connect = evdev_connect, .disconnect = evdev_disconnect, - .fops = &evdev_fops, - .minor = EVDEV_MINOR_BASE, .name = "evdev", .id_table = evdev_ids, }; diff --git a/drivers/input/input.c b/drivers/input/input.c index 768e46b..1869cf1 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/types.h> +#include <linux/idr.h> #include <linux/input/mt.h> #include <linux/module.h> #include <linux/slab.h> @@ -32,7 +33,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_DESCRIPTION("Input core"); MODULE_LICENSE("GPL"); -#define INPUT_DEVICES 256 +#define INPUT_MAX_CHAR_DEVICES 1024 +#define INPUT_FIRST_DYNAMIC_DEV 256 +static DEFINE_IDA(input_ida); static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); @@ -45,8 +48,6 @@ static LIST_HEAD(input_handler_list); */ static DEFINE_MUTEX(input_mutex); -static struct input_handler *input_table[8]; - static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max) { @@ -1144,8 +1145,6 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); if (handler->filter) seq_puts(seq, " (filter)"); - if (handler->fops) - seq_printf(seq, " Minor=%d", handler->minor); seq_putc(seq, '\n'); return 0; @@ -1932,22 +1931,14 @@ EXPORT_SYMBOL(input_unregister_device); int input_register_handler(struct input_handler *handler) { struct input_dev *dev; - int retval; + int error; - retval = mutex_lock_interruptible(&input_mutex); - if (retval) - return retval; + error = mutex_lock_interruptible(&input_mutex); + if (error) + return error; INIT_LIST_HEAD(&handler->h_list); - if (handler->fops != NULL) { - if (input_table[handler->minor >> 5]) { - retval = -EBUSY; - goto out; - } - input_table[handler->minor >> 5] = handler; - } - list_add_tail(&handler->node, &input_handler_list); list_for_each_entry(dev, &input_dev_list, node) @@ -1955,9 +1946,8 @@ int input_register_handler(struct input_handler *handler) input_wakeup_procfs_readers(); - out: mutex_unlock(&input_mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_register_handler); @@ -1980,9 +1970,6 @@ void input_unregister_handler(struct input_handler *handler) list_del_init(&handler->node); - if (handler->fops != NULL) - input_table[handler->minor >> 5] = NULL; - input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); @@ -2099,51 +2086,52 @@ void input_unregister_handle(struct input_handle *handle) } EXPORT_SYMBOL(input_unregister_handle); -static int input_open_file(struct inode *inode, struct file *file) +/** + * input_get_new_minor - allocates a new input minor number + * @legacy_base: beginning or the legacy range to be searched + * @legacy_num: size of legacy range + * @allow_dynamic: whether we can also take ID from the dynamic range + * + * This function allocates a new device minor for from input major namespace. + * Caller can request legacy minor by specifying @legacy_base and @legacy_num + * parameters and whether ID can be allocated from dynamic range if there are + * no free IDs in legacy range. + */ +int input_get_new_minor(int legacy_base, unsigned int legacy_num, + bool allow_dynamic) { - struct input_handler *handler; - const struct file_operations *old_fops, *new_fops = NULL; - int err; - - err = mutex_lock_interruptible(&input_mutex); - if (err) - return err; - - /* No load-on-demand here? */ - handler = input_table[iminor(inode) >> 5]; - if (handler) - new_fops = fops_get(handler->fops); - - mutex_unlock(&input_mutex); - /* - * That's _really_ odd. Usually NULL ->open means "nothing special", - * not "no device". Oh, well... + * This function should be called from input handler's ->connect() + * methods, which are serialized with input_mutex, so no additional + * locking is needed here. */ - if (!new_fops || !new_fops->open) { - fops_put(new_fops); - err = -ENODEV; - goto out; + if (legacy_base >= 0) { + int minor = ida_simple_get(&input_ida, + legacy_base, + legacy_base + legacy_num, + GFP_KERNEL); + if (minor >= 0 || !allow_dynamic) + return minor; } - old_fops = file->f_op; - file->f_op = new_fops; - - err = new_fops->open(inode, file); - if (err) { - fops_put(file->f_op); - file->f_op = fops_get(old_fops); - } - fops_put(old_fops); -out: - return err; + return ida_simple_get(&input_ida, + INPUT_FIRST_DYNAMIC_DEV, INPUT_MAX_CHAR_DEVICES, + GFP_KERNEL); } +EXPORT_SYMBOL(input_get_new_minor); -static const struct file_operations input_fops = { - .owner = THIS_MODULE, - .open = input_open_file, - .llseek = noop_llseek, -}; +/** + * input_free_minor - release previously allocated minor + * @minor: minor to be released + * + * This function releases previously allocated input minor so that it can be + * reused later. + */ +void input_free_minor(unsigned int minor) +{ + ida_simple_remove(&input_ida, minor); +} +EXPORT_SYMBOL(input_free_minor); static int __init input_init(void) { @@ -2159,7 +2147,8 @@ static int __init input_init(void) if (err) goto fail1; - err = register_chrdev(INPUT_MAJOR, "input", &input_fops); + err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0), + INPUT_MAX_CHAR_DEVICES, "input"); if (err) { pr_err("unable to register char major %d", INPUT_MAJOR); goto fail2; @@ -2175,7 +2164,8 @@ static int __init input_init(void) static void __exit input_exit(void) { input_proc_exit(); - unregister_chrdev(INPUT_MAJOR, "input"); + unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0), + INPUT_MAX_CHAR_DEVICES); class_unregister(&input_class); } diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index f0909ed..c82f76f 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -27,6 +27,7 @@ #include <linux/poll.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/cdev.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Joystick device interfaces"); @@ -39,13 +40,13 @@ MODULE_LICENSE("GPL"); struct joydev { int open; - int minor; struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + struct cdev cdev; bool exist; struct js_corr corr[ABS_CNT]; @@ -70,9 +71,6 @@ struct joydev_client { struct list_head node; }; -static struct joydev *joydev_table[JOYDEV_MINORS]; -static DEFINE_MUTEX(joydev_table_mutex); - static int joydev_correct(int value, struct js_corr *corr) { switch (corr->type) { @@ -252,30 +250,14 @@ static int joydev_release(struct inode *inode, struct file *file) static int joydev_open(struct inode *inode, struct file *file) { + struct joydev *joydev = + container_of(inode->i_cdev, struct joydev, cdev); struct joydev_client *client; - struct joydev *joydev; - int i = iminor(inode) - JOYDEV_MINOR_BASE; int error; - if (i >= JOYDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&joydev_table_mutex); - if (error) - return error; - joydev = joydev_table[i]; - if (joydev) - get_device(&joydev->dev); - mutex_unlock(&joydev_table_mutex); - - if (!joydev) - return -ENODEV; - client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); - if (!client) { - error = -ENOMEM; - goto err_put_joydev; - } + if (!client) + return -ENOMEM; spin_lock_init(&client->buffer_lock); client->joydev = joydev; @@ -288,13 +270,12 @@ static int joydev_open(struct inode *inode, struct file *file) file->private_data = client; nonseekable_open(inode, file); + get_device(&joydev->dev); return 0; err_free_client: joydev_detach_client(joydev, client); kfree(client); - err_put_joydev: - put_device(&joydev->dev); return error; } @@ -747,19 +728,6 @@ static const struct file_operations joydev_fops = { .llseek = no_llseek, }; -static int joydev_install_chrdev(struct joydev *joydev) -{ - joydev_table[joydev->minor] = joydev; - return 0; -} - -static void joydev_remove_chrdev(struct joydev *joydev) -{ - mutex_lock(&joydev_table_mutex); - joydev_table[joydev->minor] = NULL; - mutex_unlock(&joydev_table_mutex); -} - /* * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted @@ -778,7 +746,8 @@ static void joydev_cleanup(struct joydev *joydev) joydev_mark_dead(joydev); joydev_hangup(joydev); - joydev_remove_chrdev(joydev); + + cdev_del(&joydev->cdev); /* joydev is marked dead so no one else accesses joydev->open */ if (joydev->open) @@ -803,30 +772,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct joydev *joydev; - int i, j, t, minor; + int i, j, t, minor, dev_no; int error; - for (minor = 0; minor < JOYDEV_MINORS; minor++) - if (!joydev_table[minor]) - break; - - if (minor == JOYDEV_MINORS) { - pr_err("no more free joydev devices\n"); - return -ENFILE; + minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true); + if (minor < 0) { + error = minor; + pr_err("failed to reserve new minor: %d\n", error); + return error; } joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); - if (!joydev) - return -ENOMEM; + if (!joydev) { + error = -ENOMEM; + goto err_free_minor; + } INIT_LIST_HEAD(&joydev->client_list); spin_lock_init(&joydev->client_lock); mutex_init(&joydev->mutex); init_waitqueue_head(&joydev->wait); - - dev_set_name(&joydev->dev, "js%d", minor); joydev->exist = true; - joydev->minor = minor; + + dev_no = minor; + /* Normalize device number if it falls into legacy range */ + if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS) + dev_no -= JOYDEV_MINOR_BASE; + dev_set_name(&joydev->dev, "js%d", dev_no); joydev->handle.dev = input_get_device(dev); joydev->handle.name = dev_name(&joydev->dev); @@ -880,7 +852,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, } } - joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); + joydev->dev.devt = MKDEV(INPUT_MAJOR, minor); joydev->dev.class = &input_class; joydev->dev.parent = &dev->dev; joydev->dev.release = joydev_free; @@ -890,7 +862,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, if (error) goto err_free_joydev; - error = joydev_install_chrdev(joydev); + cdev_init(&joydev->cdev, &joydev_fops); + error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); if (error) goto err_unregister_handle; @@ -906,6 +879,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, input_unregister_handle(&joydev->handle); err_free_joydev: put_device(&joydev->dev); + err_free_minor: + input_free_minor(minor); return error; } @@ -915,6 +890,7 @@ static void joydev_disconnect(struct input_handle *handle) device_del(&joydev->dev); joydev_cleanup(joydev); + input_free_minor(MINOR(joydev->dev.devt)); input_unregister_handle(handle); put_device(&joydev->dev); } @@ -966,8 +942,6 @@ static struct input_handler joydev_handler = { .match = joydev_match, .connect = joydev_connect, .disconnect = joydev_disconnect, - .fops = &joydev_fops, - .minor = JOYDEV_MINOR_BASE, .name = "joydev", .id_table = joydev_ids, }; diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 964e43d..7fd9d91 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -24,10 +24,8 @@ #include <linux/random.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/cdev.h> #include <linux/kernel.h> -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX -#include <linux/miscdevice.h> -#endif MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces"); @@ -61,17 +59,18 @@ struct mousedev_hw_data { struct mousedev { int open; - int minor; struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + struct cdev cdev; bool exist; + bool is_mixdev; struct list_head mixdev_node; - int mixdev_open; + bool mixdev_open; struct mousedev_hw_data packet; unsigned int pkt_count; @@ -114,10 +113,6 @@ struct mousedev_client { static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; -static struct input_handler mousedev_handler; - -static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; -static DEFINE_MUTEX(mousedev_table_mutex); static struct mousedev *mousedev_mix; static LIST_HEAD(mousedev_mix_list); @@ -433,7 +428,7 @@ static int mousedev_open_device(struct mousedev *mousedev) if (retval) return retval; - if (mousedev->minor == MOUSEDEV_MIX) + if (mousedev->is_mixdev) mixdev_open_devices(); else if (!mousedev->exist) retval = -ENODEV; @@ -451,7 +446,7 @@ static void mousedev_close_device(struct mousedev *mousedev) { mutex_lock(&mousedev->mutex); - if (mousedev->minor == MOUSEDEV_MIX) + if (mousedev->is_mixdev) mixdev_close_devices(); else if (mousedev->exist && !--mousedev->open) input_close_device(&mousedev->handle); @@ -476,7 +471,7 @@ static void mixdev_open_devices(void) if (mousedev_open_device(mousedev)) continue; - mousedev->mixdev_open = 1; + mousedev->mixdev_open = true; } } } @@ -495,7 +490,7 @@ static void mixdev_close_devices(void) list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { if (mousedev->mixdev_open) { - mousedev->mixdev_open = 0; + mousedev->mixdev_open = false; mousedev_close_device(mousedev); } } @@ -538,35 +533,17 @@ static int mousedev_open(struct inode *inode, struct file *file) struct mousedev_client *client; struct mousedev *mousedev; int error; - int i; #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX if (imajor(inode) == MISC_MAJOR) - i = MOUSEDEV_MIX; + mousedev = mousedev_mix; else #endif - i = iminor(inode) - MOUSEDEV_MINOR_BASE; - - if (i >= MOUSEDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&mousedev_table_mutex); - if (error) - return error; - - mousedev = mousedev_table[i]; - if (mousedev) - get_device(&mousedev->dev); - mutex_unlock(&mousedev_table_mutex); - - if (!mousedev) - return -ENODEV; + mousedev = container_of(inode->i_cdev, struct mousedev, cdev); client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); - if (!client) { - error = -ENOMEM; - goto err_put_mousedev; - } + if (!client) + return -ENOMEM; spin_lock_init(&client->packet_lock); client->pos_x = xres / 2; @@ -579,13 +556,14 @@ static int mousedev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; + nonseekable_open(inode, file); + + get_device(&mousedev->dev); return 0; err_free_client: mousedev_detach_client(mousedev, client); kfree(client); - err_put_mousedev: - put_device(&mousedev->dev); return error; } @@ -785,29 +763,16 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait) } static const struct file_operations mousedev_fops = { - .owner = THIS_MODULE, - .read = mousedev_read, - .write = mousedev_write, - .poll = mousedev_poll, - .open = mousedev_open, - .release = mousedev_release, - .fasync = mousedev_fasync, - .llseek = noop_llseek, + .owner = THIS_MODULE, + .read = mousedev_read, + .write = mousedev_write, + .poll = mousedev_poll, + .open = mousedev_open, + .release = mousedev_release, + .fasync = mousedev_fasync, + .llseek = noop_llseek, }; -static int mousedev_install_chrdev(struct mousedev *mousedev) -{ - mousedev_table[mousedev->minor] = mousedev; - return 0; -} - -static void mousedev_remove_chrdev(struct mousedev *mousedev) -{ - mutex_lock(&mousedev_table_mutex); - mousedev_table[mousedev->minor] = NULL; - mutex_unlock(&mousedev_table_mutex); -} - /* * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted @@ -842,24 +807,50 @@ static void mousedev_cleanup(struct mousedev *mousedev) mousedev_mark_dead(mousedev); mousedev_hangup(mousedev); - mousedev_remove_chrdev(mousedev); + + cdev_del(&mousedev->cdev); /* mousedev is marked dead so no one else accesses mousedev->open */ if (mousedev->open) input_close_device(handle); } +static int mousedev_reserve_minor(bool mixdev) +{ + int minor; + + if (mixdev) { + minor = input_get_new_minor(MOUSEDEV_MIX, 1, false); + if (minor < 0) + pr_err("failed to reserve mixdev minor: %d\n", minor); + } else { + minor = input_get_new_minor(MOUSEDEV_MINOR_BASE, + MOUSEDEV_MINORS, true); + if (minor < 0) + pr_err("failed to reserve new minor: %d\n", minor); + } + + return minor; +} + static struct mousedev *mousedev_create(struct input_dev *dev, struct input_handler *handler, - int minor) + bool mixdev) { struct mousedev *mousedev; + int minor; int error; + minor = mousedev_reserve_minor(mixdev); + if (minor < 0) { + error = minor; + goto err_out; + } + mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); if (!mousedev) { error = -ENOMEM; - goto err_out; + goto err_free_minor; } INIT_LIST_HEAD(&mousedev->client_list); @@ -867,16 +858,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev, spin_lock_init(&mousedev->client_lock); mutex_init(&mousedev->mutex); lockdep_set_subclass(&mousedev->mutex, - minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0); + mixdev ? SINGLE_DEPTH_NESTING : 0); init_waitqueue_head(&mousedev->wait); - if (minor == MOUSEDEV_MIX) + if (mixdev) { dev_set_name(&mousedev->dev, "mice"); - else - dev_set_name(&mousedev->dev, "mouse%d", minor); + } else { + int dev_no = minor; + /* Normalize device number if it falls into legacy range */ + if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS) + dev_no -= MOUSEDEV_MINOR_BASE; + dev_set_name(&mousedev->dev, "mouse%d", dev_no); + } - mousedev->minor = minor; mousedev->exist = true; + mousedev->is_mixdev = mixdev; mousedev->handle.dev = input_get_device(dev); mousedev->handle.name = dev_name(&mousedev->dev); mousedev->handle.handler = handler; @@ -885,17 +881,18 @@ static struct mousedev *mousedev_create(struct input_dev *dev, mousedev->dev.class = &input_class; if (dev) mousedev->dev.parent = &dev->dev; - mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor); + mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor); mousedev->dev.release = mousedev_free; device_initialize(&mousedev->dev); - if (minor != MOUSEDEV_MIX) { + if (!mixdev) { error = input_register_handle(&mousedev->handle); if (error) goto err_free_mousedev; } - error = mousedev_install_chrdev(mousedev); + cdev_init(&mousedev->cdev, &mousedev_fops); + error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); if (error) goto err_unregister_handle; @@ -908,10 +905,12 @@ static struct mousedev *mousedev_create(struct input_dev *dev, err_cleanup_mousedev: mousedev_cleanup(mousedev); err_unregister_handle: - if (minor != MOUSEDEV_MIX) + if (!mixdev) input_unregister_handle(&mousedev->handle); err_free_mousedev: put_device(&mousedev->dev); + err_free_minor: + input_free_minor(minor); err_out: return ERR_PTR(error); } @@ -920,7 +919,8 @@ static void mousedev_destroy(struct mousedev *mousedev) { device_del(&mousedev->dev); mousedev_cleanup(mousedev); - if (mousedev->minor != MOUSEDEV_MIX) + input_free_minor(MINOR(mousedev->dev.devt)); + if (!mousedev->is_mixdev) input_unregister_handle(&mousedev->handle); put_device(&mousedev->dev); } @@ -938,7 +938,7 @@ static int mixdev_add_device(struct mousedev *mousedev) if (retval) goto out; - mousedev->mixdev_open = 1; + mousedev->mixdev_open = true; } get_device(&mousedev->dev); @@ -954,7 +954,7 @@ static void mixdev_remove_device(struct mousedev *mousedev) mutex_lock(&mousedev_mix->mutex); if (mousedev->mixdev_open) { - mousedev->mixdev_open = 0; + mousedev->mixdev_open = false; mousedev_close_device(mousedev); } @@ -969,19 +969,9 @@ static int mousedev_connect(struct input_handler *handler, const struct input_device_id *id) { struct mousedev *mousedev; - int minor; int error; - for (minor = 0; minor < MOUSEDEV_MINORS; minor++) - if (!mousedev_table[minor]) - break; - - if (minor == MOUSEDEV_MINORS) { - pr_err("no more free mousedev devices\n"); - return -ENFILE; - } - - mousedev = mousedev_create(dev, handler, minor); + mousedev = mousedev_create(dev, handler, false); if (IS_ERR(mousedev)) return PTR_ERR(mousedev); @@ -1054,27 +1044,59 @@ static const struct input_device_id mousedev_ids[] = { MODULE_DEVICE_TABLE(input, mousedev_ids); static struct input_handler mousedev_handler = { - .event = mousedev_event, - .connect = mousedev_connect, - .disconnect = mousedev_disconnect, - .fops = &mousedev_fops, - .minor = MOUSEDEV_MINOR_BASE, - .name = "mousedev", - .id_table = mousedev_ids, + .event = mousedev_event, + .connect = mousedev_connect, + .disconnect = mousedev_disconnect, + .name = "mousedev", + .id_table = mousedev_ids, }; #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX +#include <linux/miscdevice.h> + static struct miscdevice psaux_mouse = { - PSMOUSE_MINOR, "psaux", &mousedev_fops + .minor = PSMOUSE_MINOR, + .name = "psaux", + .fops = &mousedev_fops, }; -static int psaux_registered; +static bool psaux_registered; + +static void __init mousedev_psaux_register(void) +{ + int error; + + error = misc_register(&psaux_mouse); + if (error) + pr_warn("could not register psaux device, error: %d\n", + error); + else + psaux_registered = true; + +} + +static void __exit mousedev_psaux_unregister(void) +{ + if (psaux_registered) + misc_deregister(&psaux_mouse); +} + +#else + +static inline void mousedev_psaux_register(void) +{ +} + +static inline void mousedev_psaux_unregister(void) +{ +} + #endif static int __init mousedev_init(void) { int error; - mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX); + mousedev_mix = mousedev_create(NULL, &mousedev_handler, true); if (IS_ERR(mousedev_mix)) return PTR_ERR(mousedev_mix); @@ -1084,14 +1106,7 @@ static int __init mousedev_init(void) return error; } -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX - error = misc_register(&psaux_mouse); - if (error) - pr_warn("could not register psaux device, error: %d\n", - error); - else - psaux_registered = 1; -#endif + mousedev_psaux_register(); pr_info("PS/2 mouse device common for all mice\n"); @@ -1100,10 +1115,7 @@ static int __init mousedev_init(void) static void __exit mousedev_exit(void) { -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX - if (psaux_registered) - misc_deregister(&psaux_mouse); -#endif + mousedev_psaux_unregister(); input_unregister_handler(&mousedev_handler); mousedev_destroy(mousedev_mix); } diff --git a/include/linux/input.h b/include/linux/input.h index 725dcd0..c698e7e 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1387,9 +1387,6 @@ struct input_handle; * @start: starts handler for given handle. This function is called by * input core right after connect() method and also when a process * that "grabbed" a device releases it - * @fops: file operations this driver implements - * @minor: beginning of range of 32 minors for devices this driver - * can provide * @name: name of the handler, to be shown in /proc/bus/input/handlers * @id_table: pointer to a table of input_device_ids this driver can * handle @@ -1420,8 +1417,6 @@ struct input_handler { void (*disconnect)(struct input_handle *handle); void (*start)(struct input_handle *handle); - const struct file_operations *fops; - int minor; const char *name; const struct input_device_id *id_table; @@ -1488,6 +1483,10 @@ void input_reset_device(struct input_dev *); int __must_check input_register_handler(struct input_handler *); void input_unregister_handler(struct input_handler *); +int __must_check input_get_new_minor(int legacy_base, unsigned int legacy_num, + bool allow_dynamic); +void input_free_minor(unsigned int minor); + int input_handler_for_each_handle(struct input_handler *, void *data, int (*fn)(struct input_handle *, void *)); ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] input: Dynamic Minor Numbers 2012-09-21 8:07 ` [PATCH v2 0/3] input: Dynamic Minor Numbers Dmitry Torokhov @ 2012-09-21 9:22 ` David Herrmann 2012-09-21 19:18 ` David Herrmann 2012-09-25 8:55 ` David Herrmann 1 sibling, 1 reply; 10+ messages in thread From: David Herrmann @ 2012-09-21 9:22 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Bernie Thompson Hi Dmitry On Fri, Sep 21, 2012 at 10:07 AM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > Thank you very much for working on this, unfortunately your patch extends the > existing infrastructure handling of character devices in input core, > which is quite rigid and sub-optimal. > > For a while now I wanted to stop input core from pre-creating character > devices and multiplexing file operations and instead push more chardev > handling tasks into individual input handlers and make they more > independent from input core. So while I won't be taking your patch as is > it was a great motivator to finally do something about current > limitation and I would appreciate if you could take a look at the patch > below and see if you have any issues with it. I didn't know why we did that, anyway. But I tried to keep that logic, even though it is really weird. So I am quite glad that you fixed it. > The main difference from your patch: > > - switch to cdev infrastructure and creating only devices that actually > exist - this simplifies handling of opening non-existing devices as > there won't be any; > - use IDR/IDA framework for tracking minors; I didn't know of IDR/IDA, that's actually pretty nice. > - mousedev and joydev also use dynamic minors. I did never use them so I didn't want to dig into their code. I've also skipped reviewing them for now. I will try to review them later. > Thanks! > > -- > Dmitry > > > Input: extend the number of event (and other) devices > > From: Dmitry Torokhov <dmitry.torokhov@gmail.com> > > Extend the amount of character devices, such as eventX, mouseX and jsX, > from a hard limit of 32 per input handler to about 1024 shared across > all handlers. > > To be compatible with legacy installations input handlers will start > creating char devices with minors in their legacy range, however once > legacy range is exhausted they will start allocating minors from the > dynamic range 256-1024. > > Because input handlers now do the majority of character devices handling > and not register their file operations with input core format of > /proc/bus/input/handlers was changed: "Minor=X" line was taken out. > With dynamic minors is does not make much sense anyway and nobody was > ever using it. > > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> > --- > > drivers/input/evdev.c | 99 +++++++------------- > drivers/input/input.c | 114 +++++++++++------------ > drivers/input/joydev.c | 88 ++++++------------ > drivers/input/mousedev.c | 224 ++++++++++++++++++++++++---------------------- > include/linux/input.h | 9 +- > 5 files changed, 237 insertions(+), 297 deletions(-) If we ignore mousedev, this patch actually reduces line-count. That's pretty nice! > > diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c > index 6c58bff..0bc4507 100644 > --- a/drivers/input/evdev.c > +++ b/drivers/input/evdev.c > @@ -23,11 +23,11 @@ > #include <linux/input/mt.h> > #include <linux/major.h> > #include <linux/device.h> > +#include <linux/cdev.h> > #include "input-compat.h" > > struct evdev { > int open; > - int minor; > struct input_handle handle; > wait_queue_head_t wait; > struct evdev_client __rcu *grab; > @@ -35,6 +35,7 @@ struct evdev { > spinlock_t client_lock; /* protects client_list */ > struct mutex mutex; > struct device dev; > + struct cdev cdev; > bool exist; > }; > > @@ -51,9 +52,6 @@ struct evdev_client { > struct input_event buffer[]; > }; > > -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) > @@ -285,35 +283,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev) > > static int evdev_open(struct inode *inode, struct file *file) > { > - struct evdev *evdev; > + struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); > + unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); > struct evdev_client *client; > - int i = iminor(inode) - EVDEV_MINOR_BASE; > - unsigned int bufsize; > int error; > > - if (i >= EVDEV_MINORS) > - return -ENODEV; > - > - error = mutex_lock_interruptible(&evdev_table_mutex); > - if (error) > - return error; > - evdev = evdev_table[i]; > - if (evdev) > - get_device(&evdev->dev); > - mutex_unlock(&evdev_table_mutex); > - > - if (!evdev) > - return -ENODEV; > - > - bufsize = evdev_compute_buffer_size(evdev->handle.dev); > - > client = kzalloc(sizeof(struct evdev_client) + > bufsize * sizeof(struct input_event), > GFP_KERNEL); > - if (!client) { > - error = -ENOMEM; > - goto err_put_evdev; > - } > + if (!client) > + return -ENOMEM; > > client->bufsize = bufsize; > spin_lock_init(&client->buffer_lock); > @@ -327,13 +306,12 @@ static int evdev_open(struct inode *inode, struct file *file) > file->private_data = client; > nonseekable_open(inode, file); > > + get_device(&evdev->dev); > return 0; > > err_free_client: > evdev_detach_client(evdev, client); > kfree(client); > - err_put_evdev: > - put_device(&evdev->dev); > return error; > } > > @@ -915,26 +893,6 @@ static const struct file_operations evdev_fops = { > .llseek = no_llseek, > }; > > -static int evdev_install_chrdev(struct evdev *evdev) > -{ > - /* > - * No need to do any locking here as calls to connect and > - * disconnect are serialized by the input core > - */ > - evdev_table[evdev->minor] = evdev; > - return 0; > -} > - > -static void evdev_remove_chrdev(struct evdev *evdev) > -{ > - /* > - * Lock evdev table to prevent race with evdev_open() > - */ > - mutex_lock(&evdev_table_mutex); > - evdev_table[evdev->minor] = NULL; > - mutex_unlock(&evdev_table_mutex); > -} > - > /* > * Mark device non-existent. This disables writes, ioctls and > * prevents new users from opening the device. Already posted > @@ -953,7 +911,8 @@ static void evdev_cleanup(struct evdev *evdev) > > evdev_mark_dead(evdev); > evdev_hangup(evdev); > - evdev_remove_chrdev(evdev); > + > + cdev_del(&evdev->cdev); > > /* evdev is marked dead so no one else accesses evdev->open */ > if (evdev->open) { > @@ -964,43 +923,47 @@ static void evdev_cleanup(struct evdev *evdev) > > /* > * Create new evdev device. Note that input core serializes calls > - * to connect and disconnect so we don't need to lock evdev_table here. > + * to connect and disconnect. > */ > static int evdev_connect(struct input_handler *handler, struct input_dev *dev, > const struct input_device_id *id) > { > struct evdev *evdev; > int minor; > + int dev_no; > int error; > > - for (minor = 0; minor < EVDEV_MINORS; minor++) > - if (!evdev_table[minor]) > - break; > - > - if (minor == EVDEV_MINORS) { > - pr_err("no more free evdev devices\n"); > - return -ENFILE; > + minor = input_get_new_minor(EVDEV_MINOR_BASE, 8 /*EVDEV_MINORS*/, true); Why 8 instead of EVDEV_MINORS? > + if (minor < 0) { > + error = minor; > + pr_err("failed to reserve new minor: %d\n", error); > + return error; > } > > evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); > - if (!evdev) > - return -ENOMEM; > + if (!evdev) { > + error = -ENOMEM; > + goto err_free_minor; > + } > > INIT_LIST_HEAD(&evdev->client_list); > spin_lock_init(&evdev->client_lock); > mutex_init(&evdev->mutex); > init_waitqueue_head(&evdev->wait); > - > - dev_set_name(&evdev->dev, "event%d", minor); > evdev->exist = true; > - evdev->minor = minor; > + > + dev_no = minor; > + /* Normalize device number if it falls into legacy range */ > + if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) > + dev_no -= EVDEV_MINOR_BASE; > + dev_set_name(&evdev->dev, "event%d", dev_no); > > evdev->handle.dev = input_get_device(dev); > evdev->handle.name = dev_name(&evdev->dev); > evdev->handle.handler = handler; > evdev->handle.private = evdev; > > - evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); > + evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); > evdev->dev.class = &input_class; > evdev->dev.parent = &dev->dev; > evdev->dev.release = evdev_free; > @@ -1010,7 +973,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, > if (error) > goto err_free_evdev; > > - error = evdev_install_chrdev(evdev); > + cdev_init(&evdev->cdev, &evdev_fops); > + error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); > if (error) > goto err_unregister_handle; > > @@ -1026,6 +990,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, > input_unregister_handle(&evdev->handle); > err_free_evdev: > put_device(&evdev->dev); > + err_free_minor: > + input_free_minor(minor); > return error; > } > > @@ -1035,6 +1001,7 @@ static void evdev_disconnect(struct input_handle *handle) > > device_del(&evdev->dev); > evdev_cleanup(evdev); > + input_free_minor(MINOR(evdev->dev.devt)); > input_unregister_handle(handle); > put_device(&evdev->dev); > } > @@ -1050,8 +1017,6 @@ static struct input_handler evdev_handler = { > .event = evdev_event, > .connect = evdev_connect, > .disconnect = evdev_disconnect, > - .fops = &evdev_fops, > - .minor = EVDEV_MINOR_BASE, > .name = "evdev", > .id_table = evdev_ids, > }; > diff --git a/drivers/input/input.c b/drivers/input/input.c > index 768e46b..1869cf1 100644 > --- a/drivers/input/input.c > +++ b/drivers/input/input.c > @@ -14,6 +14,7 @@ > > #include <linux/init.h> > #include <linux/types.h> > +#include <linux/idr.h> > #include <linux/input/mt.h> > #include <linux/module.h> > #include <linux/slab.h> > @@ -32,7 +33,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); > MODULE_DESCRIPTION("Input core"); > MODULE_LICENSE("GPL"); > > -#define INPUT_DEVICES 256 > +#define INPUT_MAX_CHAR_DEVICES 1024 > +#define INPUT_FIRST_DYNAMIC_DEV 256 Maybe we should have some comment which explains that there were historically 8 statically assigned blocks of 32 minors here. Moreover, I think we can actually decrease that value, can't we? I think only 3 blocks were really used so using EVDEV_MINOR_BASE+32 = 96 would avoid allocating a "huge" unused range in the IDA/IDR array. > +static DEFINE_IDA(input_ida); > > static LIST_HEAD(input_dev_list); > static LIST_HEAD(input_handler_list); > @@ -45,8 +48,6 @@ static LIST_HEAD(input_handler_list); > */ > static DEFINE_MUTEX(input_mutex); > > -static struct input_handler *input_table[8]; > - > static inline int is_event_supported(unsigned int code, > unsigned long *bm, unsigned int max) > { > @@ -1144,8 +1145,6 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) > seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); > if (handler->filter) > seq_puts(seq, " (filter)"); > - if (handler->fops) > - seq_printf(seq, " Minor=%d", handler->minor); This actually breaks ABI. Can't we put this into a separate patch which is applied before this one so if someone does bisect this, they will get a shorter commit than this one with a clear statement in the commit message? > seq_putc(seq, '\n'); > > return 0; > @@ -1932,22 +1931,14 @@ EXPORT_SYMBOL(input_unregister_device); > int input_register_handler(struct input_handler *handler) > { > struct input_dev *dev; > - int retval; > + int error; > > - retval = mutex_lock_interruptible(&input_mutex); > - if (retval) > - return retval; > + error = mutex_lock_interruptible(&input_mutex); > + if (error) > + return error; Why do you rename the variable here? It's actually just adding noise to the still really long patch. > INIT_LIST_HEAD(&handler->h_list); > > - if (handler->fops != NULL) { > - if (input_table[handler->minor >> 5]) { > - retval = -EBUSY; > - goto out; > - } > - input_table[handler->minor >> 5] = handler; > - } > - > list_add_tail(&handler->node, &input_handler_list); > > list_for_each_entry(dev, &input_dev_list, node) > @@ -1955,9 +1946,8 @@ int input_register_handler(struct input_handler *handler) > > input_wakeup_procfs_readers(); > > - out: > mutex_unlock(&input_mutex); > - return retval; > + return 0; > } > EXPORT_SYMBOL(input_register_handler); > > @@ -1980,9 +1970,6 @@ void input_unregister_handler(struct input_handler *handler) > > list_del_init(&handler->node); > > - if (handler->fops != NULL) > - input_table[handler->minor >> 5] = NULL; > - > input_wakeup_procfs_readers(); > > mutex_unlock(&input_mutex); > @@ -2099,51 +2086,52 @@ void input_unregister_handle(struct input_handle *handle) > } > EXPORT_SYMBOL(input_unregister_handle); > > -static int input_open_file(struct inode *inode, struct file *file) > +/** > + * input_get_new_minor - allocates a new input minor number > + * @legacy_base: beginning or the legacy range to be searched "... or -1 if not available" or something like that. > + * @legacy_num: size of legacy range > + * @allow_dynamic: whether we can also take ID from the dynamic range > + * > + * This function allocates a new device minor for from input major namespace. > + * Caller can request legacy minor by specifying @legacy_base and @legacy_num > + * parameters and whether ID can be allocated from dynamic range if there are > + * no free IDs in legacy range. > + */ > +int input_get_new_minor(int legacy_base, unsigned int legacy_num, > + bool allow_dynamic) > { > - struct input_handler *handler; > - const struct file_operations *old_fops, *new_fops = NULL; > - int err; > - > - err = mutex_lock_interruptible(&input_mutex); > - if (err) > - return err; > - > - /* No load-on-demand here? */ > - handler = input_table[iminor(inode) >> 5]; > - if (handler) > - new_fops = fops_get(handler->fops); > - > - mutex_unlock(&input_mutex); > - > /* > - * That's _really_ odd. Usually NULL ->open means "nothing special", > - * not "no device". Oh, well... > + * This function should be called from input handler's ->connect() > + * methods, which are serialized with input_mutex, so no additional > + * locking is needed here. > */ > - if (!new_fops || !new_fops->open) { > - fops_put(new_fops); > - err = -ENODEV; > - goto out; > + if (legacy_base >= 0) { > + int minor = ida_simple_get(&input_ida, > + legacy_base, > + legacy_base + legacy_num, > + GFP_KERNEL); > + if (minor >= 0 || !allow_dynamic) > + return minor; > } > > - old_fops = file->f_op; > - file->f_op = new_fops; > - > - err = new_fops->open(inode, file); > - if (err) { > - fops_put(file->f_op); > - file->f_op = fops_get(old_fops); > - } > - fops_put(old_fops); > -out: > - return err; > + return ida_simple_get(&input_ida, > + INPUT_FIRST_DYNAMIC_DEV, INPUT_MAX_CHAR_DEVICES, > + GFP_KERNEL); > } > +EXPORT_SYMBOL(input_get_new_minor); > > -static const struct file_operations input_fops = { > - .owner = THIS_MODULE, > - .open = input_open_file, > - .llseek = noop_llseek, > -}; > +/** > + * input_free_minor - release previously allocated minor > + * @minor: minor to be released > + * > + * This function releases previously allocated input minor so that it can be > + * reused later. > + */ > +void input_free_minor(unsigned int minor) > +{ > + ida_simple_remove(&input_ida, minor); > +} > +EXPORT_SYMBOL(input_free_minor); > > static int __init input_init(void) > { > @@ -2159,7 +2147,8 @@ static int __init input_init(void) > if (err) > goto fail1; > > - err = register_chrdev(INPUT_MAJOR, "input", &input_fops); > + err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0), > + INPUT_MAX_CHAR_DEVICES, "input"); > if (err) { > pr_err("unable to register char major %d", INPUT_MAJOR); > goto fail2; > @@ -2175,7 +2164,8 @@ static int __init input_init(void) > static void __exit input_exit(void) > { > input_proc_exit(); > - unregister_chrdev(INPUT_MAJOR, "input"); > + unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0), > + INPUT_MAX_CHAR_DEVICES); > class_unregister(&input_class); > } I haven't actually tested it, yet, but I will give it a try later this weekend (and also review the rest of it). But it looks definitely nicer than my approach. Thanks! I also didn't find any races with evdev.cdev and evdev.dev. The user-space semantics are the same as with my patch. That's nice, too. Thanks a lot! Maybe we can even get this into 3.7? Regards David ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] input: Dynamic Minor Numbers 2012-09-21 9:22 ` David Herrmann @ 2012-09-21 19:18 ` David Herrmann 2012-09-21 20:51 ` Dmitry Torokhov 0 siblings, 1 reply; 10+ messages in thread From: David Herrmann @ 2012-09-21 19:18 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: linux-input, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1421 bytes --] Hi Dmitry On Fri, Sep 21, 2012 at 11:22 AM, David Herrmann <dh.herrmann@googlemail.com> wrote: > Hi Dmitry > > On Fri, Sep 21, 2012 at 10:07 AM, Dmitry Torokhov > <dmitry.torokhov@gmail.com> wrote: >> Thank you very much for working on this, unfortunately your patch extends the >> existing infrastructure handling of character devices in input core, >> which is quite rigid and sub-optimal. >> >> For a while now I wanted to stop input core from pre-creating character >> devices and multiplexing file operations and instead push more chardev >> handling tasks into individual input handlers and make they more >> independent from input core. So while I won't be taking your patch as is >> it was a great motivator to finally do something about current >> limitation and I would appreciate if you could take a look at the patch >> below and see if you have any issues with it. > > I didn't know why we did that, anyway. But I tried to keep that logic, > even though it is really weird. So I am quite glad that you fixed it. Sorry, compiling a kernel takes 44m here so I haven't had time earlier this day. But I just recompiled with your patch and it works like a charm. I have attached output of "ls -la /dev/input" with 900 uinput devices. Performance does suck but that is definitely another issue. So here's my: Tested-by: David Herrmann <dh.herrmann@googlemail.com> I will review the rest tomorrow. Cheers David [-- Attachment #2: lx_output --] [-- Type: application/octet-stream, Size: 43732 bytes --] total 0 drwxr-xr-x 3 root root 15620 Sep 21 20:43 . drwxr-xr-x 14 root root 3000 Sep 21 20:42 .. drwxr-xr-x 2 root root 100 Sep 21 20:42 by-path crw-rw---- 1 root input 13, 64 Sep 21 20:42 event0 crw-rw---- 1 root input 13, 65 Sep 21 20:42 event1 crw-rw---- 1 root input 13, 1000 Sep 21 20:43 event1000 crw-rw---- 1 root input 13, 1001 Sep 21 20:43 event1001 crw-rw---- 1 root input 13, 1002 Sep 21 20:43 event1002 crw-rw---- 1 root input 13, 1003 Sep 21 20:43 event1003 crw-rw---- 1 root input 13, 1004 Sep 21 20:43 event1004 crw-rw---- 1 root input 13, 1005 Sep 21 20:43 event1005 crw-rw---- 1 root input 13, 1006 Sep 21 20:43 event1006 crw-rw---- 1 root input 13, 1007 Sep 21 20:43 event1007 crw-rw---- 1 root input 13, 1008 Sep 21 20:43 event1008 crw-rw---- 1 root input 13, 1009 Sep 21 20:43 event1009 crw-rw---- 1 root input 13, 1010 Sep 21 20:43 event1010 crw-rw---- 1 root input 13, 1011 Sep 21 20:43 event1011 crw-rw---- 1 root input 13, 1012 Sep 21 20:43 event1012 crw-rw---- 1 root input 13, 1013 Sep 21 20:43 event1013 crw-rw---- 1 root input 13, 1014 Sep 21 20:43 event1014 crw-rw---- 1 root input 13, 1015 Sep 21 20:43 event1015 crw-rw---- 1 root input 13, 1016 Sep 21 20:43 event1016 crw-rw---- 1 root input 13, 1017 Sep 21 20:43 event1017 crw-rw---- 1 root input 13, 1018 Sep 21 20:43 event1018 crw-rw---- 1 root input 13, 1019 Sep 21 20:43 event1019 crw-rw---- 1 root input 13, 1020 Sep 21 20:43 event1020 crw-rw---- 1 root input 13, 1021 Sep 21 20:43 event1021 crw-rw---- 1 root input 13, 1022 Sep 21 20:43 event1022 crw-rw---- 1 root input 13, 1023 Sep 21 20:43 event1023 crw-rw---- 1 root input 13, 66 Sep 21 20:42 event2 crw-rw---- 1 root input 13, 256 Sep 21 20:43 event256 crw-rw---- 1 root input 13, 257 Sep 21 20:43 event257 crw-rw---- 1 root input 13, 258 Sep 21 20:43 event258 crw-rw---- 1 root input 13, 259 Sep 21 20:43 event259 crw-rw---- 1 root input 13, 260 Sep 21 20:43 event260 crw-rw---- 1 root input 13, 261 Sep 21 20:43 event261 crw-rw---- 1 root input 13, 262 Sep 21 20:43 event262 crw-rw---- 1 root input 13, 263 Sep 21 20:43 event263 crw-rw---- 1 root input 13, 264 Sep 21 20:43 event264 crw-rw---- 1 root input 13, 265 Sep 21 20:43 event265 crw-rw---- 1 root input 13, 266 Sep 21 20:43 event266 crw-rw---- 1 root input 13, 267 Sep 21 20:43 event267 crw-rw---- 1 root input 13, 268 Sep 21 20:43 event268 crw-rw---- 1 root input 13, 269 Sep 21 20:43 event269 crw-rw---- 1 root input 13, 270 Sep 21 20:43 event270 crw-rw---- 1 root input 13, 271 Sep 21 20:43 event271 crw-rw---- 1 root input 13, 272 Sep 21 20:43 event272 crw-rw---- 1 root input 13, 273 Sep 21 20:43 event273 crw-rw---- 1 root input 13, 274 Sep 21 20:43 event274 crw-rw---- 1 root input 13, 275 Sep 21 20:43 event275 crw-rw---- 1 root input 13, 276 Sep 21 20:43 event276 crw-rw---- 1 root input 13, 277 Sep 21 20:43 event277 crw-rw---- 1 root input 13, 278 Sep 21 20:43 event278 crw-rw---- 1 root input 13, 279 Sep 21 20:43 event279 crw-rw---- 1 root input 13, 280 Sep 21 20:43 event280 crw-rw---- 1 root input 13, 281 Sep 21 20:43 event281 crw-rw---- 1 root input 13, 282 Sep 21 20:43 event282 crw-rw---- 1 root input 13, 283 Sep 21 20:43 event283 crw-rw---- 1 root input 13, 284 Sep 21 20:43 event284 crw-rw---- 1 root input 13, 285 Sep 21 20:43 event285 crw-rw---- 1 root input 13, 286 Sep 21 20:43 event286 crw-rw---- 1 root input 13, 287 Sep 21 20:43 event287 crw-rw---- 1 root input 13, 288 Sep 21 20:43 event288 crw-rw---- 1 root input 13, 289 Sep 21 20:43 event289 crw-rw---- 1 root input 13, 290 Sep 21 20:43 event290 crw-rw---- 1 root input 13, 291 Sep 21 20:43 event291 crw-rw---- 1 root input 13, 292 Sep 21 20:43 event292 crw-rw---- 1 root input 13, 293 Sep 21 20:43 event293 crw-rw---- 1 root input 13, 294 Sep 21 20:43 event294 crw-rw---- 1 root input 13, 295 Sep 21 20:43 event295 crw-rw---- 1 root input 13, 296 Sep 21 20:43 event296 crw-rw---- 1 root input 13, 297 Sep 21 20:43 event297 crw-rw---- 1 root input 13, 298 Sep 21 20:43 event298 crw-rw---- 1 root input 13, 299 Sep 21 20:43 event299 crw-rw---- 1 root input 13, 67 Sep 21 20:42 event3 crw-rw---- 1 root input 13, 300 Sep 21 20:43 event300 crw-rw---- 1 root input 13, 301 Sep 21 20:43 event301 crw-rw---- 1 root input 13, 302 Sep 21 20:43 event302 crw-rw---- 1 root input 13, 303 Sep 21 20:43 event303 crw-rw---- 1 root input 13, 304 Sep 21 20:43 event304 crw-rw---- 1 root input 13, 305 Sep 21 20:43 event305 crw-rw---- 1 root input 13, 306 Sep 21 20:43 event306 crw-rw---- 1 root input 13, 307 Sep 21 20:43 event307 crw-rw---- 1 root input 13, 308 Sep 21 20:43 event308 crw-rw---- 1 root input 13, 309 Sep 21 20:43 event309 crw-rw---- 1 root input 13, 310 Sep 21 20:43 event310 crw-rw---- 1 root input 13, 311 Sep 21 20:43 event311 crw-rw---- 1 root input 13, 312 Sep 21 20:43 event312 crw-rw---- 1 root input 13, 313 Sep 21 20:43 event313 crw-rw---- 1 root input 13, 314 Sep 21 20:43 event314 crw-rw---- 1 root input 13, 315 Sep 21 20:43 event315 crw-rw---- 1 root input 13, 316 Sep 21 20:43 event316 crw-rw---- 1 root input 13, 317 Sep 21 20:43 event317 crw-rw---- 1 root input 13, 318 Sep 21 20:43 event318 crw-rw---- 1 root input 13, 319 Sep 21 20:43 event319 crw-rw---- 1 root input 13, 320 Sep 21 20:43 event320 crw-rw---- 1 root input 13, 321 Sep 21 20:43 event321 crw-rw---- 1 root input 13, 322 Sep 21 20:43 event322 crw-rw---- 1 root input 13, 323 Sep 21 20:43 event323 crw-rw---- 1 root input 13, 324 Sep 21 20:43 event324 crw-rw---- 1 root input 13, 325 Sep 21 20:43 event325 crw-rw---- 1 root input 13, 326 Sep 21 20:43 event326 crw-rw---- 1 root input 13, 327 Sep 21 20:43 event327 crw-rw---- 1 root input 13, 328 Sep 21 20:43 event328 crw-rw---- 1 root input 13, 329 Sep 21 20:43 event329 crw-rw---- 1 root input 13, 330 Sep 21 20:43 event330 crw-rw---- 1 root input 13, 331 Sep 21 20:43 event331 crw-rw---- 1 root input 13, 332 Sep 21 20:43 event332 crw-rw---- 1 root input 13, 333 Sep 21 20:43 event333 crw-rw---- 1 root input 13, 334 Sep 21 20:43 event334 crw-rw---- 1 root input 13, 335 Sep 21 20:43 event335 crw-rw---- 1 root input 13, 336 Sep 21 20:43 event336 crw-rw---- 1 root input 13, 337 Sep 21 20:43 event337 crw-rw---- 1 root input 13, 338 Sep 21 20:43 event338 crw-rw---- 1 root input 13, 339 Sep 21 20:43 event339 crw-rw---- 1 root input 13, 340 Sep 21 20:43 event340 crw-rw---- 1 root input 13, 341 Sep 21 20:43 event341 crw-rw---- 1 root input 13, 342 Sep 21 20:43 event342 crw-rw---- 1 root input 13, 343 Sep 21 20:43 event343 crw-rw---- 1 root input 13, 344 Sep 21 20:43 event344 crw-rw---- 1 root input 13, 345 Sep 21 20:43 event345 crw-rw---- 1 root input 13, 346 Sep 21 20:43 event346 crw-rw---- 1 root input 13, 347 Sep 21 20:43 event347 crw-rw---- 1 root input 13, 348 Sep 21 20:43 event348 crw-rw---- 1 root input 13, 349 Sep 21 20:43 event349 crw-rw---- 1 root input 13, 350 Sep 21 20:43 event350 crw-rw---- 1 root input 13, 351 Sep 21 20:43 event351 crw-rw---- 1 root input 13, 352 Sep 21 20:43 event352 crw-rw---- 1 root input 13, 353 Sep 21 20:43 event353 crw-rw---- 1 root input 13, 354 Sep 21 20:43 event354 crw-rw---- 1 root input 13, 355 Sep 21 20:43 event355 crw-rw---- 1 root input 13, 356 Sep 21 20:43 event356 crw-rw---- 1 root input 13, 357 Sep 21 20:43 event357 crw-rw---- 1 root input 13, 358 Sep 21 20:43 event358 crw-rw---- 1 root input 13, 359 Sep 21 20:43 event359 crw-rw---- 1 root input 13, 360 Sep 21 20:43 event360 crw-rw---- 1 root input 13, 361 Sep 21 20:43 event361 crw-rw---- 1 root input 13, 362 Sep 21 20:43 event362 crw-rw---- 1 root input 13, 363 Sep 21 20:43 event363 crw-rw---- 1 root input 13, 364 Sep 21 20:43 event364 crw-rw---- 1 root input 13, 365 Sep 21 20:43 event365 crw-rw---- 1 root input 13, 366 Sep 21 20:43 event366 crw-rw---- 1 root input 13, 367 Sep 21 20:43 event367 crw-rw---- 1 root input 13, 368 Sep 21 20:43 event368 crw-rw---- 1 root input 13, 369 Sep 21 20:43 event369 crw-rw---- 1 root input 13, 370 Sep 21 20:43 event370 crw-rw---- 1 root input 13, 371 Sep 21 20:43 event371 crw-rw---- 1 root input 13, 372 Sep 21 20:43 event372 crw-rw---- 1 root input 13, 373 Sep 21 20:43 event373 crw-rw---- 1 root input 13, 374 Sep 21 20:43 event374 crw-rw---- 1 root input 13, 375 Sep 21 20:43 event375 crw-rw---- 1 root input 13, 376 Sep 21 20:43 event376 crw-rw---- 1 root input 13, 377 Sep 21 20:43 event377 crw-rw---- 1 root input 13, 378 Sep 21 20:43 event378 crw-rw---- 1 root input 13, 379 Sep 21 20:43 event379 crw-rw---- 1 root input 13, 380 Sep 21 20:43 event380 crw-rw---- 1 root input 13, 381 Sep 21 20:43 event381 crw-rw---- 1 root input 13, 382 Sep 21 20:43 event382 crw-rw---- 1 root input 13, 383 Sep 21 20:43 event383 crw-rw---- 1 root input 13, 384 Sep 21 20:43 event384 crw-rw---- 1 root input 13, 385 Sep 21 20:43 event385 crw-rw---- 1 root input 13, 386 Sep 21 20:43 event386 crw-rw---- 1 root input 13, 387 Sep 21 20:43 event387 crw-rw---- 1 root input 13, 388 Sep 21 20:43 event388 crw-rw---- 1 root input 13, 389 Sep 21 20:43 event389 crw-rw---- 1 root input 13, 390 Sep 21 20:43 event390 crw-rw---- 1 root input 13, 391 Sep 21 20:43 event391 crw-rw---- 1 root input 13, 392 Sep 21 20:43 event392 crw-rw---- 1 root input 13, 393 Sep 21 20:43 event393 crw-rw---- 1 root input 13, 394 Sep 21 20:43 event394 crw-rw---- 1 root input 13, 395 Sep 21 20:43 event395 crw-rw---- 1 root input 13, 396 Sep 21 20:43 event396 crw-rw---- 1 root input 13, 397 Sep 21 20:43 event397 crw-rw---- 1 root input 13, 398 Sep 21 20:43 event398 crw-rw---- 1 root input 13, 399 Sep 21 20:43 event399 crw-rw---- 1 root input 13, 68 Sep 21 20:42 event4 crw-rw---- 1 root input 13, 400 Sep 21 20:43 event400 crw-rw---- 1 root input 13, 401 Sep 21 20:43 event401 crw-rw---- 1 root input 13, 402 Sep 21 20:43 event402 crw-rw---- 1 root input 13, 403 Sep 21 20:43 event403 crw-rw---- 1 root input 13, 404 Sep 21 20:43 event404 crw-rw---- 1 root input 13, 405 Sep 21 20:43 event405 crw-rw---- 1 root input 13, 406 Sep 21 20:43 event406 crw-rw---- 1 root input 13, 407 Sep 21 20:43 event407 crw-rw---- 1 root input 13, 408 Sep 21 20:43 event408 crw-rw---- 1 root input 13, 409 Sep 21 20:43 event409 crw-rw---- 1 root input 13, 410 Sep 21 20:43 event410 crw-rw---- 1 root input 13, 411 Sep 21 20:43 event411 crw-rw---- 1 root input 13, 412 Sep 21 20:43 event412 crw-rw---- 1 root input 13, 413 Sep 21 20:43 event413 crw-rw---- 1 root input 13, 414 Sep 21 20:43 event414 crw-rw---- 1 root input 13, 415 Sep 21 20:43 event415 crw-rw---- 1 root input 13, 416 Sep 21 20:43 event416 crw-rw---- 1 root input 13, 417 Sep 21 20:43 event417 crw-rw---- 1 root input 13, 418 Sep 21 20:43 event418 crw-rw---- 1 root input 13, 419 Sep 21 20:43 event419 crw-rw---- 1 root input 13, 420 Sep 21 20:43 event420 crw-rw---- 1 root input 13, 421 Sep 21 20:43 event421 crw-rw---- 1 root input 13, 422 Sep 21 20:43 event422 crw-rw---- 1 root input 13, 423 Sep 21 20:43 event423 crw-rw---- 1 root input 13, 424 Sep 21 20:43 event424 crw-rw---- 1 root input 13, 425 Sep 21 20:43 event425 crw-rw---- 1 root input 13, 426 Sep 21 20:43 event426 crw-rw---- 1 root input 13, 427 Sep 21 20:43 event427 crw-rw---- 1 root input 13, 428 Sep 21 20:43 event428 crw-rw---- 1 root input 13, 429 Sep 21 20:43 event429 crw-rw---- 1 root input 13, 430 Sep 21 20:43 event430 crw-rw---- 1 root input 13, 431 Sep 21 20:43 event431 crw-rw---- 1 root input 13, 432 Sep 21 20:43 event432 crw-rw---- 1 root input 13, 433 Sep 21 20:43 event433 crw-rw---- 1 root input 13, 434 Sep 21 20:43 event434 crw-rw---- 1 root input 13, 435 Sep 21 20:43 event435 crw-rw---- 1 root input 13, 436 Sep 21 20:43 event436 crw-rw---- 1 root input 13, 437 Sep 21 20:43 event437 crw-rw---- 1 root input 13, 438 Sep 21 20:43 event438 crw-rw---- 1 root input 13, 439 Sep 21 20:43 event439 crw-rw---- 1 root input 13, 440 Sep 21 20:43 event440 crw-rw---- 1 root input 13, 441 Sep 21 20:43 event441 crw-rw---- 1 root input 13, 442 Sep 21 20:43 event442 crw-rw---- 1 root input 13, 443 Sep 21 20:43 event443 crw-rw---- 1 root input 13, 444 Sep 21 20:43 event444 crw-rw---- 1 root input 13, 445 Sep 21 20:43 event445 crw-rw---- 1 root input 13, 446 Sep 21 20:43 event446 crw-rw---- 1 root input 13, 447 Sep 21 20:43 event447 crw-rw---- 1 root input 13, 448 Sep 21 20:43 event448 crw-rw---- 1 root input 13, 449 Sep 21 20:43 event449 crw-rw---- 1 root input 13, 450 Sep 21 20:43 event450 crw-rw---- 1 root input 13, 451 Sep 21 20:43 event451 crw-rw---- 1 root input 13, 452 Sep 21 20:43 event452 crw-rw---- 1 root input 13, 453 Sep 21 20:43 event453 crw-rw---- 1 root input 13, 454 Sep 21 20:43 event454 crw-rw---- 1 root input 13, 455 Sep 21 20:43 event455 crw-rw---- 1 root input 13, 456 Sep 21 20:43 event456 crw-rw---- 1 root input 13, 457 Sep 21 20:43 event457 crw-rw---- 1 root input 13, 458 Sep 21 20:43 event458 crw-rw---- 1 root input 13, 459 Sep 21 20:43 event459 crw-rw---- 1 root input 13, 460 Sep 21 20:43 event460 crw-rw---- 1 root input 13, 461 Sep 21 20:43 event461 crw-rw---- 1 root input 13, 462 Sep 21 20:43 event462 crw-rw---- 1 root input 13, 463 Sep 21 20:43 event463 crw-rw---- 1 root input 13, 464 Sep 21 20:43 event464 crw-rw---- 1 root input 13, 465 Sep 21 20:43 event465 crw-rw---- 1 root input 13, 466 Sep 21 20:43 event466 crw-rw---- 1 root input 13, 467 Sep 21 20:43 event467 crw-rw---- 1 root input 13, 468 Sep 21 20:43 event468 crw-rw---- 1 root input 13, 469 Sep 21 20:43 event469 crw-rw---- 1 root input 13, 470 Sep 21 20:43 event470 crw-rw---- 1 root input 13, 471 Sep 21 20:43 event471 crw-rw---- 1 root input 13, 472 Sep 21 20:43 event472 crw-rw---- 1 root input 13, 473 Sep 21 20:43 event473 crw-rw---- 1 root input 13, 474 Sep 21 20:43 event474 crw-rw---- 1 root input 13, 475 Sep 21 20:43 event475 crw-rw---- 1 root input 13, 476 Sep 21 20:43 event476 crw-rw---- 1 root input 13, 477 Sep 21 20:43 event477 crw-rw---- 1 root input 13, 478 Sep 21 20:43 event478 crw-rw---- 1 root input 13, 479 Sep 21 20:43 event479 crw-rw---- 1 root input 13, 480 Sep 21 20:43 event480 crw-rw---- 1 root input 13, 481 Sep 21 20:43 event481 crw-rw---- 1 root input 13, 482 Sep 21 20:43 event482 crw-rw---- 1 root input 13, 483 Sep 21 20:43 event483 crw-rw---- 1 root input 13, 484 Sep 21 20:43 event484 crw-rw---- 1 root input 13, 485 Sep 21 20:43 event485 crw-rw---- 1 root input 13, 486 Sep 21 20:43 event486 crw-rw---- 1 root input 13, 487 Sep 21 20:43 event487 crw-rw---- 1 root input 13, 488 Sep 21 20:43 event488 crw-rw---- 1 root input 13, 489 Sep 21 20:43 event489 crw-rw---- 1 root input 13, 490 Sep 21 20:43 event490 crw-rw---- 1 root input 13, 491 Sep 21 20:43 event491 crw-rw---- 1 root input 13, 492 Sep 21 20:43 event492 crw-rw---- 1 root input 13, 493 Sep 21 20:43 event493 crw-rw---- 1 root input 13, 494 Sep 21 20:43 event494 crw-rw---- 1 root input 13, 495 Sep 21 20:43 event495 crw-rw---- 1 root input 13, 496 Sep 21 20:43 event496 crw-rw---- 1 root input 13, 497 Sep 21 20:43 event497 crw-rw---- 1 root input 13, 498 Sep 21 20:43 event498 crw-rw---- 1 root input 13, 499 Sep 21 20:43 event499 crw-rw---- 1 root input 13, 69 Sep 21 20:42 event5 crw-rw---- 1 root input 13, 500 Sep 21 20:43 event500 crw-rw---- 1 root input 13, 501 Sep 21 20:43 event501 crw-rw---- 1 root input 13, 502 Sep 21 20:43 event502 crw-rw---- 1 root input 13, 503 Sep 21 20:43 event503 crw-rw---- 1 root input 13, 504 Sep 21 20:43 event504 crw-rw---- 1 root input 13, 505 Sep 21 20:43 event505 crw-rw---- 1 root input 13, 506 Sep 21 20:43 event506 crw-rw---- 1 root input 13, 507 Sep 21 20:43 event507 crw-rw---- 1 root input 13, 508 Sep 21 20:43 event508 crw-rw---- 1 root input 13, 509 Sep 21 20:43 event509 crw-rw---- 1 root input 13, 510 Sep 21 20:43 event510 crw-rw---- 1 root input 13, 511 Sep 21 20:43 event511 crw-rw---- 1 root input 13, 512 Sep 21 20:43 event512 crw-rw---- 1 root input 13, 513 Sep 21 20:43 event513 crw-rw---- 1 root input 13, 514 Sep 21 20:43 event514 crw-rw---- 1 root input 13, 515 Sep 21 20:43 event515 crw-rw---- 1 root input 13, 516 Sep 21 20:43 event516 crw-rw---- 1 root input 13, 517 Sep 21 20:43 event517 crw-rw---- 1 root input 13, 518 Sep 21 20:43 event518 crw-rw---- 1 root input 13, 519 Sep 21 20:43 event519 crw-rw---- 1 root input 13, 520 Sep 21 20:43 event520 crw-rw---- 1 root input 13, 521 Sep 21 20:43 event521 crw-rw---- 1 root input 13, 522 Sep 21 20:43 event522 crw-rw---- 1 root input 13, 523 Sep 21 20:43 event523 crw-rw---- 1 root input 13, 524 Sep 21 20:43 event524 crw-rw---- 1 root input 13, 525 Sep 21 20:43 event525 crw-rw---- 1 root input 13, 526 Sep 21 20:43 event526 crw-rw---- 1 root input 13, 527 Sep 21 20:43 event527 crw-rw---- 1 root input 13, 528 Sep 21 20:43 event528 crw-rw---- 1 root input 13, 529 Sep 21 20:43 event529 crw-rw---- 1 root input 13, 530 Sep 21 20:43 event530 crw-rw---- 1 root input 13, 531 Sep 21 20:43 event531 crw-rw---- 1 root input 13, 532 Sep 21 20:43 event532 crw-rw---- 1 root input 13, 533 Sep 21 20:43 event533 crw-rw---- 1 root input 13, 534 Sep 21 20:43 event534 crw-rw---- 1 root input 13, 535 Sep 21 20:43 event535 crw-rw---- 1 root input 13, 536 Sep 21 20:43 event536 crw-rw---- 1 root input 13, 537 Sep 21 20:43 event537 crw-rw---- 1 root input 13, 538 Sep 21 20:43 event538 crw-rw---- 1 root input 13, 539 Sep 21 20:43 event539 crw-rw---- 1 root input 13, 540 Sep 21 20:43 event540 crw-rw---- 1 root input 13, 541 Sep 21 20:43 event541 crw-rw---- 1 root input 13, 542 Sep 21 20:43 event542 crw-rw---- 1 root input 13, 543 Sep 21 20:43 event543 crw-rw---- 1 root input 13, 544 Sep 21 20:43 event544 crw-rw---- 1 root input 13, 545 Sep 21 20:43 event545 crw-rw---- 1 root input 13, 546 Sep 21 20:43 event546 crw-rw---- 1 root input 13, 547 Sep 21 20:43 event547 crw-rw---- 1 root input 13, 548 Sep 21 20:43 event548 crw-rw---- 1 root input 13, 549 Sep 21 20:43 event549 crw-rw---- 1 root input 13, 550 Sep 21 20:43 event550 crw-rw---- 1 root input 13, 551 Sep 21 20:43 event551 crw-rw---- 1 root input 13, 552 Sep 21 20:43 event552 crw-rw---- 1 root input 13, 553 Sep 21 20:43 event553 crw-rw---- 1 root input 13, 554 Sep 21 20:43 event554 crw-rw---- 1 root input 13, 555 Sep 21 20:43 event555 crw-rw---- 1 root input 13, 556 Sep 21 20:43 event556 crw-rw---- 1 root input 13, 557 Sep 21 20:43 event557 crw-rw---- 1 root input 13, 558 Sep 21 20:43 event558 crw-rw---- 1 root input 13, 559 Sep 21 20:43 event559 crw-rw---- 1 root input 13, 560 Sep 21 20:43 event560 crw-rw---- 1 root input 13, 561 Sep 21 20:43 event561 crw-rw---- 1 root input 13, 562 Sep 21 20:43 event562 crw-rw---- 1 root input 13, 563 Sep 21 20:43 event563 crw-rw---- 1 root input 13, 564 Sep 21 20:43 event564 crw-rw---- 1 root input 13, 565 Sep 21 20:43 event565 crw-rw---- 1 root input 13, 566 Sep 21 20:43 event566 crw-rw---- 1 root input 13, 567 Sep 21 20:43 event567 crw-rw---- 1 root input 13, 568 Sep 21 20:43 event568 crw-rw---- 1 root input 13, 569 Sep 21 20:43 event569 crw-rw---- 1 root input 13, 570 Sep 21 20:43 event570 crw-rw---- 1 root input 13, 571 Sep 21 20:43 event571 crw-rw---- 1 root input 13, 572 Sep 21 20:43 event572 crw-rw---- 1 root input 13, 573 Sep 21 20:43 event573 crw-rw---- 1 root input 13, 574 Sep 21 20:43 event574 crw-rw---- 1 root input 13, 575 Sep 21 20:43 event575 crw-rw---- 1 root input 13, 576 Sep 21 20:43 event576 crw-rw---- 1 root input 13, 577 Sep 21 20:43 event577 crw-rw---- 1 root input 13, 578 Sep 21 20:43 event578 crw-rw---- 1 root input 13, 579 Sep 21 20:43 event579 crw-rw---- 1 root input 13, 580 Sep 21 20:43 event580 crw-rw---- 1 root input 13, 581 Sep 21 20:43 event581 crw-rw---- 1 root input 13, 582 Sep 21 20:43 event582 crw-rw---- 1 root input 13, 583 Sep 21 20:43 event583 crw-rw---- 1 root input 13, 584 Sep 21 20:43 event584 crw-rw---- 1 root input 13, 585 Sep 21 20:43 event585 crw-rw---- 1 root input 13, 586 Sep 21 20:43 event586 crw-rw---- 1 root input 13, 587 Sep 21 20:43 event587 crw-rw---- 1 root input 13, 588 Sep 21 20:43 event588 crw-rw---- 1 root input 13, 589 Sep 21 20:43 event589 crw-rw---- 1 root input 13, 590 Sep 21 20:43 event590 crw-rw---- 1 root input 13, 591 Sep 21 20:43 event591 crw-rw---- 1 root input 13, 592 Sep 21 20:43 event592 crw-rw---- 1 root input 13, 593 Sep 21 20:43 event593 crw-rw---- 1 root input 13, 594 Sep 21 20:43 event594 crw-rw---- 1 root input 13, 595 Sep 21 20:43 event595 crw-rw---- 1 root input 13, 596 Sep 21 20:43 event596 crw-rw---- 1 root input 13, 597 Sep 21 20:43 event597 crw-rw---- 1 root input 13, 598 Sep 21 20:43 event598 crw-rw---- 1 root input 13, 599 Sep 21 20:43 event599 crw-rw---- 1 root input 13, 70 Sep 21 20:42 event6 crw-rw---- 1 root input 13, 600 Sep 21 20:43 event600 crw-rw---- 1 root input 13, 601 Sep 21 20:43 event601 crw-rw---- 1 root input 13, 602 Sep 21 20:43 event602 crw-rw---- 1 root input 13, 603 Sep 21 20:43 event603 crw-rw---- 1 root input 13, 604 Sep 21 20:43 event604 crw-rw---- 1 root input 13, 605 Sep 21 20:43 event605 crw-rw---- 1 root input 13, 606 Sep 21 20:43 event606 crw-rw---- 1 root input 13, 607 Sep 21 20:43 event607 crw-rw---- 1 root input 13, 608 Sep 21 20:43 event608 crw-rw---- 1 root input 13, 609 Sep 21 20:43 event609 crw-rw---- 1 root input 13, 610 Sep 21 20:43 event610 crw-rw---- 1 root input 13, 611 Sep 21 20:43 event611 crw-rw---- 1 root input 13, 612 Sep 21 20:43 event612 crw-rw---- 1 root input 13, 613 Sep 21 20:43 event613 crw-rw---- 1 root input 13, 614 Sep 21 20:43 event614 crw-rw---- 1 root input 13, 615 Sep 21 20:43 event615 crw-rw---- 1 root input 13, 616 Sep 21 20:43 event616 crw-rw---- 1 root input 13, 617 Sep 21 20:43 event617 crw-rw---- 1 root input 13, 618 Sep 21 20:43 event618 crw-rw---- 1 root input 13, 619 Sep 21 20:43 event619 crw-rw---- 1 root input 13, 620 Sep 21 20:43 event620 crw-rw---- 1 root input 13, 621 Sep 21 20:43 event621 crw-rw---- 1 root input 13, 622 Sep 21 20:43 event622 crw-rw---- 1 root input 13, 623 Sep 21 20:43 event623 crw-rw---- 1 root input 13, 624 Sep 21 20:43 event624 crw-rw---- 1 root input 13, 625 Sep 21 20:43 event625 crw-rw---- 1 root input 13, 626 Sep 21 20:43 event626 crw-rw---- 1 root input 13, 627 Sep 21 20:43 event627 crw-rw---- 1 root input 13, 628 Sep 21 20:43 event628 crw-rw---- 1 root input 13, 629 Sep 21 20:43 event629 crw-rw---- 1 root input 13, 630 Sep 21 20:43 event630 crw-rw---- 1 root input 13, 631 Sep 21 20:43 event631 crw-rw---- 1 root input 13, 632 Sep 21 20:43 event632 crw-rw---- 1 root input 13, 633 Sep 21 20:43 event633 crw-rw---- 1 root input 13, 634 Sep 21 20:43 event634 crw-rw---- 1 root input 13, 635 Sep 21 20:43 event635 crw-rw---- 1 root input 13, 636 Sep 21 20:43 event636 crw-rw---- 1 root input 13, 637 Sep 21 20:43 event637 crw-rw---- 1 root input 13, 638 Sep 21 20:43 event638 crw-rw---- 1 root input 13, 639 Sep 21 20:43 event639 crw-rw---- 1 root input 13, 640 Sep 21 20:43 event640 crw-rw---- 1 root input 13, 641 Sep 21 20:43 event641 crw-rw---- 1 root input 13, 642 Sep 21 20:43 event642 crw-rw---- 1 root input 13, 643 Sep 21 20:43 event643 crw-rw---- 1 root input 13, 644 Sep 21 20:43 event644 crw-rw---- 1 root input 13, 645 Sep 21 20:43 event645 crw-rw---- 1 root input 13, 646 Sep 21 20:43 event646 crw-rw---- 1 root input 13, 647 Sep 21 20:43 event647 crw-rw---- 1 root input 13, 648 Sep 21 20:43 event648 crw-rw---- 1 root input 13, 649 Sep 21 20:43 event649 crw-rw---- 1 root input 13, 650 Sep 21 20:43 event650 crw-rw---- 1 root input 13, 651 Sep 21 20:43 event651 crw-rw---- 1 root input 13, 652 Sep 21 20:43 event652 crw-rw---- 1 root input 13, 653 Sep 21 20:43 event653 crw-rw---- 1 root input 13, 654 Sep 21 20:43 event654 crw-rw---- 1 root input 13, 655 Sep 21 20:43 event655 crw-rw---- 1 root input 13, 656 Sep 21 20:43 event656 crw-rw---- 1 root input 13, 657 Sep 21 20:43 event657 crw-rw---- 1 root input 13, 658 Sep 21 20:43 event658 crw-rw---- 1 root input 13, 659 Sep 21 20:43 event659 crw-rw---- 1 root input 13, 660 Sep 21 20:43 event660 crw-rw---- 1 root input 13, 661 Sep 21 20:43 event661 crw-rw---- 1 root input 13, 662 Sep 21 20:43 event662 crw-rw---- 1 root input 13, 663 Sep 21 20:43 event663 crw-rw---- 1 root input 13, 664 Sep 21 20:43 event664 crw-rw---- 1 root input 13, 665 Sep 21 20:43 event665 crw-rw---- 1 root input 13, 666 Sep 21 20:43 event666 crw-rw---- 1 root input 13, 667 Sep 21 20:43 event667 crw-rw---- 1 root input 13, 668 Sep 21 20:43 event668 crw-rw---- 1 root input 13, 669 Sep 21 20:43 event669 crw-rw---- 1 root input 13, 670 Sep 21 20:43 event670 crw-rw---- 1 root input 13, 671 Sep 21 20:43 event671 crw-rw---- 1 root input 13, 672 Sep 21 20:43 event672 crw-rw---- 1 root input 13, 673 Sep 21 20:43 event673 crw-rw---- 1 root input 13, 674 Sep 21 20:43 event674 crw-rw---- 1 root input 13, 675 Sep 21 20:43 event675 crw-rw---- 1 root input 13, 676 Sep 21 20:43 event676 crw-rw---- 1 root input 13, 677 Sep 21 20:43 event677 crw-rw---- 1 root input 13, 678 Sep 21 20:43 event678 crw-rw---- 1 root input 13, 679 Sep 21 20:43 event679 crw-rw---- 1 root input 13, 680 Sep 21 20:43 event680 crw-rw---- 1 root input 13, 681 Sep 21 20:43 event681 crw-rw---- 1 root input 13, 682 Sep 21 20:43 event682 crw-rw---- 1 root input 13, 683 Sep 21 20:43 event683 crw-rw---- 1 root input 13, 684 Sep 21 20:43 event684 crw-rw---- 1 root input 13, 685 Sep 21 20:43 event685 crw-rw---- 1 root input 13, 686 Sep 21 20:43 event686 crw-rw---- 1 root input 13, 687 Sep 21 20:43 event687 crw-rw---- 1 root input 13, 688 Sep 21 20:43 event688 crw-rw---- 1 root input 13, 689 Sep 21 20:43 event689 crw-rw---- 1 root input 13, 690 Sep 21 20:43 event690 crw-rw---- 1 root input 13, 691 Sep 21 20:43 event691 crw-rw---- 1 root input 13, 692 Sep 21 20:43 event692 crw-rw---- 1 root input 13, 693 Sep 21 20:43 event693 crw-rw---- 1 root input 13, 694 Sep 21 20:43 event694 crw-rw---- 1 root input 13, 695 Sep 21 20:43 event695 crw-rw---- 1 root input 13, 696 Sep 21 20:43 event696 crw-rw---- 1 root input 13, 697 Sep 21 20:43 event697 crw-rw---- 1 root input 13, 698 Sep 21 20:43 event698 crw-rw---- 1 root input 13, 699 Sep 21 20:43 event699 crw-rw---- 1 root input 13, 71 Sep 21 20:42 event7 crw-rw---- 1 root input 13, 700 Sep 21 20:43 event700 crw-rw---- 1 root input 13, 701 Sep 21 20:43 event701 crw-rw---- 1 root input 13, 702 Sep 21 20:43 event702 crw-rw---- 1 root input 13, 703 Sep 21 20:43 event703 crw-rw---- 1 root input 13, 704 Sep 21 20:43 event704 crw-rw---- 1 root input 13, 705 Sep 21 20:43 event705 crw-rw---- 1 root input 13, 706 Sep 21 20:43 event706 crw-rw---- 1 root input 13, 707 Sep 21 20:43 event707 crw-rw---- 1 root input 13, 708 Sep 21 20:43 event708 crw-rw---- 1 root input 13, 709 Sep 21 20:43 event709 crw-rw---- 1 root input 13, 710 Sep 21 20:43 event710 crw-rw---- 1 root input 13, 711 Sep 21 20:43 event711 crw-rw---- 1 root input 13, 712 Sep 21 20:43 event712 crw-rw---- 1 root input 13, 713 Sep 21 20:43 event713 crw-rw---- 1 root input 13, 714 Sep 21 20:43 event714 crw-rw---- 1 root input 13, 715 Sep 21 20:43 event715 crw-rw---- 1 root input 13, 716 Sep 21 20:43 event716 crw-rw---- 1 root input 13, 717 Sep 21 20:43 event717 crw-rw---- 1 root input 13, 718 Sep 21 20:43 event718 crw-rw---- 1 root input 13, 719 Sep 21 20:43 event719 crw-rw---- 1 root input 13, 720 Sep 21 20:43 event720 crw-rw---- 1 root input 13, 721 Sep 21 20:43 event721 crw-rw---- 1 root input 13, 722 Sep 21 20:43 event722 crw-rw---- 1 root input 13, 723 Sep 21 20:43 event723 crw-rw---- 1 root input 13, 724 Sep 21 20:43 event724 crw-rw---- 1 root input 13, 725 Sep 21 20:43 event725 crw-rw---- 1 root input 13, 726 Sep 21 20:43 event726 crw-rw---- 1 root input 13, 727 Sep 21 20:43 event727 crw-rw---- 1 root input 13, 728 Sep 21 20:43 event728 crw-rw---- 1 root input 13, 729 Sep 21 20:43 event729 crw-rw---- 1 root input 13, 730 Sep 21 20:43 event730 crw-rw---- 1 root input 13, 731 Sep 21 20:43 event731 crw-rw---- 1 root input 13, 732 Sep 21 20:43 event732 crw-rw---- 1 root input 13, 733 Sep 21 20:43 event733 crw-rw---- 1 root input 13, 734 Sep 21 20:43 event734 crw-rw---- 1 root input 13, 735 Sep 21 20:43 event735 crw-rw---- 1 root input 13, 736 Sep 21 20:43 event736 crw-rw---- 1 root input 13, 737 Sep 21 20:43 event737 crw-rw---- 1 root input 13, 738 Sep 21 20:43 event738 crw-rw---- 1 root input 13, 739 Sep 21 20:43 event739 crw-rw---- 1 root input 13, 740 Sep 21 20:43 event740 crw-rw---- 1 root input 13, 741 Sep 21 20:43 event741 crw-rw---- 1 root input 13, 742 Sep 21 20:43 event742 crw-rw---- 1 root input 13, 743 Sep 21 20:43 event743 crw-rw---- 1 root input 13, 744 Sep 21 20:43 event744 crw-rw---- 1 root input 13, 745 Sep 21 20:43 event745 crw-rw---- 1 root input 13, 746 Sep 21 20:43 event746 crw-rw---- 1 root input 13, 747 Sep 21 20:43 event747 crw-rw---- 1 root input 13, 748 Sep 21 20:43 event748 crw-rw---- 1 root input 13, 749 Sep 21 20:43 event749 crw-rw---- 1 root input 13, 750 Sep 21 20:43 event750 crw-rw---- 1 root input 13, 751 Sep 21 20:43 event751 crw-rw---- 1 root input 13, 752 Sep 21 20:43 event752 crw-rw---- 1 root input 13, 753 Sep 21 20:43 event753 crw-rw---- 1 root input 13, 754 Sep 21 20:43 event754 crw-rw---- 1 root input 13, 755 Sep 21 20:43 event755 crw-rw---- 1 root input 13, 756 Sep 21 20:43 event756 crw-rw---- 1 root input 13, 757 Sep 21 20:43 event757 crw-rw---- 1 root input 13, 758 Sep 21 20:43 event758 crw-rw---- 1 root input 13, 759 Sep 21 20:43 event759 crw-rw---- 1 root input 13, 760 Sep 21 20:43 event760 crw-rw---- 1 root input 13, 761 Sep 21 20:43 event761 crw-rw---- 1 root input 13, 762 Sep 21 20:43 event762 crw-rw---- 1 root input 13, 763 Sep 21 20:43 event763 crw-rw---- 1 root input 13, 764 Sep 21 20:43 event764 crw-rw---- 1 root input 13, 765 Sep 21 20:43 event765 crw-rw---- 1 root input 13, 766 Sep 21 20:43 event766 crw-rw---- 1 root input 13, 767 Sep 21 20:43 event767 crw-rw---- 1 root input 13, 768 Sep 21 20:43 event768 crw-rw---- 1 root input 13, 769 Sep 21 20:43 event769 crw-rw---- 1 root input 13, 770 Sep 21 20:43 event770 crw-rw---- 1 root input 13, 771 Sep 21 20:43 event771 crw-rw---- 1 root input 13, 772 Sep 21 20:43 event772 crw-rw---- 1 root input 13, 773 Sep 21 20:43 event773 crw-rw---- 1 root input 13, 774 Sep 21 20:43 event774 crw-rw---- 1 root input 13, 775 Sep 21 20:43 event775 crw-rw---- 1 root input 13, 776 Sep 21 20:43 event776 crw-rw---- 1 root input 13, 777 Sep 21 20:43 event777 crw-rw---- 1 root input 13, 778 Sep 21 20:43 event778 crw-rw---- 1 root input 13, 779 Sep 21 20:43 event779 crw-rw---- 1 root input 13, 780 Sep 21 20:43 event780 crw-rw---- 1 root input 13, 781 Sep 21 20:43 event781 crw-rw---- 1 root input 13, 782 Sep 21 20:43 event782 crw-rw---- 1 root input 13, 783 Sep 21 20:43 event783 crw-rw---- 1 root input 13, 784 Sep 21 20:43 event784 crw-rw---- 1 root input 13, 785 Sep 21 20:43 event785 crw-rw---- 1 root input 13, 786 Sep 21 20:43 event786 crw-rw---- 1 root input 13, 787 Sep 21 20:43 event787 crw-rw---- 1 root input 13, 788 Sep 21 20:43 event788 crw-rw---- 1 root input 13, 789 Sep 21 20:43 event789 crw-rw---- 1 root input 13, 790 Sep 21 20:43 event790 crw-rw---- 1 root input 13, 791 Sep 21 20:43 event791 crw-rw---- 1 root input 13, 792 Sep 21 20:43 event792 crw-rw---- 1 root input 13, 793 Sep 21 20:43 event793 crw-rw---- 1 root input 13, 794 Sep 21 20:43 event794 crw-rw---- 1 root input 13, 795 Sep 21 20:43 event795 crw-rw---- 1 root input 13, 796 Sep 21 20:43 event796 crw-rw---- 1 root input 13, 797 Sep 21 20:43 event797 crw-rw---- 1 root input 13, 798 Sep 21 20:43 event798 crw-rw---- 1 root input 13, 799 Sep 21 20:43 event799 crw-rw---- 1 root input 13, 800 Sep 21 20:43 event800 crw-rw---- 1 root input 13, 801 Sep 21 20:43 event801 crw-rw---- 1 root input 13, 802 Sep 21 20:43 event802 crw-rw---- 1 root input 13, 803 Sep 21 20:43 event803 crw-rw---- 1 root input 13, 804 Sep 21 20:43 event804 crw-rw---- 1 root input 13, 805 Sep 21 20:43 event805 crw-rw---- 1 root input 13, 806 Sep 21 20:43 event806 crw-rw---- 1 root input 13, 807 Sep 21 20:43 event807 crw-rw---- 1 root input 13, 808 Sep 21 20:43 event808 crw-rw---- 1 root input 13, 809 Sep 21 20:43 event809 crw-rw---- 1 root input 13, 810 Sep 21 20:43 event810 crw-rw---- 1 root input 13, 811 Sep 21 20:43 event811 crw-rw---- 1 root input 13, 812 Sep 21 20:43 event812 crw-rw---- 1 root input 13, 813 Sep 21 20:43 event813 crw-rw---- 1 root input 13, 814 Sep 21 20:43 event814 crw-rw---- 1 root input 13, 815 Sep 21 20:43 event815 crw-rw---- 1 root input 13, 816 Sep 21 20:43 event816 crw-rw---- 1 root input 13, 817 Sep 21 20:43 event817 crw-rw---- 1 root input 13, 818 Sep 21 20:43 event818 crw-rw---- 1 root input 13, 819 Sep 21 20:43 event819 crw-rw---- 1 root input 13, 820 Sep 21 20:43 event820 crw-rw---- 1 root input 13, 821 Sep 21 20:43 event821 crw-rw---- 1 root input 13, 822 Sep 21 20:43 event822 crw-rw---- 1 root input 13, 823 Sep 21 20:43 event823 crw-rw---- 1 root input 13, 824 Sep 21 20:43 event824 crw-rw---- 1 root input 13, 825 Sep 21 20:43 event825 crw-rw---- 1 root input 13, 826 Sep 21 20:43 event826 crw-rw---- 1 root input 13, 827 Sep 21 20:43 event827 crw-rw---- 1 root input 13, 828 Sep 21 20:43 event828 crw-rw---- 1 root input 13, 829 Sep 21 20:43 event829 crw-rw---- 1 root input 13, 830 Sep 21 20:43 event830 crw-rw---- 1 root input 13, 831 Sep 21 20:43 event831 crw-rw---- 1 root input 13, 832 Sep 21 20:43 event832 crw-rw---- 1 root input 13, 833 Sep 21 20:43 event833 crw-rw---- 1 root input 13, 834 Sep 21 20:43 event834 crw-rw---- 1 root input 13, 835 Sep 21 20:43 event835 crw-rw---- 1 root input 13, 836 Sep 21 20:43 event836 crw-rw---- 1 root input 13, 837 Sep 21 20:43 event837 crw-rw---- 1 root input 13, 838 Sep 21 20:43 event838 crw-rw---- 1 root input 13, 839 Sep 21 20:43 event839 crw-rw---- 1 root input 13, 840 Sep 21 20:43 event840 crw-rw---- 1 root input 13, 841 Sep 21 20:43 event841 crw-rw---- 1 root input 13, 842 Sep 21 20:43 event842 crw-rw---- 1 root input 13, 843 Sep 21 20:43 event843 crw-rw---- 1 root input 13, 844 Sep 21 20:43 event844 crw-rw---- 1 root input 13, 845 Sep 21 20:43 event845 crw-rw---- 1 root input 13, 846 Sep 21 20:43 event846 crw-rw---- 1 root input 13, 847 Sep 21 20:43 event847 crw-rw---- 1 root input 13, 848 Sep 21 20:43 event848 crw-rw---- 1 root input 13, 849 Sep 21 20:43 event849 crw-rw---- 1 root input 13, 850 Sep 21 20:43 event850 crw-rw---- 1 root input 13, 851 Sep 21 20:43 event851 crw-rw---- 1 root input 13, 852 Sep 21 20:43 event852 crw-rw---- 1 root input 13, 853 Sep 21 20:43 event853 crw-rw---- 1 root input 13, 854 Sep 21 20:43 event854 crw-rw---- 1 root input 13, 855 Sep 21 20:43 event855 crw-rw---- 1 root input 13, 856 Sep 21 20:43 event856 crw-rw---- 1 root input 13, 857 Sep 21 20:43 event857 crw-rw---- 1 root input 13, 858 Sep 21 20:43 event858 crw-rw---- 1 root input 13, 859 Sep 21 20:43 event859 crw-rw---- 1 root input 13, 860 Sep 21 20:43 event860 crw-rw---- 1 root input 13, 861 Sep 21 20:43 event861 crw-rw---- 1 root input 13, 862 Sep 21 20:43 event862 crw-rw---- 1 root input 13, 863 Sep 21 20:43 event863 crw-rw---- 1 root input 13, 864 Sep 21 20:43 event864 crw-rw---- 1 root input 13, 865 Sep 21 20:43 event865 crw-rw---- 1 root input 13, 866 Sep 21 20:43 event866 crw-rw---- 1 root input 13, 867 Sep 21 20:43 event867 crw-rw---- 1 root input 13, 868 Sep 21 20:43 event868 crw-rw---- 1 root input 13, 869 Sep 21 20:43 event869 crw-rw---- 1 root input 13, 870 Sep 21 20:43 event870 crw-rw---- 1 root input 13, 871 Sep 21 20:43 event871 crw-rw---- 1 root input 13, 872 Sep 21 20:43 event872 crw-rw---- 1 root input 13, 873 Sep 21 20:43 event873 crw-rw---- 1 root input 13, 874 Sep 21 20:43 event874 crw-rw---- 1 root input 13, 875 Sep 21 20:43 event875 crw-rw---- 1 root input 13, 876 Sep 21 20:43 event876 crw-rw---- 1 root input 13, 877 Sep 21 20:43 event877 crw-rw---- 1 root input 13, 878 Sep 21 20:43 event878 crw-rw---- 1 root input 13, 879 Sep 21 20:43 event879 crw-rw---- 1 root input 13, 880 Sep 21 20:43 event880 crw-rw---- 1 root input 13, 881 Sep 21 20:43 event881 crw-rw---- 1 root input 13, 882 Sep 21 20:43 event882 crw-rw---- 1 root input 13, 883 Sep 21 20:43 event883 crw-rw---- 1 root input 13, 884 Sep 21 20:43 event884 crw-rw---- 1 root input 13, 885 Sep 21 20:43 event885 crw-rw---- 1 root input 13, 886 Sep 21 20:43 event886 crw-rw---- 1 root input 13, 887 Sep 21 20:43 event887 crw-rw---- 1 root input 13, 888 Sep 21 20:43 event888 crw-rw---- 1 root input 13, 889 Sep 21 20:43 event889 crw-rw---- 1 root input 13, 890 Sep 21 20:43 event890 crw-rw---- 1 root input 13, 891 Sep 21 20:43 event891 crw-rw---- 1 root input 13, 892 Sep 21 20:43 event892 crw-rw---- 1 root input 13, 893 Sep 21 20:43 event893 crw-rw---- 1 root input 13, 894 Sep 21 20:43 event894 crw-rw---- 1 root input 13, 895 Sep 21 20:43 event895 crw-rw---- 1 root input 13, 896 Sep 21 20:43 event896 crw-rw---- 1 root input 13, 897 Sep 21 20:43 event897 crw-rw---- 1 root input 13, 898 Sep 21 20:43 event898 crw-rw---- 1 root input 13, 899 Sep 21 20:43 event899 crw-rw---- 1 root input 13, 900 Sep 21 20:43 event900 crw-rw---- 1 root input 13, 901 Sep 21 20:43 event901 crw-rw---- 1 root input 13, 902 Sep 21 20:43 event902 crw-rw---- 1 root input 13, 903 Sep 21 20:43 event903 crw-rw---- 1 root input 13, 904 Sep 21 20:43 event904 crw-rw---- 1 root input 13, 905 Sep 21 20:43 event905 crw-rw---- 1 root input 13, 906 Sep 21 20:43 event906 crw-rw---- 1 root input 13, 907 Sep 21 20:43 event907 crw-rw---- 1 root input 13, 908 Sep 21 20:43 event908 crw-rw---- 1 root input 13, 909 Sep 21 20:43 event909 crw-rw---- 1 root input 13, 910 Sep 21 20:43 event910 crw-rw---- 1 root input 13, 911 Sep 21 20:43 event911 crw-rw---- 1 root input 13, 912 Sep 21 20:43 event912 crw-rw---- 1 root input 13, 913 Sep 21 20:43 event913 crw-rw---- 1 root input 13, 914 Sep 21 20:43 event914 crw-rw---- 1 root input 13, 915 Sep 21 20:43 event915 crw-rw---- 1 root input 13, 916 Sep 21 20:43 event916 crw-rw---- 1 root input 13, 917 Sep 21 20:43 event917 crw-rw---- 1 root input 13, 918 Sep 21 20:43 event918 crw-rw---- 1 root input 13, 919 Sep 21 20:43 event919 crw-rw---- 1 root input 13, 920 Sep 21 20:43 event920 crw-rw---- 1 root input 13, 921 Sep 21 20:43 event921 crw-rw---- 1 root input 13, 922 Sep 21 20:43 event922 crw-rw---- 1 root input 13, 923 Sep 21 20:43 event923 crw-rw---- 1 root input 13, 924 Sep 21 20:43 event924 crw-rw---- 1 root input 13, 925 Sep 21 20:43 event925 crw-rw---- 1 root input 13, 926 Sep 21 20:43 event926 crw-rw---- 1 root input 13, 927 Sep 21 20:43 event927 crw-rw---- 1 root input 13, 928 Sep 21 20:43 event928 crw-rw---- 1 root input 13, 929 Sep 21 20:43 event929 crw-rw---- 1 root input 13, 930 Sep 21 20:43 event930 crw-rw---- 1 root input 13, 931 Sep 21 20:43 event931 crw-rw---- 1 root input 13, 932 Sep 21 20:43 event932 crw-rw---- 1 root input 13, 933 Sep 21 20:43 event933 crw-rw---- 1 root input 13, 934 Sep 21 20:43 event934 crw-rw---- 1 root input 13, 935 Sep 21 20:43 event935 crw-rw---- 1 root input 13, 936 Sep 21 20:43 event936 crw-rw---- 1 root input 13, 937 Sep 21 20:43 event937 crw-rw---- 1 root input 13, 938 Sep 21 20:43 event938 crw-rw---- 1 root input 13, 939 Sep 21 20:43 event939 crw-rw---- 1 root input 13, 940 Sep 21 20:43 event940 crw-rw---- 1 root input 13, 941 Sep 21 20:43 event941 crw-rw---- 1 root input 13, 942 Sep 21 20:43 event942 crw-rw---- 1 root input 13, 943 Sep 21 20:43 event943 crw-rw---- 1 root input 13, 944 Sep 21 20:43 event944 crw-rw---- 1 root input 13, 945 Sep 21 20:43 event945 crw-rw---- 1 root input 13, 946 Sep 21 20:43 event946 crw-rw---- 1 root input 13, 947 Sep 21 20:43 event947 crw-rw---- 1 root input 13, 948 Sep 21 20:43 event948 crw-rw---- 1 root input 13, 949 Sep 21 20:43 event949 crw-rw---- 1 root input 13, 950 Sep 21 20:43 event950 crw-rw---- 1 root input 13, 951 Sep 21 20:43 event951 crw-rw---- 1 root input 13, 952 Sep 21 20:43 event952 crw-rw---- 1 root input 13, 953 Sep 21 20:43 event953 crw-rw---- 1 root input 13, 954 Sep 21 20:43 event954 crw-rw---- 1 root input 13, 955 Sep 21 20:43 event955 crw-rw---- 1 root input 13, 956 Sep 21 20:43 event956 crw-rw---- 1 root input 13, 957 Sep 21 20:43 event957 crw-rw---- 1 root input 13, 958 Sep 21 20:43 event958 crw-rw---- 1 root input 13, 959 Sep 21 20:43 event959 crw-rw---- 1 root input 13, 960 Sep 21 20:43 event960 crw-rw---- 1 root input 13, 961 Sep 21 20:43 event961 crw-rw---- 1 root input 13, 962 Sep 21 20:43 event962 crw-rw---- 1 root input 13, 963 Sep 21 20:43 event963 crw-rw---- 1 root input 13, 964 Sep 21 20:43 event964 crw-rw---- 1 root input 13, 965 Sep 21 20:43 event965 crw-rw---- 1 root input 13, 966 Sep 21 20:43 event966 crw-rw---- 1 root input 13, 967 Sep 21 20:43 event967 crw-rw---- 1 root input 13, 968 Sep 21 20:43 event968 crw-rw---- 1 root input 13, 969 Sep 21 20:43 event969 crw-rw---- 1 root input 13, 970 Sep 21 20:43 event970 crw-rw---- 1 root input 13, 971 Sep 21 20:43 event971 crw-rw---- 1 root input 13, 972 Sep 21 20:43 event972 crw-rw---- 1 root input 13, 973 Sep 21 20:43 event973 crw-rw---- 1 root input 13, 974 Sep 21 20:43 event974 crw-rw---- 1 root input 13, 975 Sep 21 20:43 event975 crw-rw---- 1 root input 13, 976 Sep 21 20:43 event976 crw-rw---- 1 root input 13, 977 Sep 21 20:43 event977 crw-rw---- 1 root input 13, 978 Sep 21 20:43 event978 crw-rw---- 1 root input 13, 979 Sep 21 20:43 event979 crw-rw---- 1 root input 13, 980 Sep 21 20:43 event980 crw-rw---- 1 root input 13, 981 Sep 21 20:43 event981 crw-rw---- 1 root input 13, 982 Sep 21 20:43 event982 crw-rw---- 1 root input 13, 983 Sep 21 20:43 event983 crw-rw---- 1 root input 13, 984 Sep 21 20:43 event984 crw-rw---- 1 root input 13, 985 Sep 21 20:43 event985 crw-rw---- 1 root input 13, 986 Sep 21 20:43 event986 crw-rw---- 1 root input 13, 987 Sep 21 20:43 event987 crw-rw---- 1 root input 13, 988 Sep 21 20:43 event988 crw-rw---- 1 root input 13, 989 Sep 21 20:43 event989 crw-rw---- 1 root input 13, 990 Sep 21 20:43 event990 crw-rw---- 1 root input 13, 991 Sep 21 20:43 event991 crw-rw---- 1 root input 13, 992 Sep 21 20:43 event992 crw-rw---- 1 root input 13, 993 Sep 21 20:43 event993 crw-rw---- 1 root input 13, 994 Sep 21 20:43 event994 crw-rw---- 1 root input 13, 995 Sep 21 20:43 event995 crw-rw---- 1 root input 13, 996 Sep 21 20:43 event996 crw-rw---- 1 root input 13, 997 Sep 21 20:43 event997 crw-rw---- 1 root input 13, 998 Sep 21 20:43 event998 crw-rw---- 1 root input 13, 999 Sep 21 20:43 event999 crw-r----- 1 root root 13, 31 Sep 21 20:42 mice crw-r----- 1 root root 13, 32 Sep 21 20:42 mouse0 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] input: Dynamic Minor Numbers 2012-09-21 19:18 ` David Herrmann @ 2012-09-21 20:51 ` Dmitry Torokhov 2012-09-21 21:32 ` David Herrmann 0 siblings, 1 reply; 10+ messages in thread From: Dmitry Torokhov @ 2012-09-21 20:51 UTC (permalink / raw) To: David Herrmann; +Cc: linux-input, linux-kernel On Friday, September 21, 2012 09:18:00 PM David Herrmann wrote: > Hi Dmitry > > On Fri, Sep 21, 2012 at 11:22 AM, David Herrmann > > <dh.herrmann@googlemail.com> wrote: > > Hi Dmitry > > > > On Fri, Sep 21, 2012 at 10:07 AM, Dmitry Torokhov > > > > <dmitry.torokhov@gmail.com> wrote: > >> Thank you very much for working on this, unfortunately your patch extends > >> the existing infrastructure handling of character devices in input core, > >> which is quite rigid and sub-optimal. > >> > >> For a while now I wanted to stop input core from pre-creating character > >> devices and multiplexing file operations and instead push more chardev > >> handling tasks into individual input handlers and make they more > >> independent from input core. So while I won't be taking your patch as is > >> it was a great motivator to finally do something about current > >> limitation and I would appreciate if you could take a look at the patch > >> below and see if you have any issues with it. > > > > I didn't know why we did that, anyway. But I tried to keep that logic, > > even though it is really weird. So I am quite glad that you fixed it. > > Sorry, compiling a kernel takes 44m here so I haven't had time earlier > this day. But I just recompiled with your patch and it works like a > charm. I have attached output of "ls -la /dev/input" with 900 uinput > devices. Performance does suck but that is definitely another issue. Could you elaborate a bit on this? > > So here's my: > Tested-by: David Herrmann <dh.herrmann@googlemail.com> Thanks for testing! -- Dmitry ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] input: Dynamic Minor Numbers 2012-09-21 20:51 ` Dmitry Torokhov @ 2012-09-21 21:32 ` David Herrmann 0 siblings, 0 replies; 10+ messages in thread From: David Herrmann @ 2012-09-21 21:32 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: linux-input, linux-kernel Hi Dmitry On Fri, Sep 21, 2012 at 10:51 PM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > On Friday, September 21, 2012 09:18:00 PM David Herrmann wrote: >> Hi Dmitry >> >> On Fri, Sep 21, 2012 at 11:22 AM, David Herrmann >> >> <dh.herrmann@googlemail.com> wrote: >> > Hi Dmitry >> > >> > On Fri, Sep 21, 2012 at 10:07 AM, Dmitry Torokhov >> > >> > <dmitry.torokhov@gmail.com> wrote: >> >> Thank you very much for working on this, unfortunately your patch extends >> >> the existing infrastructure handling of character devices in input core, >> >> which is quite rigid and sub-optimal. >> >> >> >> For a while now I wanted to stop input core from pre-creating character >> >> devices and multiplexing file operations and instead push more chardev >> >> handling tasks into individual input handlers and make they more >> >> independent from input core. So while I won't be taking your patch as is >> >> it was a great motivator to finally do something about current >> >> limitation and I would appreciate if you could take a look at the patch >> >> below and see if you have any issues with it. >> > >> > I didn't know why we did that, anyway. But I tried to keep that logic, >> > even though it is really weird. So I am quite glad that you fixed it. >> >> Sorry, compiling a kernel takes 44m here so I haven't had time earlier >> this day. But I just recompiled with your patch and it works like a >> charm. I have attached output of "ls -la /dev/input" with 900 uinput >> devices. Performance does suck but that is definitely another issue. > > Could you elaborate a bit on this? It takes like 2s to create 100 devices. Ok, that's about 500 syscalls. But still, 2s seemed pretty much to me. But that's probably related to uinput. 1000 devices take like 10s here. Also the xserver crashes when connecting more than 40 or 50 devices. It does print "too many devices; ignoring" but there seems to be some error-path bug. I haven't noticed any runtime kernel bugs or runtime performance-drops, though. So as I said, there are some issues, that need to be solved, but they are not related to input-core. (Also, creating 1000 uinput devices doesn't seem like a use-case that we should try to optimize). Regards David ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/3] input: Dynamic Minor Numbers 2012-09-21 8:07 ` [PATCH v2 0/3] input: Dynamic Minor Numbers Dmitry Torokhov 2012-09-21 9:22 ` David Herrmann @ 2012-09-25 8:55 ` David Herrmann 1 sibling, 0 replies; 10+ messages in thread From: David Herrmann @ 2012-09-25 8:55 UTC (permalink / raw) To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Bernie Thompson Hi Dmitry On Fri, Sep 21, 2012 at 10:07 AM, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: [snip] See my previous review > diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c > index f0909ed..c82f76f 100644 > --- a/drivers/input/joydev.c > +++ b/drivers/input/joydev.c > @@ -27,6 +27,7 @@ > #include <linux/poll.h> > #include <linux/init.h> > #include <linux/device.h> > +#include <linux/cdev.h> > > MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); > MODULE_DESCRIPTION("Joystick device interfaces"); > @@ -39,13 +40,13 @@ MODULE_LICENSE("GPL"); > > struct joydev { > int open; > - int minor; > struct input_handle handle; > wait_queue_head_t wait; > struct list_head client_list; > spinlock_t client_lock; /* protects client_list */ > struct mutex mutex; > struct device dev; > + struct cdev cdev; > bool exist; > > struct js_corr corr[ABS_CNT]; > @@ -70,9 +71,6 @@ struct joydev_client { > struct list_head node; > }; > > -static struct joydev *joydev_table[JOYDEV_MINORS]; > -static DEFINE_MUTEX(joydev_table_mutex); > - > static int joydev_correct(int value, struct js_corr *corr) > { > switch (corr->type) { > @@ -252,30 +250,14 @@ static int joydev_release(struct inode *inode, struct file *file) > > static int joydev_open(struct inode *inode, struct file *file) > { > + struct joydev *joydev = > + container_of(inode->i_cdev, struct joydev, cdev); > struct joydev_client *client; > - struct joydev *joydev; > - int i = iminor(inode) - JOYDEV_MINOR_BASE; > int error; > > - if (i >= JOYDEV_MINORS) > - return -ENODEV; > - > - error = mutex_lock_interruptible(&joydev_table_mutex); > - if (error) > - return error; > - joydev = joydev_table[i]; > - if (joydev) > - get_device(&joydev->dev); > - mutex_unlock(&joydev_table_mutex); > - > - if (!joydev) > - return -ENODEV; > - > client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); > - if (!client) { > - error = -ENOMEM; > - goto err_put_joydev; > - } > + if (!client) > + return -ENOMEM; > > spin_lock_init(&client->buffer_lock); > client->joydev = joydev; > @@ -288,13 +270,12 @@ static int joydev_open(struct inode *inode, struct file *file) > file->private_data = client; > nonseekable_open(inode, file); > > + get_device(&joydev->dev); > return 0; > > err_free_client: > joydev_detach_client(joydev, client); > kfree(client); > - err_put_joydev: > - put_device(&joydev->dev); > return error; > } > > @@ -747,19 +728,6 @@ static const struct file_operations joydev_fops = { > .llseek = no_llseek, > }; > > -static int joydev_install_chrdev(struct joydev *joydev) > -{ > - joydev_table[joydev->minor] = joydev; > - return 0; > -} > - > -static void joydev_remove_chrdev(struct joydev *joydev) > -{ > - mutex_lock(&joydev_table_mutex); > - joydev_table[joydev->minor] = NULL; > - mutex_unlock(&joydev_table_mutex); > -} > - > /* > * Mark device non-existent. This disables writes, ioctls and > * prevents new users from opening the device. Already posted > @@ -778,7 +746,8 @@ static void joydev_cleanup(struct joydev *joydev) > > joydev_mark_dead(joydev); > joydev_hangup(joydev); > - joydev_remove_chrdev(joydev); > + > + cdev_del(&joydev->cdev); > > /* joydev is marked dead so no one else accesses joydev->open */ > if (joydev->open) > @@ -803,30 +772,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, > const struct input_device_id *id) > { > struct joydev *joydev; > - int i, j, t, minor; > + int i, j, t, minor, dev_no; > int error; > > - for (minor = 0; minor < JOYDEV_MINORS; minor++) > - if (!joydev_table[minor]) > - break; > - > - if (minor == JOYDEV_MINORS) { > - pr_err("no more free joydev devices\n"); > - return -ENFILE; > + minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true); > + if (minor < 0) { > + error = minor; > + pr_err("failed to reserve new minor: %d\n", error); > + return error; How about: return minor; and avoid the "error = minor;" line? > } > > joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); > - if (!joydev) > - return -ENOMEM; > + if (!joydev) { > + error = -ENOMEM; > + goto err_free_minor; > + } > > INIT_LIST_HEAD(&joydev->client_list); > spin_lock_init(&joydev->client_lock); > mutex_init(&joydev->mutex); > init_waitqueue_head(&joydev->wait); > - > - dev_set_name(&joydev->dev, "js%d", minor); > joydev->exist = true; > - joydev->minor = minor; > + > + dev_no = minor; > + /* Normalize device number if it falls into legacy range */ > + if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS) > + dev_no -= JOYDEV_MINOR_BASE; > + dev_set_name(&joydev->dev, "js%d", dev_no); > > joydev->handle.dev = input_get_device(dev); > joydev->handle.name = dev_name(&joydev->dev); > @@ -880,7 +852,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, > } > } > > - joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); > + joydev->dev.devt = MKDEV(INPUT_MAJOR, minor); > joydev->dev.class = &input_class; > joydev->dev.parent = &dev->dev; > joydev->dev.release = joydev_free; > @@ -890,7 +862,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, > if (error) > goto err_free_joydev; > > - error = joydev_install_chrdev(joydev); > + cdev_init(&joydev->cdev, &joydev_fops); > + error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); > if (error) > goto err_unregister_handle; > > @@ -906,6 +879,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, > input_unregister_handle(&joydev->handle); > err_free_joydev: > put_device(&joydev->dev); > + err_free_minor: > + input_free_minor(minor); > return error; > } > > @@ -915,6 +890,7 @@ static void joydev_disconnect(struct input_handle *handle) > > device_del(&joydev->dev); > joydev_cleanup(joydev); > + input_free_minor(MINOR(joydev->dev.devt)); > input_unregister_handle(handle); > put_device(&joydev->dev); > } > @@ -966,8 +942,6 @@ static struct input_handler joydev_handler = { > .match = joydev_match, > .connect = joydev_connect, > .disconnect = joydev_disconnect, > - .fops = &joydev_fops, > - .minor = JOYDEV_MINOR_BASE, > .name = "joydev", > .id_table = joydev_ids, > }; > diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c > index 964e43d..7fd9d91 100644 > --- a/drivers/input/mousedev.c > +++ b/drivers/input/mousedev.c > @@ -24,10 +24,8 @@ > #include <linux/random.h> > #include <linux/major.h> > #include <linux/device.h> > +#include <linux/cdev.h> > #include <linux/kernel.h> > -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX > -#include <linux/miscdevice.h> > -#endif > > MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); > MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces"); > @@ -61,17 +59,18 @@ struct mousedev_hw_data { > > struct mousedev { > int open; > - int minor; > struct input_handle handle; > wait_queue_head_t wait; > struct list_head client_list; > spinlock_t client_lock; /* protects client_list */ > struct mutex mutex; > struct device dev; > + struct cdev cdev; > bool exist; > + bool is_mixdev; > > struct list_head mixdev_node; > - int mixdev_open; > + bool mixdev_open; Could you keep cleanup/codingstyle-patches separate? It makes review so much easier. This patch is already quite long. Anyway, looks good. > > struct mousedev_hw_data packet; > unsigned int pkt_count; > @@ -114,10 +113,6 @@ struct mousedev_client { > static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; > static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; > > -static struct input_handler mousedev_handler; > - > -static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; > -static DEFINE_MUTEX(mousedev_table_mutex); > static struct mousedev *mousedev_mix; > static LIST_HEAD(mousedev_mix_list); > > @@ -433,7 +428,7 @@ static int mousedev_open_device(struct mousedev *mousedev) > if (retval) > return retval; > > - if (mousedev->minor == MOUSEDEV_MIX) > + if (mousedev->is_mixdev) > mixdev_open_devices(); > else if (!mousedev->exist) > retval = -ENODEV; > @@ -451,7 +446,7 @@ static void mousedev_close_device(struct mousedev *mousedev) > { > mutex_lock(&mousedev->mutex); > > - if (mousedev->minor == MOUSEDEV_MIX) > + if (mousedev->is_mixdev) > mixdev_close_devices(); > else if (mousedev->exist && !--mousedev->open) > input_close_device(&mousedev->handle); > @@ -476,7 +471,7 @@ static void mixdev_open_devices(void) > if (mousedev_open_device(mousedev)) > continue; > > - mousedev->mixdev_open = 1; > + mousedev->mixdev_open = true; > } > } > } > @@ -495,7 +490,7 @@ static void mixdev_close_devices(void) > > list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { > if (mousedev->mixdev_open) { > - mousedev->mixdev_open = 0; > + mousedev->mixdev_open = false; > mousedev_close_device(mousedev); > } > } > @@ -538,35 +533,17 @@ static int mousedev_open(struct inode *inode, struct file *file) > struct mousedev_client *client; > struct mousedev *mousedev; > int error; > - int i; > > #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX > if (imajor(inode) == MISC_MAJOR) > - i = MOUSEDEV_MIX; > + mousedev = mousedev_mix; > else > #endif > - i = iminor(inode) - MOUSEDEV_MINOR_BASE; > - > - if (i >= MOUSEDEV_MINORS) > - return -ENODEV; > - > - error = mutex_lock_interruptible(&mousedev_table_mutex); > - if (error) > - return error; > - > - mousedev = mousedev_table[i]; > - if (mousedev) > - get_device(&mousedev->dev); > - mutex_unlock(&mousedev_table_mutex); > - > - if (!mousedev) > - return -ENODEV; > + mousedev = container_of(inode->i_cdev, struct mousedev, cdev); > > client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); > - if (!client) { > - error = -ENOMEM; > - goto err_put_mousedev; > - } > + if (!client) > + return -ENOMEM; > > spin_lock_init(&client->packet_lock); > client->pos_x = xres / 2; > @@ -579,13 +556,14 @@ static int mousedev_open(struct inode *inode, struct file *file) > goto err_free_client; > > file->private_data = client; > + nonseekable_open(inode, file); > + > + get_device(&mousedev->dev); > return 0; > > err_free_client: > mousedev_detach_client(mousedev, client); > kfree(client); > - err_put_mousedev: > - put_device(&mousedev->dev); > return error; > } > > @@ -785,29 +763,16 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait) > } > > static const struct file_operations mousedev_fops = { > - .owner = THIS_MODULE, > - .read = mousedev_read, > - .write = mousedev_write, > - .poll = mousedev_poll, > - .open = mousedev_open, > - .release = mousedev_release, > - .fasync = mousedev_fasync, > - .llseek = noop_llseek, > + .owner = THIS_MODULE, > + .read = mousedev_read, > + .write = mousedev_write, > + .poll = mousedev_poll, > + .open = mousedev_open, > + .release = mousedev_release, > + .fasync = mousedev_fasync, > + .llseek = noop_llseek, > }; Again some cleanups. > -static int mousedev_install_chrdev(struct mousedev *mousedev) > -{ > - mousedev_table[mousedev->minor] = mousedev; > - return 0; > -} > - > -static void mousedev_remove_chrdev(struct mousedev *mousedev) > -{ > - mutex_lock(&mousedev_table_mutex); > - mousedev_table[mousedev->minor] = NULL; > - mutex_unlock(&mousedev_table_mutex); > -} > - > /* > * Mark device non-existent. This disables writes, ioctls and > * prevents new users from opening the device. Already posted > @@ -842,24 +807,50 @@ static void mousedev_cleanup(struct mousedev *mousedev) > > mousedev_mark_dead(mousedev); > mousedev_hangup(mousedev); > - mousedev_remove_chrdev(mousedev); > + > + cdev_del(&mousedev->cdev); > > /* mousedev is marked dead so no one else accesses mousedev->open */ > if (mousedev->open) > input_close_device(handle); > } > > +static int mousedev_reserve_minor(bool mixdev) > +{ > + int minor; > + > + if (mixdev) { > + minor = input_get_new_minor(MOUSEDEV_MIX, 1, false); > + if (minor < 0) > + pr_err("failed to reserve mixdev minor: %d\n", minor); > + } else { > + minor = input_get_new_minor(MOUSEDEV_MINOR_BASE, > + MOUSEDEV_MINORS, true); > + if (minor < 0) > + pr_err("failed to reserve new minor: %d\n", minor); > + } > + > + return minor; > +} > + > static struct mousedev *mousedev_create(struct input_dev *dev, > struct input_handler *handler, > - int minor) > + bool mixdev) > { > struct mousedev *mousedev; > + int minor; > int error; > > + minor = mousedev_reserve_minor(mixdev); > + if (minor < 0) { > + error = minor; > + goto err_out; > + } > + > mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); > if (!mousedev) { > error = -ENOMEM; > - goto err_out; > + goto err_free_minor; > } > > INIT_LIST_HEAD(&mousedev->client_list); > @@ -867,16 +858,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev, > spin_lock_init(&mousedev->client_lock); > mutex_init(&mousedev->mutex); > lockdep_set_subclass(&mousedev->mutex, > - minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0); > + mixdev ? SINGLE_DEPTH_NESTING : 0); > init_waitqueue_head(&mousedev->wait); > > - if (minor == MOUSEDEV_MIX) > + if (mixdev) { > dev_set_name(&mousedev->dev, "mice"); > - else > - dev_set_name(&mousedev->dev, "mouse%d", minor); > + } else { > + int dev_no = minor; > + /* Normalize device number if it falls into legacy range */ > + if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS) > + dev_no -= MOUSEDEV_MINOR_BASE; > + dev_set_name(&mousedev->dev, "mouse%d", dev_no); > + } > > - mousedev->minor = minor; > mousedev->exist = true; > + mousedev->is_mixdev = mixdev; > mousedev->handle.dev = input_get_device(dev); > mousedev->handle.name = dev_name(&mousedev->dev); > mousedev->handle.handler = handler; > @@ -885,17 +881,18 @@ static struct mousedev *mousedev_create(struct input_dev *dev, > mousedev->dev.class = &input_class; > if (dev) > mousedev->dev.parent = &dev->dev; > - mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor); > + mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor); > mousedev->dev.release = mousedev_free; > device_initialize(&mousedev->dev); > > - if (minor != MOUSEDEV_MIX) { > + if (!mixdev) { > error = input_register_handle(&mousedev->handle); > if (error) > goto err_free_mousedev; > } > > - error = mousedev_install_chrdev(mousedev); > + cdev_init(&mousedev->cdev, &mousedev_fops); > + error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); > if (error) > goto err_unregister_handle; > > @@ -908,10 +905,12 @@ static struct mousedev *mousedev_create(struct input_dev *dev, > err_cleanup_mousedev: > mousedev_cleanup(mousedev); > err_unregister_handle: > - if (minor != MOUSEDEV_MIX) > + if (!mixdev) > input_unregister_handle(&mousedev->handle); > err_free_mousedev: > put_device(&mousedev->dev); > + err_free_minor: > + input_free_minor(minor); > err_out: > return ERR_PTR(error); > } > @@ -920,7 +919,8 @@ static void mousedev_destroy(struct mousedev *mousedev) > { > device_del(&mousedev->dev); > mousedev_cleanup(mousedev); > - if (mousedev->minor != MOUSEDEV_MIX) > + input_free_minor(MINOR(mousedev->dev.devt)); > + if (!mousedev->is_mixdev) > input_unregister_handle(&mousedev->handle); > put_device(&mousedev->dev); > } > @@ -938,7 +938,7 @@ static int mixdev_add_device(struct mousedev *mousedev) > if (retval) > goto out; > > - mousedev->mixdev_open = 1; > + mousedev->mixdev_open = true; > } > > get_device(&mousedev->dev); > @@ -954,7 +954,7 @@ static void mixdev_remove_device(struct mousedev *mousedev) > mutex_lock(&mousedev_mix->mutex); > > if (mousedev->mixdev_open) { > - mousedev->mixdev_open = 0; > + mousedev->mixdev_open = false; > mousedev_close_device(mousedev); > } > > @@ -969,19 +969,9 @@ static int mousedev_connect(struct input_handler *handler, > const struct input_device_id *id) > { > struct mousedev *mousedev; > - int minor; > int error; > > - for (minor = 0; minor < MOUSEDEV_MINORS; minor++) > - if (!mousedev_table[minor]) > - break; > - > - if (minor == MOUSEDEV_MINORS) { > - pr_err("no more free mousedev devices\n"); > - return -ENFILE; > - } > - > - mousedev = mousedev_create(dev, handler, minor); > + mousedev = mousedev_create(dev, handler, false); > if (IS_ERR(mousedev)) > return PTR_ERR(mousedev); > > @@ -1054,27 +1044,59 @@ static const struct input_device_id mousedev_ids[] = { > MODULE_DEVICE_TABLE(input, mousedev_ids); > > static struct input_handler mousedev_handler = { > - .event = mousedev_event, > - .connect = mousedev_connect, > - .disconnect = mousedev_disconnect, > - .fops = &mousedev_fops, > - .minor = MOUSEDEV_MINOR_BASE, > - .name = "mousedev", > - .id_table = mousedev_ids, > + .event = mousedev_event, > + .connect = mousedev_connect, > + .disconnect = mousedev_disconnect, > + .name = "mousedev", > + .id_table = mousedev_ids, > }; > > #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX > +#include <linux/miscdevice.h> > + > static struct miscdevice psaux_mouse = { > - PSMOUSE_MINOR, "psaux", &mousedev_fops > + .minor = PSMOUSE_MINOR, > + .name = "psaux", > + .fops = &mousedev_fops, > }; > -static int psaux_registered; > +static bool psaux_registered; > + > +static void __init mousedev_psaux_register(void) > +{ > + int error; > + > + error = misc_register(&psaux_mouse); > + if (error) > + pr_warn("could not register psaux device, error: %d\n", > + error); > + else > + psaux_registered = true; > + Why that newline here? > +} > + > +static void __exit mousedev_psaux_unregister(void) > +{ > + if (psaux_registered) > + misc_deregister(&psaux_mouse); > +} > + > +#else > + > +static inline void mousedev_psaux_register(void) > +{ > +} > + > +static inline void mousedev_psaux_unregister(void) > +{ > +} > + > #endif > > static int __init mousedev_init(void) > { > int error; > > - mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX); > + mousedev_mix = mousedev_create(NULL, &mousedev_handler, true); > if (IS_ERR(mousedev_mix)) > return PTR_ERR(mousedev_mix); > > @@ -1084,14 +1106,7 @@ static int __init mousedev_init(void) > return error; > } > > -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX > - error = misc_register(&psaux_mouse); > - if (error) > - pr_warn("could not register psaux device, error: %d\n", > - error); > - else > - psaux_registered = 1; > -#endif > + mousedev_psaux_register(); > > pr_info("PS/2 mouse device common for all mice\n"); > > @@ -1100,10 +1115,7 @@ static int __init mousedev_init(void) > > static void __exit mousedev_exit(void) > { > -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX > - if (psaux_registered) > - misc_deregister(&psaux_mouse); > -#endif > + mousedev_psaux_unregister(); > input_unregister_handler(&mousedev_handler); > mousedev_destroy(mousedev_mix); > } > diff --git a/include/linux/input.h b/include/linux/input.h > index 725dcd0..c698e7e 100644 > --- a/include/linux/input.h > +++ b/include/linux/input.h > @@ -1387,9 +1387,6 @@ struct input_handle; > * @start: starts handler for given handle. This function is called by > * input core right after connect() method and also when a process > * that "grabbed" a device releases it > - * @fops: file operations this driver implements > - * @minor: beginning of range of 32 minors for devices this driver > - * can provide > * @name: name of the handler, to be shown in /proc/bus/input/handlers > * @id_table: pointer to a table of input_device_ids this driver can > * handle > @@ -1420,8 +1417,6 @@ struct input_handler { > void (*disconnect)(struct input_handle *handle); > void (*start)(struct input_handle *handle); > > - const struct file_operations *fops; > - int minor; > const char *name; > > const struct input_device_id *id_table; > @@ -1488,6 +1483,10 @@ void input_reset_device(struct input_dev *); > int __must_check input_register_handler(struct input_handler *); > void input_unregister_handler(struct input_handler *); > > +int __must_check input_get_new_minor(int legacy_base, unsigned int legacy_num, > + bool allow_dynamic); > +void input_free_minor(unsigned int minor); > + > int input_handler_for_each_handle(struct input_handler *, void *data, > int (*fn)(struct input_handle *, void *)); > Looks all good and works perfectly well for me. Reviewed-by: David Herrmann <dh.herrmann@googlemail.com> Dmitry, if you push it into linux-next soon, we might even get it into 3.7. And while looking over it, I noticed that it really isn't that much of a functional change. We basically just move the cdev allocation from the core into each handler so we didn't introduce any new races/deadlocks. At least I didn't find one. Thanks again! David ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2012-09-25 8:55 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-09-20 17:52 [PATCH v2 0/3] input: Dynamic Minor Numbers David Herrmann 2012-09-20 17:52 ` [PATCH v2 1/3] input: add dynamic-minor allocation helpers David Herrmann 2012-09-20 17:52 ` [PATCH v2 2/3] input: increase INPUT_DEVICES to 512 to allow dynamic minors David Herrmann 2012-09-20 17:52 ` [PATCH v2 3/3] input: evdev: use dynamic-minors if running out of static minors David Herrmann 2012-09-21 8:07 ` [PATCH v2 0/3] input: Dynamic Minor Numbers Dmitry Torokhov 2012-09-21 9:22 ` David Herrmann 2012-09-21 19:18 ` David Herrmann 2012-09-21 20:51 ` Dmitry Torokhov 2012-09-21 21:32 ` David Herrmann 2012-09-25 8:55 ` David Herrmann
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).