linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).