Skip to content

Commit 7f8d4ca

Browse files
committed
Input: extend the number of event (and other) devices
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. Reviewed-by: David Herrmann <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 0124be4 commit 7f8d4ca

File tree

5 files changed

+187
-256
lines changed

5 files changed

+187
-256
lines changed

drivers/input/evdev.c

Lines changed: 33 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,19 @@
2323
#include <linux/input/mt.h>
2424
#include <linux/major.h>
2525
#include <linux/device.h>
26+
#include <linux/cdev.h>
2627
#include "input-compat.h"
2728

2829
struct evdev {
2930
int open;
30-
int minor;
3131
struct input_handle handle;
3232
wait_queue_head_t wait;
3333
struct evdev_client __rcu *grab;
3434
struct list_head client_list;
3535
spinlock_t client_lock; /* protects client_list */
3636
struct mutex mutex;
3737
struct device dev;
38+
struct cdev cdev;
3839
bool exist;
3940
};
4041

@@ -51,9 +52,6 @@ struct evdev_client {
5152
struct input_event buffer[];
5253
};
5354

54-
static struct evdev *evdev_table[EVDEV_MINORS];
55-
static DEFINE_MUTEX(evdev_table_mutex);
56-
5755
static void __pass_event(struct evdev_client *client,
5856
const struct input_event *event)
5957
{
@@ -310,35 +308,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev)
310308

311309
static int evdev_open(struct inode *inode, struct file *file)
312310
{
313-
struct evdev *evdev;
311+
struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
312+
unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
314313
struct evdev_client *client;
315-
int i = iminor(inode) - EVDEV_MINOR_BASE;
316-
unsigned int bufsize;
317314
int error;
318315

319-
if (i >= EVDEV_MINORS)
320-
return -ENODEV;
321-
322-
error = mutex_lock_interruptible(&evdev_table_mutex);
323-
if (error)
324-
return error;
325-
evdev = evdev_table[i];
326-
if (evdev)
327-
get_device(&evdev->dev);
328-
mutex_unlock(&evdev_table_mutex);
329-
330-
if (!evdev)
331-
return -ENODEV;
332-
333-
bufsize = evdev_compute_buffer_size(evdev->handle.dev);
334-
335316
client = kzalloc(sizeof(struct evdev_client) +
336317
bufsize * sizeof(struct input_event),
337318
GFP_KERNEL);
338-
if (!client) {
339-
error = -ENOMEM;
340-
goto err_put_evdev;
341-
}
319+
if (!client)
320+
return -ENOMEM;
342321

343322
client->bufsize = bufsize;
344323
spin_lock_init(&client->buffer_lock);
@@ -352,13 +331,12 @@ static int evdev_open(struct inode *inode, struct file *file)
352331
file->private_data = client;
353332
nonseekable_open(inode, file);
354333

334+
get_device(&evdev->dev);
355335
return 0;
356336

357337
err_free_client:
358338
evdev_detach_client(evdev, client);
359339
kfree(client);
360-
err_put_evdev:
361-
put_device(&evdev->dev);
362340
return error;
363341
}
364342

@@ -942,26 +920,6 @@ static const struct file_operations evdev_fops = {
942920
.llseek = no_llseek,
943921
};
944922

