aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Stone <daniel@fooishbar.org>2013-10-31 03:25:34 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-10-31 11:45:42 -0400
commit92eb77d0ffbaa71b501a0a8dabf09a351bf4267f (patch)
tree88ce9406ab92dc2c33d42baf9292dd616874a2ea
parent5df682b297f6b23ec35615ed7bb50cbb25d25869 (diff)
Input: evdev - fall back to vmalloc for client event buffer
evdev always tries to allocate the event buffer for clients using kzalloc rather than vmalloc, presumably to avoid mapping overhead where possible. However, drivers like bcm5974, which claims support for reporting 16 fingers simultaneously, can have an extraordinarily large buffer. The resultant contiguous order-4 allocation attempt fails due to fragmentation, and the device is thus unusable until reboot. Try kzalloc if we can to avoid the mapping overhead, but if that fails, fall back to vzalloc. Signed-off-by: Daniel Stone <daniels@collabora.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--drivers/input/evdev.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b6ded17b3be3..a06e12552886 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -18,6 +18,8 @@
18#include <linux/poll.h> 18#include <linux/poll.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/vmalloc.h>
22#include <linux/mm.h>
21#include <linux/module.h> 23#include <linux/module.h>
22#include <linux/init.h> 24#include <linux/init.h>
23#include <linux/input/mt.h> 25#include <linux/input/mt.h>
@@ -369,7 +371,11 @@ static int evdev_release(struct inode *inode, struct file *file)
369 mutex_unlock(&evdev->mutex); 371 mutex_unlock(&evdev->mutex);
370 372
371 evdev_detach_client(evdev, client); 373 evdev_detach_client(evdev, client);
372 kfree(client); 374
375 if (is_vmalloc_addr(client))
376 vfree(client);
377 else
378 kfree(client);
373 379
374 evdev_close_device(evdev); 380 evdev_close_device(evdev);
375 381
@@ -389,12 +395,14 @@ static int evdev_open(struct inode *inode, struct file *file)
389{ 395{
390 struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); 396 struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev);
391 unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); 397 unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev);
398 unsigned int size = sizeof(struct evdev_client) +
399 bufsize * sizeof(struct input_event);
392 struct evdev_client *client; 400 struct evdev_client *client;
393 int error; 401 int error;
394 402
395 client = kzalloc(sizeof(struct evdev_client) + 403 client = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
396 bufsize * sizeof(struct input_event), 404 if (!client)
397 GFP_KERNEL); 405 client = vzalloc(size);
398 if (!client) 406 if (!client)
399 return -ENOMEM; 407 return -ENOMEM;
400 408