945-
static int evdev_install_chrdev(struct evdev *evdev)
946-
{
947-
/*
948-
* No need to do any locking here as calls to connect and
949-
* disconnect are serialized by the input core
950-
*/
951-
evdev_table[evdev->minor] = evdev;
952-
return 0;
953-
}
954-
955-
static void evdev_remove_chrdev(struct evdev *evdev)
956-
{
957-
/*
958-
* Lock evdev table to prevent race with evdev_open()
959-
*/
960-
mutex_lock(&evdev_table_mutex);
961-
evdev_table[evdev->minor] = NULL;
962-
mutex_unlock(&evdev_table_mutex);
963-
}
964-
965923
/*
966924
* Mark device non-existent. This disables writes, ioctls and
967925
* prevents new users from opening the device. Already posted
@@ -980,7 +938,8 @@ static void evdev_cleanup(struct evdev *evdev)
980938

981939
evdev_mark_dead(evdev);
982940
evdev_hangup(evdev);
983-
evdev_remove_chrdev(evdev);
941+
942+
cdev_del(&evdev->cdev);
984943

985944
/* evdev is marked dead so no one else accesses evdev->open */
986945
if (evdev->open) {
@@ -991,43 +950,47 @@ static void evdev_cleanup(struct evdev *evdev)
991950

992951
/*
993952
* Create new evdev device. Note that input core serializes calls
994-
* to connect and disconnect so we don't need to lock evdev_table here.
953+
* to connect and disconnect.
995954
*/
996955
static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
997956
const struct input_device_id *id)
998957
{
999958
struct evdev *evdev;
1000959
int minor;
960+
int dev_no;
1001961
int error;
1002962

1003-
for (minor = 0; minor < EVDEV_MINORS; minor++)
1004-
if (!evdev_table[minor])
1005-
break;
1006-
1007-
if (minor == EVDEV_MINORS) {
1008-
pr_err("no more free evdev devices\n");
1009-
return -ENFILE;
963+
minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true);
964+
if (minor < 0) {
965+
error = minor;
966+
pr_err("failed to reserve new minor: %d\n", error);
967+
return error;
1010968
}
1011969

1012970
evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL);
1013-
if (!evdev)
1014-
return -ENOMEM;
971+
if (!evdev) {
972+
error = -ENOMEM;
973+
goto err_free_minor;
974+
}
1015975

1016976
INIT_LIST_HEAD(&evdev->client_list);
1017977
spin_lock_init(&evdev->client_lock);
1018978
mutex_init(&evdev->mutex);
1019979
init_waitqueue_head(&evdev->wait);
1020-
1021-
dev_set_name(&evdev->dev, "event%d", minor);
1022980
evdev->exist = true;
1023-
evdev->minor = minor;
981+
982+
dev_no = minor;
983+
/* Normalize device number if it falls into legacy range */
984+
if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS)
985+
dev_no -= EVDEV_MINOR_BASE;
986+
dev_set_name(&evdev->dev, "event%d", dev_no);
1024987

1025988
evdev->handle.dev = input_get_device(dev);
1026989
evdev->handle.name = dev_name(&evdev->dev);
1027990
evdev->handle.handler = handler;
1028991
evdev->handle.private = evdev;
1029992

1030-
evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor);
993+
evdev->dev.devt = MKDEV(INPUT_MAJOR, minor);
1031994
evdev->dev.class = &input_class;
1032995
evdev->dev.parent = &dev->dev;
1033996
evdev->dev.release = evdev_free;
@@ -1037,7 +1000,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
10371000
if (error)
10381001
goto err_free_evdev;
10391002

1040-
error = evdev_install_chrdev(evdev);
1003+
cdev_init(&evdev->cdev, &evdev_fops);
1004+
error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
10411005
if (error)
10421006
goto err_unregister_handle;
10431007

@@ -1053,6 +1017,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
10531017
input_unregister_handle(&evdev->handle);
10541018
err_free_evdev:
10551019
put_device(&evdev->dev);
1020+
err_free_minor:
1021+
input_free_minor(minor);
10561022
return error;
10571023
}
10581024

@@ -1062,6 +1028,7 @@ static void evdev_disconnect(struct input_handle *handle)
10621028

10631029
device_del(&evdev->dev);
10641030
evdev_cleanup(evdev);
1031+
input_free_minor(MINOR(evdev->dev.devt));
10651032
input_unregister_handle(handle);
10661033
put_device(&evdev->dev);
10671034
}
@@ -1078,7 +1045,7 @@ static struct input_handler evdev_handler = {
10781045
.events = evdev_events,
10791046
.connect = evdev_connect,
10801047
.disconnect = evdev_disconnect,
1081-
.fops = &evdev_fops,
1048+
.legacy_minors = true,
10821049
.minor = EVDEV_MINOR_BASE,
10831050
.name = "evdev",
10841051
.id_table = evdev_ids,

0 commit comments

Comments
 (0)